Selenium/ Java how to verify the this complex text on page - java

I want to verify below text(HTML code) is present on page which as // characters , etc using selenium /jav
<div class="powatag" data-endpoint="https://api-sb2.powatag.com" data-key="b3JvYmlhbmNvdGVzdDErYXBpOjEyMzQ1Njc4" data-sku="519" data-lang="en_GB" data-type="bag" data-style="bg-act-left" data-colorscheme="light" data-redirect=""></div>
Appreciate any help on this

I believe you're looking for:
String textToVerify = "some html";
boolean bFoundText = driver.getPageSource.contains(textToVerify)
Assert.assertTrue(bFoundText);
Note, this checks the page source of the last loaded page as detailed here in the javadoc. I've found this to also take longer to execute, especially when dealing with large source codes. As such, this method is more prone to failure than validating the attributes and values and the answer from Breaks Software is what I utilize when possible, only with an xpath selector

As Andreas commented, you probably want to verify individual attributes of the div element. since you specifically mentioned the "//", I'm guessing that you are having trouble with the data-endpoint attribute. I'm assuming that your data-sku attribute will bring you to a unique element, so Try something like this (not verified):
String endpoint = driver.findElement(
new By.ByCssSelector("div[data-sku='519']")).getAttribute("data-endpoint");
assertTrue("https://api-sb2.powatag.com", endpoint);

Related

How am I supposed to extract properties from a node in Apache Jackrabbit from xml?

I have been playing around with the example number three in here http://jackrabbit.apache.org/jcr/first-hops.html , however to me it remains unclear how to get access to the properties of a node.
In the first screenshot
I used the debugger from my IDE and I evaluated this expression
session.getNode("/importxml/xhtml:html/xhtml:body/mathml:math/mathml:apply/mathml:apply[2]/mathml:apply[2]/mathml:cn").getProperty("jcr:xmltext/jcr:xmlcharacters").getString().trim();
You can see how I can get access to "jcr:xmltest/jcr:xmlcharacters" and have 2 as a result.
However, when I try to get this information, get this property out of the node, I am unable to perform this operation as in this screenshot.
This is the code fragment in the above screenshot:
var node = session.getNode("/importxml/xhtml:html/xhtml:body/mathml:math/mathml:apply/mathml:apply[2]/mathml:apply[2]/mathml:cn");
var properties = node.getProperties();
List<string> result = new ArrayList<>();
while(properties.hasNext()) {
Property property = properties.nextProperty();
result.add(property.getString().trim());
}
return result;
You can see how I get as a response only a value containing "nt:unstructured".
Unfortunately I couldn't find many code examples online, on Github, etc. many outdated, and also, there are not books as there are for Scrapy or other libraries/frameworks.
Thank you in advance.
Have a nice day!
Davide
In the first case, you are looking at the properties of:
/importxml/xhtml:html/xhtml:body/mathml:math/mathml:apply/mathml:apply[2]/mathml:apply[2]/mathml:cn/jcr:xmltext
In the second case:
/importxml/xhtml:html/xhtml:body/mathml:math/mathml:apply/mathml:apply[2]/mathml:apply[2]/mathml:cn
Note the different paths.

Rythm use transformers and nested tags with #i18n tag

