The Intern - functional tests Finding Element with A Descendant that matches - functional-testing

I am writing a functional test script to find a parent element that HAS a child that can be found, and if a descendant is found, return the parent. For example:
<div class="contentPane">
<h2>Heading 1</h2>
<p id="first">FIRST TEXT</p>
</div>
<div class="contentPane">
<h2>Heading 2</h2>
<p id="second">SECOND TEXT</p>
</div>
<div class="contentPane">
<h2>Heading 2</h2>
<p id="third"></p>
</div>
I want to find the contentPane that can find the paragraph with the id="second". My test case to find the parent is similar to this:
...
findAllCssSelector(".contentPane")
.then(function(array, setContext){
//for every element i in array
//I want to call its findByCssSelector(".second")
//and check if it is found. If it is
//I want to return the ith element in array
// to the command.
})
.findByTagName("h2")
.getVisibleText()
.then(function(text){
assert.strictEqual(text, "Heading 2");
})
....
...
How do I iterate through each array element and return the array element to the context stack?

For complex queries, Xpath is generally much more efficient than manually searching through elements. You could query with something like:
.findByXpath('//div[#class="contentPane" and p[#id="second"]]')
This will find the first DIV with class "contentPane" that contains a P with id "second".

Related

Select nodes that 1) precede a given node but 2) are also descendants of another given node

Say I have the following XML:
<body>
<div id="global-header">
header
</div>
<div class="a">
<h3>some title</h3>
<p>text 1</p>
<p>text 2</p>
<p>text 3</p>
</div>
</body>
I want to
find any <p> node whose value is "text 2", and then
find all the nodes that precede this particular <p> but are also descendants of the <div class='a'> node.
The desired output should look like:
<h3>some title</h3>
<p>text 1</p>
The caveat is that the preceding nodes may contain arbitrary node type, not only <h3> and <p>, as in the above case.
My first try:
.//p[text()="text 2"]/preceding::*
Unfortunately, this will also select <div id="global-header">, which is not desired.
You need to use preceding-sibling to select nodes that are children of the same parent instead of preceding:
.//p[text()="text 2"]/preceding-sibling::*

Simple dom document iteration

I have an HTML as so:
<html>
<body>
<div class="somethingunneccessary"></div>
<div class="container">
<div>
<p>text1</p>
<p>text2</p>
<p>text3</p>
</div>
<div>
<p>text4/p>
<p>text5</p>
<p>text6</p>
</div>
<div>
<p>text7</p>
<p>text8</p>
<p>text9</p>
</div>
<div>
<p>text10</p>
<p>text11</p>
<p>text12</p>
</div>
<div>
<p>text13</p>
<p>text14</p>
<p>text15</p>
</div>
</div>
</body>
</html>
What I'm trying to accomplish is the following:
1./ Loop over the div elements within the div having a class container.
2./ During the iteration I want to grab the text from the 3rd p tag.
The looping part is essential instead of just slicing out the p tags by themselves
I've got some code done but it doesn't do looping:
$doc=new DOMDocument();
$doc->loadHTML($htmlsource);
$xpath = new DOMXpath($doc);
$commentxpath = $xpath->query("/html/body/div[2]/div[5]/p[3]");
$commentdata = $commentxpath->item(0)->nodeValue;
How do I loop through each inner div element and extract the 3rd p tag.
Like I said, the looping is essential.
During the iteration I want to grab the text from the 3rd p tag
Try:
"//div[#class='container']/div/p[3]"
This should return all third p in all div inside of div with class container.
You may have to query over attributes: php xpath get attribute value
$xpath->query("/html/body/div[#class='container']");
Just try
/html/body/div/div//p
That should return only the p elements XD

Check for preceding nodes starting from a specific point in xml

I'm trying to create an xpath to find an element which doesn't have any 'p', 'li', or 'span' preceding elements under a common parent. For example I have this structure:
<a>
<div>
<div/>
<div>
<div>
<div>
</p>
</div>
<img/>
</div>
<div>
<ci/>
</div>
</div>
</div>
</a>
The node I'm interested in is the <img> element. So far I have this xpath:
count(/a/div[1]/div[position() = last()]//img[(count(preceding::*[name() = 'p' or name() = 'li' or name() = 'span']) = 0)]) > 0
I don't care if any of the unwanted elements are under /a/div[1]/div[1]/ only under /a/div[1]/div[2]. With that said, preceding won't work because it'll look under /a/div[1]/div[1] which I don't care for. The 'p' element in the above example can be in any number of divs.
EDIT:
I added the div containing the element <ci/>.
I was able to get this to work using the following:
count(/a/div[1]/div[position() = last()]//img[(count(preceding::*[(name() = 'p' or name() = 'li' or name() = 'span']) and ancestor::div[parent::div[parent::a] and descendant::ci]]) = 0)]) > 0

Selecting cousin element with XPATH

Given following markup
<div>
<a>Username1</a>
</div>
<div>
<button>Unblock</button>
</div>
<div>
<a>Username2</a>
</div>
<div>
<button>Unblock</button>
</div>
<div>
<a>Username3</a>
</div>
<div>
<button>Unblock</button>
</div>
How do I select button element which is a cousin of a element with text Username2?
I can select the a element with //a[contains(., 'Username2')], so I thought that //a[contains(., 'Username2')]/following-sibling::/div/button would select the correct button, but that does not work. I think that it's not even valid XPATH.
You were close:
//a[contains(., 'Username2')]/../following-sibling::div[1]/button
To navigate to the cousin you first have to go to the parent (..) and then to its sibling.
Note that the following-sibling:: axis selects all following siblings, not only the first one. This means you must use [1] if you just want the first.
This would also work:
//a[. = 'Username2']/../following-sibling::div[1]/button
So would this:
//div[a = 'Username2']/following-sibling::div[1]/button

xPath strange behaviour - selecting ALL elements even if [1] set

today I stumbled upon a very interesting case (at least for me). I am messing around with Selenium and xPath and tried to get some elements, but got a strange behaviour:
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some other text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some even unrelated text
</a>
</div>
</div>
</div>
This is my data.
When i run the following xPath query:
//div[#class="title"][1]/a
I get as a result ALL instead of only the first one. But if I query:
//div[#class="resultcontainer"][1]/div[#class="info"]/div[#class="title"]/a
I get only the first , not all.
Is there some divine reason behind that?
Best regards,
bisko
I think you want
(//div[#class="title"])[1]/a
This:
//div[#class="title"][1]/a
selects all (<a> elements that are children of) <div> elements that have a #class of 'title', that are the first children of their parents (in this context). Which means: it selects all of them.
The working XPath selects all <div> elements that have a #class of 'title' - and of those it takes the first one.
The predicates (the expressions in square brackets []) are applied to each element that matched the preceding location step (i.e. "//div") individually. To apply a predicate to a filtered set of nodes, you need to make the grouping clear with parentheses.
Consequently, this:
//div[1][#class="title"]/a
would select all <div> elements, take the first one, and then filter it down futher by checking the #class value. Also not what you want. ;-)

Resources