I currently have a problem with Java and Cucumber. Accessing a website's element by using Selenium, I want to use phrases like the following:
Then the value of the attribute XYZ should be 1000
That example is quite trivial and works fine for each attribute name by using the Java annotation
#Then("the value of the attribute (.*) should be (.*)")
except for the following use-case: an attribute name contains parentheses like ABC(s).
While using Eclipse and JUnit, a Cucumber test with a string containing parentheses like that is not even recognized completely but just the part of the string before the opening bracket. Any ideas or solutions?
It doesn't matter whether the attribute name contains any parentheses.
When using this method:
#Then("^the value of the attribute (.*) should be (.*)$")
public void checkAttributeValue(String name, String value)
throws Throwable {
System.out.println("Name: " + name + " value: " + value);
}
And
Then the value of the attribute XYZ(s) should be 1000
I get
Name: XYZ(s) value: 1000
Which I think is what you expect.
Related
I'm trying to locate elements dynamically usign the xpath. However, when I use variable in the xpath, elements are NOT located. However, if I use hardcoded value, elements are located properly.
What am I missing here?
Below xpath locates the elements perfectly:
driver.findElements(By.xpath("//XCUIElementTypeStaticText[contains(#value, 'hp')]"));
whereas, below xpath doesn't locate the elements:
driver.findElements(By.xpath("//XCUIElementTypeStaticText[contains(#value, '" + device + "')]"));
Please note that , there are multiple elements matching the above xpath.
I even tried below code but of no use:
driver.findElements(By.XPath(String.Format("//XCUIElementTypeStaticText[contains(#value, '{0}')]", device)));
Any help would be appreciated.
Try do debug this issue as following:
Define the XPath string before calling driver.findElements method, format the string to have the proper value and then pass it into Selenium method, as following:
String xpathLocator = "//XCUIElementTypeStaticText[contains(#value, '%s')]";
xpathLocator = String.format(xpathLocator, device);
driver.findElements(By.xpath(xpathLocator));
As about your existing code.
Here driver.findElements(By.xpath("//XCUIElementTypeStaticText[contains(#value, '" + device + "')]"));
I can't see the formatting action.
And here driver.FindElements(By.XPath(string.Format("//XCUIElementTypeStaticText[contains(#value, '{0}')]", device)));
it seems to be a wrong syntax.
It should be String.format while you wrote string.Format
Try trimming the spaces as:
driver.findElements(By.xpath("//XCUIElementTypeStaticText[contains(#value, '"+device+"')]"));
Or using String.format() as:
String device = "hp";
driver.findElements(By.xpath(String.format("//XCUIElementTypeStaticText[contains(#value, '%s')]", device)));
Note:
Instead of FindElements() it should be findElements()
Instead of String.Format() it should be String.format()
The issue was with the case mismatch in the value returned by variable. i.e; device variable was returning 'hP' instead of 'hp'.
Corrected the code and it works fine now.
Input -
String ipXmlString = "<root>"
+ "<accntNoGrp><accntNo>1234567</accntNo></accntNoGrp>"
+ "<accntNoGrp><accntNo>6663823</accntNo></accntNoGrp>"
+ "</root>";
Tried follwing things using to mask values within using
String op = ipXmlString .replaceAll("<accntNo>(.+?)</accntNo>", "######");
But above code masks all the values
<root><accntNoGrp>######</accntNoGrp><accntNoGrp>######</accntNoGrp></root>
Expected Output:
<root><accntNoGrp><accntNo>#####67</accntNo></accntNoGrp><accntNoGrp><accntNo>#####23</accntNo></accntNoGrp></root>
How to achieve this using java regex ?Could someone help
Your replacement is wrong, you need to include the <accntNo> tag in the actual replacement. Also, it appears that you want to show the last two characters/numbers of the account number. In this case, we can capture this information during the match and use it in the replacement.
Code:
String op = ipXmlString.replaceAll("<accntNo>(?:.+?)(.{2})</accntNo>", "<accntNo>######$1</accntNo>");
Explanation:
<accntNo> match an opening tag
(?:.+?) match, but do not capture, anything up until the first
(.{2}) two characters before closing tag (and capture this)
</accntNo> match a closing tag
Note here that by using ?: inside a parenthesis in the pattern, we tell the regex engine to not capture it. There is no point in capturing anything before the last two characters of the account number because we don't want to us it.
The $1 quantity in the replacement refers to the first capture group. In this case, it is the last two characters of the account number. Hence, we build the replacement string you want this way.
Demo here:
Rextester
Try this code:
public static void main(String[] args) {
String ipXmlString = "<root>"
+ "<accntNoGrp><accntNo>1234567</accntNo></accntNoGrp>"
+ "<accntNoGrp><accntNo>6663823</accntNo></accntNoGrp>"
+ "</root>";
String replaceAll = ipXmlString.replaceAll("\\d+", "######");
System.out.println(replaceAll);
}
Prints:
<root><accntNoGrp><accntNo>######</accntNo></accntNoGrp><accntNoGrp><accntNo>######</accntNo></accntNoGrp></root>
Does Java have a built-in way to escape arbitrary text so that it can be included in a regular expression? For example, if my users enter "$5", I'd like to match that exactly rather than a "5" after the end of input.
Since Java 1.5, yes:
Pattern.quote("$5");
Difference between Pattern.quote and Matcher.quoteReplacement was not clear to me before I saw following example
s.replaceFirst(Pattern.quote("text to replace"),
Matcher.quoteReplacement("replacement text"));
It may be too late to respond, but you can also use Pattern.LITERAL, which would ignore all special characters while formatting:
Pattern.compile(textToFormat, Pattern.LITERAL);
I think what you're after is \Q$5\E. Also see Pattern.quote(s) introduced in Java5.
See Pattern javadoc for details.
First off, if
you use replaceAll()
you DON'T use Matcher.quoteReplacement()
the text to be substituted in includes a $1
it won't put a 1 at the end. It will look at the search regex for the first matching group and sub THAT in. That's what $1, $2 or $3 means in the replacement text: matching groups from the search pattern.
I frequently plug long strings of text into .properties files, then generate email subjects and bodies from those. Indeed, this appears to be the default way to do i18n in Spring Framework. I put XML tags, as placeholders, into the strings and I use replaceAll() to replace the XML tags with the values at runtime.
I ran into an issue where a user input a dollars-and-cents figure, with a dollar sign. replaceAll() choked on it, with the following showing up in a stracktrace:
java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)
In this case, the user had entered "$3" somewhere in their input and replaceAll() went looking in the search regex for the third matching group, didn't find one, and puked.
Given:
// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input
replacing
msg = msg.replaceAll("<userInput \\/>", userInput);
with
msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));
solved the problem. The user could put in any kind of characters, including dollar signs, without issue. It behaved exactly the way you would expect.
To have protected pattern you may replace all symbols with "\\\\", except digits and letters. And after that you can put in that protected pattern your special symbols to make this pattern working not like stupid quoted text, but really like a patten, but your own. Without user special symbols.
public class Test {
public static void main(String[] args) {
String str = "y z (111)";
String p1 = "x x (111)";
String p2 = ".* .* \\(111\\)";
p1 = escapeRE(p1);
p1 = p1.replace("x", ".*");
System.out.println( p1 + "-->" + str.matches(p1) );
//.*\ .*\ \(111\)-->true
System.out.println( p2 + "-->" + str.matches(p2) );
//.* .* \(111\)-->true
}
public static String escapeRE(String str) {
//Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
//return escaper.matcher(str).replaceAll("\\\\$1");
return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
}
}
Pattern.quote("blabla") works nicely.
The Pattern.quote() works nicely. It encloses the sentence with the characters "\Q" and "\E", and if it does escape "\Q" and "\E".
However, if you need to do a real regular expression escaping(or custom escaping), you can use this code:
String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
This method returns: Some/\s/wText*/\,**
Code for example and tests:
String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
^(Negation) symbol is used to match something that is not in the character group.
This is the link to Regular Expressions
Here is the image info about negation:
I am trying to extract data out of a website access log as part of a java program. Every entry in the log has a url. I have successfully extracted the url out of each record.
Within the url, there is a parameter that I want to capture so that I can use it to query a database. Unfortunately, it doesn't seem that the web developers used any one standard to write the parameter's name.
The parameter is usually called "course_id", but I have also seen "courseId", "course%3DId", "course%253Did", etc. The format for the parameter name and value is usually course_id=_22222_1, where the number I want is between the "_" and "_1". (The value is always the same, even if the parameter name varies.)
So, my idea was to use the regex /^.*course_id[^_]*_(\d*)_1.*$/i to find and extract the number.
In java, my code is
java.util.regex.Pattern courseIDPattern = java.util.regex.Pattern.compile(".*course[^i]*id[^_]*_(\\d*)_1.*", java.util.regex.Pattern.CASE_INSENSITIVE);
java.util.regex.Matcher courseIDMatcher = courseIDPattern.matcher(_url);
_courseID = "";
if(courseIDMatcher.matches())
{
_courseID = retrieveCourseID(courseIDMatcher.group(1));
return;
}
This works for a lot of the records. However, some records do not record the course_id, even though the parameter is in the url. One such example is the record:
/webapps/contentDetail?course_id=_223629_1&content_id=_3641164_1&rich_content_level=RICH&language=en_US&v=1&ver=4.1.2
However, I used notepad++ to do a regex replace on this (in fact, every) url using the regex above, and the url was successfully replaced by the course ID, implying that the regex is not incorrect.
Am I doing something wrong in the java code, or is the java matcher broken?
A website displays the following text I need to assert:
Living Place "123" hasn't been found
I have a piece of ghurkin/cucumber on a webpage I need to assert.assertTrue using Selenum Webdriver Java:
The text "Living Place "123" hasn't been found" is present on the page
The java Code I've written for this, is as follows:
#Then("^The Text \"([^\"]*)\" isnt present on the page$")
public void not_present(String text) throws Throwable {
waitForTextInElementVisible(By.id("main-content"), text);
Assert.assertTrue(driver.findElement(By.id("main-content")).getText().contains(text));
}
The problem is, the Gherkin script can't handle the String this way, as it contains a double quote. Is there a way to assert the exact string as given above?
I am not sure if I get your problem fully.
But you can pass the string as "Living Place \"123\" hasn't been found".
[Note \ before " inside string]
You can call like follows.
not_present("Living Place \"123\" hasn't been found");
try this one #Then("^The Text \"([^\"]*)\"\d+\"([^\"]*)\" isnt present on the page$"). This step mapping will be mapped to string in feature file Then The Text "Living Place "123" hasn't been found" isnt present on the page. This substitutes the text before digits \"([^\"]*)\" i.e. 'Living Place ', this searches more then one digit symbol in quotation marks \"\d+\" i.e 123, and again part to match text.
Apparently, instead of using
\"([^\"]*)\",
I had to use \"(.*)\"
this will make the gherkin script work:
And The text "Living Place "123" hasn't been found" is present on the page