First of all I'm very happy with Rythm! Excellent work for something that is free.
Recently I have begun internationalization of my templates with Rythm and some things seem more cumbersome than needed. I'm wondering if there is any better way of doing what I'm trying to do.
1. Chain tag onto #i18n()
This does not work:
#i18n("about.text").nl2br()
#i18n("about.text").mytransformer()
The workaround for this is:
#assign(newvar){#i18n("about.text")}
#newvar.nl2br()
This works but is is not pretty.
2. #i18n() escaped in javascript
If I have a section
<script>
var s = '#description';
</script>
then Rythm will nicely escape any ' or " in that description. However when I use:
<script>
var s = '#i18n("description")';
</script>
escaping is not done. I also tried doing:
var s = '#i18n("description").escape("js")';
and
var s = '#escapeJS(){#i18n("description")}';
but both do not work (see above). What does work again is using
#assign(desc){#i18n("description")}
...
var s = '#desc';
3. Use of tag inside #i18n() as argument
Sometimes I need a link inside a translated string like so:
about.text=See my profile here {1}
I would like to use this in the template as follows:
#i18n("about.txt",#genlink("person",person.getId()),person)
Note: person here is an template argument of type Person. #genlink is a convenience template(or tag) to generate a link using a lookup.
The solution I currently use is:
#assign(lnk){<a href='#genlink("person",person.getId())'>#person</a>}
#i18n("about.txt",lnk)
Note that the language resource has changed to: about.text=See my profile here {0}
This is probably the better way to write the resource string anyway, but it would be nice if I could get rid of the #assign() somehow and write this:
#i18n("about.text","<a href='#genlink("person",person.getId())'>#person</a>")
Edit:
I tried your suggestions and was only partially successful.
Chain tag onto #i18n()
doing #("about.text".i18n()) works whereas doing #("about.text".i18n().nl2br()) doesn't work and complains about a missing parameter for #i18n(). If I add the missing parameter like so: #("about.txt".i18n("").nl2br()) it complains that nl2br() is not defined for String
What did work for me was: #s().i18n("about.txt").nl2br()
Even weirder so, when I run your fiddle on Chrome it works perfectly. When I run it on Mac/Safari I get the same error as I just described: see screenshot:
#i18n() escaped in javascript
Works as you explained!
Use of tag inside #i18n() as argument
understood. The current solution with #assign() is fine for one-offs. Using #def() is a nicer generic solution.
Chain tag onto #i18n()
Try to use .i18n() transformer instead of #i18n() tag.
Say change #i18n("about.text").nl2br() to #("about.text".i18n().nl2br())
Note you need the () pair to enclose the entire expression if you feed into a string literal like "about.text", however if you do the same thing for a variable then that () can be opt out, e.g #foo.i18n().nl2br()
#i18n() escaped in javascript
Again, use .i18n() transformer
Use of tag inside #i18n() as argument
Tag processing is very hard to put into another tag or transformer. In your case I recommend you to use inline tag
The demonstration of all above three points could be found at http://fiddle.rythmengine.org/#/editor/0c426d5332334db3870b6bd8c0806e66

How to speed up page parsing in Selenium

