Use random var in behat tests to produce unique usernames - behat

Right now I am creating users using something like the following
Given users:
| name | status | roles |
| kyle | 1 | authenticated user |
| cartman | 1 | admin |
Is there a possibility to add random strings in these names?

If I didn't misunderstand, you can do this instead.
Gherkin
Scenario: Create random users
Given I create "3" users
FeatureContext
var $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var $status = [0, 1];
var $roles = ['authenticated user', 'admin', 'superman'];
/**
* #Given /^I create "([^"]*)" users$/
*/
public function createDummyUsers($count)
{
for ($i = 0; $i < $count; $i++) {
$name = substr(str_shuffle($this->str), 0, 8);
$status = $this->status[array_rand($this->status, 1)];
$role = $this->roles[array_rand($this->roles, 1)];
echo "You've just created $name - $status -$role" . PHP_EOL;
}
}
Prints
You've just created mqBWAQJK - 1 - superman
You've just created WYuAZSco - 0 - admin
You've just created HCNWvVth - 1 - admin
You've just created EmLkVRpO - 1 -superman
You've just created pxWcsuPl - 1 -authenticated user
You've just created mLYrlKdz - 0 -superman

The RandomContext functionality from drupal/drupal-extension allows for usage like this:
Given I fill in "E-mail address" with "<?username>#example.org"
or
Given users:
| name | email | status | roles |
| <?standard> | <?standard>#example.org | 1 | authenticated |
| <?admin> | <?admin>#example.org | 1 | admin |
Each token (eg <?username>, <?firstname>) used in a feature will be randomly transformed with a (random string) value for that feature execution. This is implemented with the use of Behat's #Transform functionality, meaning that your tokens will be substituted before execution of that step - so it works to generate random inputs anywhere you might need to use random input as part of your feature.
You can reference the same token later in your feature, eg to verify that the random value input earlier has been returned correctly, and the randomly generated value will be recalled. So, the first and second usages of <?admin> in the example above will both be replaced by the same generated value.
If you are using drupal/drupal-extension then this can be enabled by adding Drupal\DrupalExtension\Context\RandomContext to the enabled contexts in your behat.yml.
If you aren't using Drupal, then the source linked above will demonstrate how you could implement the same for your own usage.

I've created a solution on that you can try.
https://github.com/JordiGiros/MinkFieldRandomizer
MinkFieldRandomizer is a random (with sense) information generator for filling browser form fields in Behat Mink Selenium tests. It brings the option to run your tests in a more realistic way changing the information you use to fill in the forms in every test you run.
You can easily add it to your project by Composer.
One example:
Then Fills in form fields with provided table
| "f_outbound_accommodation_name" | "{RandomName(10)}" |
| "f_outbound_accommodation_phone_number" | "{RandomPhone(9)}" |
| "f_outbound_accommodation_address_1" | "{RandomText(10)}" |
I hope you try it!
And you're welcome to add new functionalities or fork it or do wathever you want.
Cheers

Related

I want to run Scenario Outline in loop for one of the variable configurable

I have use case in which I am making server name configurable using Scenario outline for get call. But I also want to make another variable like ID configurable. I want using that id it should run for all server name mentioned in Scenario Outline. How can we achieve that?
Example
Scenario Outline: Test one get call
Given url: 'https://' + server+ 'v1/share/12345/profit'
When method get
Then status 200
Examples:
|server|
|server1|
|server2|
|server3|
|server4|
In above example server name, I made it configurable using scenario outline, but I want to make number entered in URL configurable & want that to run for all servers. How I will achieve that?
Just use another variable.
Examples:
| server | id |
| foo | 1 |
| foo | 2 |
| bar | 1 |
| bar | 2 |
And if you want to dynamically generate data using a function, all that is possible. Refer: https://github.com/karatelabs/karate#json-function-data-source

KQL - return entries not matching IP from watchlist (query optimization)

I want to receive a high severity alert in Sentinel when a user is added to a defined "high severity" group (via watchlist), however, I want to omit any users that are connected to a Zscaler IP address. The query below is working, however, I'm not sure this is the neatest/most optimized logic. Is there a shorter/better way to write this?
I'm only concerned about the lines beginning with asterisks (which are only added for clarity).
watchlist "aadgroups"
Group
Severity
Prod Owners
High
Prod Contributors
High
watchlist "ZSIPs"
zscaler_ip
location
165.225.0.0/23
Chicago
165.225.60.0/22
Chicago
165.225.56.0/22
Chicago
let HighSeverityGroups = (_GetWatchlist('aadgroups') | where severity == "High" | project group_name, severity);
let ZSIPs = (_GetWatchlist('zscaler_ip') | project zscaler_ip);
AuditLogs
| where ActivityDisplayName == "Add member to group"
| where parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].newValue)) has_any (HighSeverityGroups)
| extend InitiatedByActor = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend GroupName = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].newValue)))
| extend Actor_ipv4 = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
| extend TargetUser = tostring(TargetResources[0].userPrincipalName)
| project-reorder TimeGenerated,SourceSystem,InitiatedBy,ActivityDisplayName,TargetUser,GroupName,InitiatedByActor,Actor_ipv4,Result
| where TargetUser <> ""
** | evaluate ipv4_lookup(ZSIPs, Actor_ipv4, zscaler_ip, return_unmatched = true)
** | where isempty(zscaler_ip)
A couple of things you can try to optimize the query:
This filter is quite costly: | where parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].newValue)) has_any (HighSeverityGroups) - if TargetResources will rarely have strings from HighSeverityGroups, then before this filter, you can add a much more efficient filter, that will filter out most of the records: | where TargetResources has_any (HighSeverityGroups) - this way, the heavy parsing will be done only on a small amount of records
You're parsing some of the data more than once, for example tostring(parse_json(tostring(InitiatedBy.user)) - instead, you need to use the extend operator to parse them only once, and then use later on in the query

