I would like to write a number in cucumber page. Please let me know How can I write this.
Scenario Outline: Enter an invalid URL
Given the context "Invalid URL" is open on "Market"
When user is on the error 404 page
Then page not found message is displayed
But I have observed that 404 is taken as a parameter.
Sure, you just have to handle it as a regular expression (regex) in your step definitions. Your step definition could read as following:
#When("^When user is on the error \"(\\d+)\" page$")
public void When_user_is_on_the_error_page(int errorNum) throws Throwable {
...
}
That'll handle 1 or more digits. The \d represents a digit and the + sign represents "1 or more".
I personally like wrapping my parameters in double quotes ("") because then the IDE understands it's a parameter and can help you out with autocomplete, etc.
If you want to restrict it to more specific numbers (say only three digits) you can refine your regex to something like [\d]{3}. Oracle have lessons on Java regex here.
With
When user is on the error 404 page
You could use in the steps:
#When("^When user is on the error (.*) page$")
public void When_user_is_on_the_error_page(int errorNum) {
...
}
the (.*) will take whatever is in that slot and use as a variable that will be defined by the type between the (). In this case, the '400' will be converted to a int, thanks to:
(**int** errorNum){ ...}
If you have no practice with regex, it can be really useful since it will make your steps easier to read, since the (.*) doesn't have a pre defined type.
Related
I'm trying to create a more friendly page URL in Kentico with the two letter culture code (en) instead of the full culture code (en-US). I modified the page URL pattern as seen in the image below. Is there a better way of doing this, should I create a custom macro expression?
The other thing I wanted to achieve was having the default culture not in the URL. Maybe I could also use the custom macro expression for it.
I have solved the problem with a custom macro expression. This is used in the URL pattern in combination with the DocumentCulture. The macro expression takes the culture alias name which is in case of the default culture empty and else the two letter code, and returns this with a '/'.
The url pattern for a page:
{%Util.GetUrlCultureCode(DocumentCulture)%}{%NodeAliasPath%}
The macro expression I wrote for fixing this problem is as below.
public class CustomCultureMacroExpression : MacroMethodContainer
{
[MacroMethod(typeof(List<string>), "Returns the url culture code of current document", 1)]
[MacroMethodParam(0, "Culture", typeof(string), "Current culture.")]
public static object GetUrlCultureCode(EvaluationContext context, params object[] parameters)
{
// Branches according to the number of the method's parameters
switch (parameters.Length)
{
case 1:
return GetCultureAliasOfCulture(parameters[0].ToString());
case 2:
// Weird bug causing macro expression in url pattern to have two parameters where the first parameter is null.
return GetCultureAliasOfCulture(parameters[1].ToString());
default:
// No other overloads are supported
return string.Empty;
}
}
private static string GetCultureAliasOfCulture(string cultureCode)
{
var culture = CultureInfoProvider.GetCultureInfo(cultureCode);
var culturealias = culture?.CultureAlias ?? string.Empty;
return string.IsNullOrEmpty(culturealias) ? string.Empty : $"/{culturealias}";
}
}
You may try to update culture codes in Localization -> Cultures, however I'm not sure if it won't have any side effect
If you use the Dynamic Routing module, you can hook into the GetCulture and GetPage global events to do what you are looking for.
For the GetCulture, you would check if the URL has a 2 letter culture code, if it does then use that as the culture.
You can also adjust the GetPage if needed, although the URL slugs generated should work properly, unless you want a fall back that on the GetPage.After, if there is no found page, you can try removing any culture from the URL and looking up the page by that.
I recommended using the NodeAliasPath for the remaining part of the UrlPattern for ease of use.
Does anyone know if cucumber/Java supports the functionality of multiple steps to access the same stepDefinition?
What I am trying to achieve is to use as a Given a step that at the moment is used as a When (in another more complex test where the current When becomes just a precondition)
In my previous experience (Specflow/.Net) I could use something like
[Given(#"the user added a (.*) to the cart")]
[When(#"the user adds a (.*) to the cart")]
public void WhenTheUserAddsATotheCart(string product){
////code that adds to the cart
}
If I use the same methodology as in Specflow, a DuplicateStepDefinitionException is thrown.
Because Cucumber doesn't take the key words (Given, When etc.) into consideration when matching the Steps with the step definitions. Cucumber only looks for a regEx in the step definitions so I would need to have only one step definition (Given OR When). Meaning
[When(#"the user adds a (.*) to the cart")]
will also match
[Given(#"the user adds a (.*) to the cart")]
My problem is that we use the Given at past tense and the When at present tense.
So the question is: how can I use the same implementation for two step definitions?
The only solution I see is to extract the contains of the method that implements the Given into another method and call it under both Given step definition and under When.Something like:
[Given(#"the user added a (.*) to the cart")]
public void GivenTheUserAddedATotheCart(string product){
addToTheCart(product);
}
[When(#"the user adds a (.*) to the cart")]
public void WhenTheUserAddsATotheCart(string product){
addToTheCart(product);
}
public void addToTheCart(String product){
////code that adds to the cart
}
... but I don't really find this a nice solution
I have found multiple discussions around this topic in the cucumber repo but most of them are specific to the cucumber-jvm implementation:
https://github.com/cucumber/cucumber-jvm/issues/957
https://github.com/cucumber/cucumber-jvm/issues/1341
https://github.com/cucumber/cucumber-jvm/issues/895
This is a controversial topic and as I far as I understood no official support for this feature has been implemented but there are some references on how this could be achieved. On the example shown, since the steps are similar I would just extended the regular expression on the step definition to match both steps:
[Given(#"the user add(s|ed) a (.*) to the cart")]
public void WhenTheUserAddsATotheCart(string tense, string product){
////code that adds to the cart
}
Of course, this solution produces an additional parameter on the method which is useless unless you are planning to follow a different path when the step is executed in the past (Given) or in the present (When).
I am very new to Xtext/Xtend, therefore apologies in advance if the answer is obvious.
I would like to allow the end-users of my DSL to define a 'filter', that when applied and 'returns' true it means that they want to 'filter out' the given entity of data from consideration.
I want to allow them 2 ways of defining the filter
A) by introspecting the attributes of a given data object and apply basic rules like
if (obj.field1<CURRENT_DATE && obj.field2=="EXPIRED)
{ return true;} else {return false;}
B) by executing a controlled snippet using 'eval' of my host language
In other words, the user would be expected to type into a string/code block a valid
code snippet of the hosting language
I had decided that the easiest way for me support case A) would be to leverage the XBase rules (including expressions/etc)
Therefore I defined filters (mostly copying the ideas from Lorenzo's book)
Filter:
(FilterDSL | FilterCode);
FilterDSL:
'filterDSL' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
body=XBlockExpression ;
FilterCode:
'filterCode' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
'{'
body=STRING
'}';
Now when trying to implement the Java mapping for my DSL, via the inferrer stub in Xtend -- I am running into multiple problems.
All of them likely indicate that I am missing some fundamental understanding
Problem 1) fl.body is not defined. fl Is of type Filter, not FilterDSL or FilterCode
And I do not understand how to check what type a given instance is of, so that I can access the content of a 'body' feature.
Problem 2) I do not understand where 'body' attribute in the inferrer method is defined and why. Is this part of ECore? (I could not find it)
Problem 3) what's the proper way to allow a user to specify a code block? String seems to be not the right thing as it does not allow multiline
Problem 4) How do I correctly convert a code block into something that is accepted by the 'body' such that it ends up in the generated code.
Problem 5) How do I setup multiple inferrers (as I have more than one thing for which I need the code generated (mostly) by xBase code generator)
Appreciate in advance any suggestions, or pointer to code examples solving similar problems.
As a side observation, Inferrer and its interplay with XBase has sofar been the most confusing and difficult thing to understand.
in general: have a look at the xtend docs at xtend-lang.org
You can do a if (x instanceof Type) or a switch statement with Type guards (see domain model example)
i dont get that question. both your FilterDSL and FilterCode EClasses should have a field+getter/setter named body, FilterCode of type String, FilterDSL of type XBlockExpression. The JvmTypesBuilder add extension methods to JvmOperation called setBody(String) and setBody(XExpression), syntax sugar lets you call body = .... instead of setBody(...)
(btw you can do crtl+click to find out where a thing is defined)
strings are actually multiline
is answered by (2)
you dont need multiple inferrers, you can infer multiple stuff e.g. by calling toClass or toField multiple times for the same input
This question is with reference to the Cymbol code from the book (~ page 143) :
int t = ctx.type().start.getType(); // in DefPhase.enterFunctionDecl()
Symbol.Type type = CheckSymbols.getType(t);
What does each component return: "ctx.type()", "start", "getType()" ? The book does not contain any explanation about these names.
I can "kind of" understand that "ctx.type()" refers to the "type" rule, and "getType()" returns the number associated with it. But what exactly does the "start" do?
Also, to generalize this question: what is the mechanism to get the value/structure returned by a rule - especially in the context of usage in a listener?
I can see that for an ID, it is:
String name = ctx.ID().getText();
And as in above, for an enumeration of keywords it is via "start.getType()". Any other special kinds of access that I should be aware of?
Lets disassemble problem step by step. Obviously, ctx is instance of CymbolParser.FunctionDeclContext. On page 98-99 you can see how grammar and ParseTree are implemented (at least the feeling - for real implementation please see th .g4 file).
Take a look at the figure of AST on page 99 - you can see that node FunctionDeclContext has a several children, one labeled type. Intuitively you see that it somehow correspond with function return-type. This is the node you retrieve when calling CymbolParser.FunctionDeclContext::type. The return type is probably sth like TypeContext.
Note that methods without 'get' at the beginning are usually children-getters - e.g. you can access the block by calling CymbolParser.FunctionDeclContext::block.
So you got the type context of the method you got passed. You can call either begin or end on any context to get first of last Token defining the context. Simply start gets you "the first word". In this case, the first Token is of course the function return-type itsef, e.g. int.
And the last call - Token::getType returns integral representation of Token.
You can find more information at API reference webpages - Context, Token. But the best way of understanding the behavior is reading through the generated ANTLR classes such as <GrammarName>Parser etc. And to be complete, I attach a link to the book.
I have a legacy database that has column names like "void". I also have several Microsoft SSIS log databases. those have column names like "event" and "operator". It looks like we need to set the CleanName on the column early on in Settings.ttinclude template, but I am not quite sure the best way to tackle this since the list of reserved words might get long. Should this be a separate include? I'd be happy to contribute, but I'd like some design input from you smart people first.
Reserved words in c# can be handled in code by prepending them with the '#' symbol. For example,
public void Test(int if)
{
}
fails with a compiler error, but
public void Test(int #if)
{
var something = #if;
}
is just fine. This works for property names as well. You could probably upgrade your T4 templates to check a list of reserved words, and if there is a match, prepend the '#' symbol in front of the name.
As to the best way of adding this into Subsonic, I'd have to do more digging.