I am writing a test automation step-defintion using Cucumber and WebdriverJS. I have the following feature file
Scenario Outline : Validate whatever in this scenario works
Given I have a <Service Method> for test store
Then validate that something exists
Example :
|Service Method|
|Carryout |
|Delivery |
|Dine-in |
I'm mapping this cucumber step to the following auto-generated step-definition file
this.Given(/^I have a (.*) order$/, function (serviceMethod) {}
In this situation, I want this function to process only if the cucumber parameter is one of (carryout|delivery|dine-in).
I tried to limit the capture group by trying the following regex but the cucumber step-definition is not mapping to nodeJS step-definition after this.
this.Given(/^I have a (.*) (carryout|delivery|dine-in)? order$/, function (serviceMethod) {}
How can this be resolved ? Any help is highly appreciated
If you require one of those types of orders, you can speed things up by asserting it exists,
then laying down the blazay form of the container.
/^(?=.* (carryout|delivery|dine-in) )I have a.*order$/
Group 1 contains the TYPE of the order.
this.Given(/^I have a (carryout|delivery|dine-in) order$/, function (serviceMethod) {}
The above step-definition finally worked for me.
Related
Have a requirement where before running the feature "abfeatureTest1" few initial data setup required for validation needs to be created through UI and is available in method "beforeFeatureTest1".
I need to execute the method "beforeFeatureTest1" only once before running the feature "abfeatureTest1" and discard the data after feature execution.
I am aware of After/Before all hooks and After/Before scenario hooks, But i need something like After/Before feature hook.
Any suggestions on how this can be achieved?
Thanks.
For Cypress-Cucumber, following hooks will run before and after each feature file but not after each scenario
before(()=>{
cy.log('======before=====')
})
after(()=>{
cy.log('======after=====')
cy.wait(5000)
})
You can have tags at FeatureFile level and at Scenario level.
So #FeatureFile3 tag will run all the cases in your FeatureFile3
and #FF1scenario2 tag will run only particular scenario
You can specify these tags in your runner class for execution as per your requirement.
#CucumberOptions(features= "src/main/resources/publish", tags="#FeatureFile3", format = {"pretty"} )
I'm trying to write a step that will match the following steps that are similar and capture parameters:
Step1: And I delete the filter(s) using the "UI"
Step2: Then I delete the filter(s) using the "API" for "doc-browser" context
Step3: I delete the filter(s) using the "API" for "doc-browser" context with user "file_user2"
I don't want to create 3 separate steps, they all start with I delete the filter using the #{arg} and the last 2 just extend on that.
I thought this was going to accomplish it:
And(/^I delete the filter\(s\) using the "([^"]*)"(?: for "([^"]*)" context| with user "([^"]*)")?/) do |delete_method, context, user|
case delete_method
when 'API'
if user.nil?
SearchFilters.new.delete_global_local_filters(delete_method, api_context_val: context)
else
SearchFilters.new.delete_global_local_filters(delete_method, { api_context_val: context, username: user })
end
when 'UI'
SearchFilters.new.delete_global_local_filters(delete_method, filter_name: #filter_name)
end
end
However, I'm not capturing my username.
Is it possible to accomplish having one step definition that captures all 3 variations and still captures my arguments?
Just duplicating my mailing list answer in case anyone else is interested in this question.
I understand you don't want to use three different steps, but in this case you really should because
The implementation of each step is a clear one liner, so you are removing a case statement.
The regex for this step is horrible and you will be removing that
Each individual step provides the opportunity to simplify the parameters being passed, you have 2 API and one UI paramter which can just be removed entirely (if I understand the code correctly you can remove all the params and regexs)
This is a clear case where a little bit of repetition is a price well worth paying for a simpler implementation.
Reducing the number of step definitions by using regex's and params is often an anti-pattern.
All best
Andrew
I have an array of usernames (eg. ['abc','def','ghi']) to be added under 'user' label in the graph.
Now I first want to check if the username already exists (g.V().hasLabel('user').has('username','def')) and then add only those for which the username property doesn't match under 'user' label.
Also, can this be done in a single gremlin query or groovy script?
I am using titan graph database, tinkerpop3 and gremlin REST server.
With "scripts" you can always pass a multi-line/command script to the server for processing to get what you want done. This question is then answered with normal programming techniques using variables, if/then statements, etc:
t = g.V().has('person','name','bill')
t.hasNext() ? t.next() : g.addV('person').property('name','bill').next()
or perhaps:
g.V().has('person','name','bill').tryNext().orElseGet{
g.addV('person').property('name','bill').next()}
But these are groovy scripts and ultimately TinkerPop recommends avoiding scripts and closures in favor of a pure traversal. The general way to handle a "get or create" in a single traversal is to do something like this:
gremlin> g.V().has('person','name','bill').fold().
......1> coalesce(unfold(),
......2> addV('person').property('name','bill'))
==>v[18]
Also see this StackOverflow question for more information on upsert/"get or create" patterns.
You can do it directly using :
g.V().has('user','username','def').fold().coalesce(unfold(),addV('user').property('username','def'))
Just adding into this answer. It is better to use the following idempotent query. Coalesce works like an if-else statement. Refer to, https://spin.atomicobject.com/2021/08/10/idempotent-queries-in-gremlin/ for more information. Also, if you are noticing that the entry is not being saved, make sure you commit the changes using .next().
g.V().hasLabel('user').has('username','def')
.fold()
.coalesce(
__.unfold(),
__.addV('user').property('username','def')
)
.next()
I'm writing a REST api in node js that will execute a sql query and send the results;
in the request I need to send the WHERE conditions; ex:
GET 127.0.0.1:5007/users //gets the list of users
GET 127.0.0.1:5007/users
id = 1 //gets the user with id 1
Right now the conditions are passed from the client to the rest api in the request's headers.
In the API I'm using sequelize, an ORM that needs to receive WHERE conditions in a particular form (an object); ex: having the condition:
(x=1 AND (y=2 OR z=3)) OR (x=3 AND y=1)
this needs to be formatted as a nested object:
-- x=1
-- AND -| -- y=2
| -- OR ----|
| -- z=3
-- OR -|
|
| -- x=3
-- AND -|
-- y=1
so the object would be:
Sequelize.or (
Sequelize.and (
{x=1},
Sequelize.or(
{y=2},
{z=3}
)
),
Sequelize.and (
{x=3},
{y=1}
)
)
Now I'm trying to pass a simple string (like "(x=1 AND (y=2 OR z=3)) OR (x=3 AND y=1)"), but then I will need a function on the server that can convert the string in the needed object (this method in my opinion has the advantage that the developer writing the client, can pass the where conditions in a simple way, like using sql, and this method is also indipendent from the used ORM, with no need to change the client if we need to change the server or use a different ORM);
The function to read and convert the conditions' string into an object is giving me headache (I'm trying to write one without success, so if you have some examples about how to do something like this...)
What I would like to get is a route capable of executing almost any kind of sql query and give the results:
now I have a different route for everything:
127.0.0.1:5007/users //to get all users
127.0.0.1:5007/users/1 //to get a single user
127.0.0.1:5007/lastusers //to get user registered in the last month
and so on for the other tables i need to query (one route for every kind of request I need in the client);
instead I would like to have only one route, something like:
127.0.0.1:5007/request
(when calling this route I will pass the table name and the conditions' string)
Do you think this solution would be a good solution or you generally use other ways to handle this kind of things?
Do you have any idea on how to write a function to convert the conditions' string into the desired object?
Any suggestion would be appreciated ;)
I would strongly advise you not to expose any part of your database model to your clients. Doing so means you can't change anything you expose without the risk of breaking the clients. One suggestion as far as what you've supplied is that you can and should use query parameters to cut down on the number of endpoints you've got.
GET /users //to get all users
GET /users?registeredInPastDays=30 //to get user registered in the last month
GET /users/1 //to get a single user
Obviously "registeredInPastDays" should be renamed to something less clumsy .. it's just an example.
As far as the conditions string, there ought to be plenty of parsers available online. The grammar looks very straightforward.
IMHO the main disadvantage of your solution is that you are creating just another API for quering data. Why create sthm from scratch if it is already created? You should use existing mature query API and focus on your business logic rather then inventing sthm new.
For example, you can take query syntax from Odata. Many people have been developing that standard for a long time. They have already considered different use cases and obstacles for query API.
Resources are located with a URI. You can use or mix three ways to address them:
Hierarchically with a sequence of path segments:
/users/john/posts/4711
Non hierarchically with query parameters:
/users/john/posts?minVotes=10&minViews=1000&tags=java
With matrix parameters which affect only one path segment:
/users;country=ukraine/posts
This is normally sufficient enough but it has limitations like the maximum length. In your case a problem is that you can't easily describe and and or conjunctions with query parameters. But you can use a custom or standard query syntax. For instance if you want to find all cars or vehicles from Ford except the Capri with a price between $10000 and $20000 Google uses the search parameter
q=cars+OR+vehicles+%22ford%22+-capri+%2410000..%2420000
(the %22 is a escaped ", the %24 a escaped $).
If this does not work for your case and you want to pass data outside of the URI the format is just a matter of your taste. Adding a custom header like X-Filter may be a valid approach. I would tend to use a POST. Although you just want to query data this is still RESTful if you treat your request as the creation of a search result resource:
POST /search HTTP/1.1
your query-data
Your server should return the newly created resource in the Location header:
HTTP/1.1 201 Created
Location: /search/3
The result can still be cached and you can bookmark it or send the link. The downside is that you need an additional POST.
I have a scenario to validate 100 employee names, The QueryString will return them in xml format.All I want to do is to validate all the employee names in an Assertion statement like given below. Instead of adding each name in the Scenario Outline Example, Is it possible to send a list of 100 employee names as input so that I can Iterate through them in java and could easily validate in Assertion condition. Please advice.
Scenario Outline: When the User queries for employee information, the correct records are returned
Given the webservice is running
When the User queries for employee information "<QueryString>"
Then the User receives correct data "<Name>"
Examples:
|QueryString|Name|
|Some localhost url|Peter|
|Some localhost url|Sam|
.
.
#Then("^the User receives correct data\"([^\"]*)\"$")
public void the_user_receives_correct_data(String arg1) throws Throwable {
queryResultPage = selenium.getPageSource();
assertTrue(queryResultPage.contains(arg1));
}
so i will answere here to LINGS comment
What you can do, is use these filenames in your step definition to load the files in your code. Cucumber doesnt support direct file loading as far as i know.
i use something like this to locate full ressource pathes for my relative path file names:
public static String getAbsoluteResourcePath(String resourcePath) {
if (SystemUtils.IS_OS_WINDOWS) {
return Utils.class.getResource(resourcePath).getPath().substring(1).replace("/", File.separator);
} else {
return Utils.class.getResource(resourcePath).getPath().replace("/", File.separator);
}
}
The resourcePath should then be your relative file path
What you are looking for is external test data support, which is supported with QAF. You can use any inbuilt data provider with interceptor to modify data set or custom data provider.
If you are using cucumber version 5+ you can use qaf-cucumber that will give you all qaf features with cucumber. For lower version you can run your existing feature files with QAF runner.