How can i create a Laravel API to show ads added by admin based on impression count of users?

I've an admin side in my laravel project where admin can add Ads along with impression and hours. For e.g if i add a add with impression = 2 and hours = 2. So, once the user have viewed this ad for 2 times then user will not be shown that Ad for the next 2 hours.
Here is the structure of admin ads table:
--------------------------------------
id | image |impressions| hours |
1 | image.png| 2 | 6 |
--------------------------------------
And there's ads_impression_log where i store the log of users who have viewed an ad
---------------------------------------------
id | user_id | ad_id | impression_datetime |
1 | 1 | 1 | 2020-07-28 23:22:45 |
---------------------------------------------
How can i create a laravel query so, that i get specific ad impression count and if impression count is within the hours show the user next ad.
This is my first question here. So, please ignore if there's some mistake :)
Ad Model
public function users(){
return $this->belongsToMany(App\Add, 'ads_impression_log', 'ad_id', 'user_id')
->withPivot('impression_datetime');
}
User Model
public function ads(){
return $this->belongsToMany(App\Add, 'ads_impression_log', , 'user_id', 'ad_id')
->withPivot('impression_datetime');
}
Impression count of a given user($user_id) for a given ad.($user_id)
We'll use the collection method filter here.
$user = User::with('ads')->find($user_id);
//
$ads = $user->ads->filter(function($value, $key){
return $value->id === $ad_id;
});
Now you can get the count of those impressions.
$count = $ads->count();
Impressions required for that ad.
$ads->first()->impression;
You can do the comparison accordingly.
And to get the impression_date column from the pivot table you could do the following.
foreach($ads as $adImp){
$adImp->pivot->impression_date;
}

how to dynamically set an value in json read from file in Karate

I want to dynamically set value for some elements in JSON(read from a file) using data driven feature of KARATE framework. Here are more details:
request.json -> { wheels : <wheel>, color: '<color>' }
Feature: Read json input from file and iterate over data table values
Background:
* url ''
* def reqJson = read('request.json')
* print reqJson
Scenario Outline: Test file read
# I want to avoid writing below set statements for each element in request
#* set reqJson.wheels = <wheel>
#* set reqJson.color = '<color>'
Given path ''
And request reqJson
When method POST
Then status 200
And match response contains {mode: '<result>'}
Examples:
| wheel | color | result |
| 4 | red | car |
| 2 | any | bicycle |
I am developing automation framework using Karate, my intention is to save sample request in JSON file for a given API and then during execution I want element values to be replaced with the ones given in the table above.I don't want to write set statement for each element either(commented lines above)
P.S.: I tried with calling other feature file using table approach. However, I want to keep one feature file per API, hence want to know if there is any way possible for the above approach
I think you have missed embedded expressions which is simpler than the set keyword in many cases, especially when reading from files.
For example:
request.json -> { wheels : '#(wheels)', color: '#(color)' }
And then this would work:
* def wheels = 4
* def color = 'blue'
* def reqJson = read('request.json')
* match reqJson == { wheels: 4, color: 'blue' }
If you go through the demo examples you will get plenty of other ideas. For example:
* table rows
| wheels | color | result |
| 4 | 'blue' | 'car' |
| 2 | 'red' | 'bike' |
* call read('make-request.feature') rows
And where make-request.feature is:
Given path ''
And request { wheels: '#(wheels)', color: '#(color)' }
When method POST
Then status 200
And match response contains { mode: '#(result)' }

Parameterizing with examples keyword in specflow issue

Working with parameterizing through examples keyword in specflow creating an issue.
Following is my scenario and code to insert password in the Field:
Scenario Outline: Register Successfully
Given I am shown the Registration view
When I enter ComapnyName in the <CompanyName> field
And I enter UserName in the <UserName> field
And I enter Email in the <Email> field
And I enter Password in the <Password> field
And I enter ConfirmPassword in the <ConfirmPassword> field
And I choose to register my account
Then my user account is created
And I am navigated to my company dashboard
Examples:
| CompanyName | UserName | Email | Password | ConfirmPassword |
| XYZ | Salman Haider | salman.haider#gmail.com | FooBar#123 | FooBar#123 |
public void Password(string password, int n)
{
//Getting and Setting up the values in the Password Field
var passwords = Helper.Driver.FindElements(By.XPath(".//*[#name='password']")).ToList();
passwords[n].SendKeys(password);
Thread.Sleep(2000);
}
When it enters the password in the field and clicks on submit button shows a validation error that password should be 8 characters long,one capital and a special character required besides the password is all correct. However same code works working with parameterizing with table.
Scenario: Register Successfully
Given I am shown the Registration view
When I enter credientials
| CompanyName | UserName | Email | Password | ConfirmPassword |
| Seven | Mobeen | usama.rafiq#gmail.com | FooBar#123 | FooBar#123 |
And I choose to register my account
Then my user account is created
And I am navigated to my company dashboard
. But I need former method to work as I have multiple test data to enter.