What can I do in case if I load the page in Selenium and then I have to do like 100 different parsing requests to this page?
At this moment I use different driver.findElement(By...) and the problem is that every time it is a http (get/post) request from java into selenium. From this case one simple page parsing costs me like 30+ seconds (too much).
I think that I must get source code (driver.getPageSource()) from first request and then parse this string locally (my page does not change while I parse it).
Can I build some kind of HTML object from this string to keep working with WebElement requests?
Do I have to use another lib to build HTML object? (for example - jsoup) In this case I will have to rebuild my parsing requests from webelement's and XPath.
Anything else?
When you call findElement, there is no need for Selenium to parse the page to find the element. The parsing of the HTML happens when the page is loaded. Some further parsing may happen due to JavaScript modifications to the page (like when doing element.innerHTML += ...). What Selenium does is query the DOM with methods like .getElementsByClassName, .querySelector, etc. This being said, if your browser is loaded on a remote machine, things can slow down. Even locally, if you are doing a huge amount of round-trip to between your Selenium script and the browser, it can impact the script's speed quite a bit. What can you do?
What I prefer to do when I have a lot of queries to do on a page is to use .executeScript to do the work on the browser side. This can reduce dozens of queries to a single one. For instance:
List<WebElement> elements = (List<WebElement>) ((JavascriptExecutor) driver)
.executeScript(
"var elements = document.getElementsByClassName('foo');" +
"return Array.prototype.filter.call(elements, function (el) {" +
" return el.attributes.whatever.value === 'something';" +
"});");
(I've not run the code above. Watch out for typos!)
In this example, you'd get a list of all elements of class foo that have an attribute named whatever which has a value equal to something. (The Array.prototype.filter.call rigmarole is because .getElementsByClassName returns something that behaves like an Array but which is not an Array so it does not have a .filter method.)
Parsing locally is an option if you know that the page won't change as you examine it. You should get the page's source by using something like:
String html = (String) ((JavascriptExecutor) driver).executeScript(
"return document.documentElement.outerHTML");
By doing this, you see the page exactly in the way the browser interpreted it. You will have to use something else than Selenium to parse the HTML.
Maybe try evaluating your elements only when you try to use them?
I dont know about the Java equivalent, but in C# you could do something similar to the following, which would only look for the element when it is used:
private static readonly By UsernameSelector = By.Name("username");
private IWebElement UsernameInputElement
{
get { return Driver.FindElement(UsernameSelector); }
}

Include page javascripts conflicting with outer page javascripts

My problem is a little difficult to explain, but I will try.
I have 2 jsp pages Outer.jsp and Inner.jsp
Outer.jsp
Script: src="tabs.js"
var PageTabs = "Tab1"
#include "Inner.jsp"
Inner.jsp
Script: src="tabs.js"
var PageTabs = "Tab2~Tab3~Tab4"
Both the jsp pages use the same tabs.js to render some tab elements on the page. The "PageTabs" variable is one of the many common variables that are used by tabs.js. So what happpens is while rendering, the tabs.js takes the latest "PageTabs" variable i'e var PageTabs = "Tab2~Tab3~Tab4" even while rendeing tabs of Outer.jsp.
Note: The page variables and tabs.js are part of standard elements recieved from client. So they have to be used to give the same look and feel for application.
What I need is a way to isolate the "Inner.jsp" from accessing scripts of "Outer.jsp". This will prevent the tabs element from being confused over which variables to use.
I hope I am somewhat clear. Please let me know if I need to provide any more clarifications. Thanks.
JavaScript is interpreted top-to-bottom inside a page, so your second PageTabs value overrides the first one. One option is to use a different name for the variable (and parameterize tabs.js functions rather than rely on global vars.)
When using jsp include, one of a very useful skill is to make your .js code modular . This is also an important method to encapsulate code and avoid conflict.
tab.js:
var tabModule = (function(my){
var model;
return {
setModel: function(model){/*....*/}
//other api functions
}
})(tabModoule||{});
Outer.jsp:
tabModule.setModel({PageTabs : "Tab1"});
Innder.jsp:
tabModule.setModel({PageTabs : "Tab2~Tab3~Tab4"});

JSoup not translating ampersand in links in html

In JSoup the following test case should pass, it is not.
#Test
public void shouldPrintHrefCorrectly(){
String content= "<li>Good<ul><li><a href=\"article.php?boid=1865&sid=53&mid=1\">" +
"Boss</a></li><li><a href=\"article.php?boid=186&sid=53&mid=1\">" +
"heavent</a></li><li><a href=\"article.php?boid=167&sid=53&mid=1\">" +
"hellos</a></li><li><a href=\"article.php?boid=181&sid=53&mid=1\">" +
"Mr.Jackson!</a></li>";
Document document = Jsoup.parse(content, "http://www.google.co.in/");
Elements links = document.select("a[href^=article]");
Iterator<Element> iterator = links.iterator();
List<String> urls = new ArrayList<String>();
while(iterator.hasNext()){
urls.add(iterator.next().attr("href"));
}
Assert.assertTrue(urls.contains("article.php?boid=181&sid=53&mid=1"));
}
Could any of you please give me the reason as to why it is failing?
There are three problems:
You're asserting that there's a bovikatanid parameter is present, while it's actually called boid.
The HTML source is using & instead of & in the source. This is technically invalid.
Jsoup is parsing &mid as | somehow. It should have scanned until ;.
To fix #1, you have to do it yourself. To fix #2, you have to report this issue to the serveradmin in question (it's their fault, however, since the average browser is forgiving on this, I'd imagine that Google is doing this to save bandwidth). To fix #3, I've reported an issue to the Jsoup guy to see what he thinks about this.
Update: see, Jonathan (the Jsoup guy) has fixed it. It'll be there in the next release.

Categories