Find an element relative from a previous element - html

I'm trying to find an element from a location I got before.
In easy words I use PHPUnit with Selenium/Mink/Behat and first did this
$products = $this->getPage()->findAll('css', 'ul.list li.item .price');
Now I have a list with all items that have a price.
From this position I have to go one node up and find the previous DIV-element.
/preceding-sibling::div[#class='product-box']/descendant-or-self::*/figure/descendant-or-self::*/a/#href
This all works with one XPATH call, but I can't do that in one call, because I have a condition that is checking my first call for a specific needle.
So in real I'm now at a price element and need to know how I can travel up to my previous DIV-element.

Related

ASTContext::getParents() - Ancestors or Parents?

ASTContext::getParents is supposed to return the parents of a given node. My question is how can one AST node have more than one parent??
I suspected that the doc might mean the member function returns the ancestors of a given node, not just the parents and i tested it. sizereturns a size of1` and all the nodes i tested only have one parent.
It's been a couple of years but anyways.
I did ask the question on the clang mailing list but the archive link doesn't seem to exist anymore.
The parents member function could be parent when it comes to C since in C, AST nodes can't have more than one parent. parents makes sense in C++ where nodes can have more than one parent in the AST. This happens for example with template instantiations and lambdas where a node can end up with more than one parent.

How to select a child node by conditionally excluding a parents previous sibling

I have a question regarding using (what is to me) some complex XPath queries in Selenium IDE (thought they do apply to XPath in general).
Firstly, here is my scenario.
I'm writing some automated tests for a feature of a website I am working on that only certain items for sale on the website have. I'm trying to engineer the test in such a way that changes in data will not break it. Here is an abstraction of what I'm testing:
Given a set of search results, certain products within the results will have a feature (let's call the feature attributes), I want to click on the first result (which may change in the future) that has a single price and attributes.
I am using Selenium IDE 2.5.0 / FF 28.
Here is a JsFiddle I created that simulates the markup / DOM structure I have to work with (the markup cannot be changed): http://jsfiddle.net/xDaevax/3qUHB/6/
Here is my XPath query:
//div[contains(#class, 'primary')]//div[contains(#class, 'results')]//div[#class='price-range']/span[not(contains(#class, 'seperate'))]/../../..//a[#class='detail-link']
Essentially, the problem is this: All three have the same wrapping markup and css class information, but they differ in the price-range class due to the second element (the one I'm after) does not have "separate" or "minimum" CSS class elements.
I have made it this far with the XPath selector, but am stuck. I assume that when I traverse back up the DOM with the "/../..", I am losing the conditional XPath clause I previously used.
I apologize for the vagueness of the details, but due to contractual restrictions, I'm being as generic as possible.
Any suggestions on how to achieve the selection I want would be greatly appreciated. Please let me know if I need to clarify any of the requirements or steps I have tried.
Edit:
Here is a succinct description of the desired outcome.
In the markup example given, I want to select and click the link in the middle result element only. This is because the middle element has the desired "attributes" that once the link is clicked, it will take you to the product page which has additional things needing tested. That being said, the data could change: today it is the second element in the list, but maybe tomorrow it is the 7th element of 16 total elements.
My current logic for the XPath (though my solution does not work) is as follows: The element I am interested in is distinguishable from the other results because of two things: 1), it has a detail hyperlink (that will later be clicked) and 2) it does not have a range of prices (unlike the first result). Because the first result also has a hyperlink, the only difference between the two is that the first result has a minimum and separator markup element, while the second does not (my target link will always have a single price and not a range). Based on this information, I tried to write XPath that will select the first hyperlink that is not contained within an element that has a price range.
This expression will select all three div elements:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
If I understood your requirements correctly, the price-range div must have a sibling that is an <a href> element, so we can filter out the last div by adding that restriction in a predicate: [../a[#href]]. So this expression selects only the first two divs:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href]]
Now you can add one more predicate to remove the items that don't have a single price. You chose the separate class as the criterion, so we can change that last predicate and add another restriction to it: [../a[#href] and not(span[contains(#class,'separate')])]. Now your expression selects the div that you want:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href] and not(span[contains(#class,'separate')])]
This is a location path, which creates a context. From this context, you can navigate anywhere you want. You can get the sibling <a href> adding a new step with its relative path: ../a. So, finally, this expression selects the link at the same level as your div:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href] and not(span[contains(#class,'separate')])]
/../a
Or in one line:
//div[contains(#class, 'primary')]//div[contains(#class, 'results')]//div[#class='price-range'][../a[#href] and not(span[contains(#class,'separate')])]/../a

Slick (mootools) selector engine documentation

Mootools slick selector engine documentation seems kind of sparse / unfriendly.
http://mootools.net/docs/core/Slick/Slick
An example:
Normally i can reach the last child of an element with:
$('wrapper').getLast().setStyle('background-color','green');
how do i utilize the new slick engine to achieve the same?
And where is the documentation?
Should i just learn CSS3 selectors?
In their example they use $$('p.foo !^') to get the last child of p class foo whatever that means. (do they mean the last instance of p.foo in the $$ array or the last child of the last element???)
Here i tried to fiddle a bit, the last two doesn't work:
http://jsfiddle.net/XLVr6/1/
The example bellow will select the last child of the element with id="wrapper. It will only return one element.
$$('#wrapper !^').setStyle('background-color','red');
or better way as only one element is needed, as it is faster:
document.getElement('#wrapper !^').setStyle('background-color','red');
However, if it's written like this where we select the last child of all p-elements on the page with class="wrapper"
$$('p.wrapper !^').setStyle('background-color','red');
Another way to do it is like this, however next example is faster:
('someId').getLast().setStyle('background-color','red');
As pointed out by Dimitar this is a better (faster) way to do it:
document.getElement('#someId :last-child')
As for your fiddle, the two last selectors should be written like this:
$$('#wrapper :last-child').setStyle('background-color','red');
$$('#wrapper !^').setStyle('background-color','red');
Please note the space between "wrapper" and ":last-child", that is because we are selecting the last child of a the child elements of "wrapper".

How can I access an element by using its DOM hierarchy(parent element)?

I want to access an element using a DOM hierarchy Node structure, through its parent nodes.I am trying to find the DOM hierarchy through firebug; want something like, <parent_node1>.<child_node1>.<child_node2> (not by document.getElementByID, getElementbyname) to access an element.
I want to automate a scenario like, I have column headers and corresponding values. Want to test, whether the values present under each column header, is correct...
I am thinking of using DOM as a method of automating this case...But, how can I find the DOM hierarchy...?
What I see through Inspect Element in Firebug is something like, list of events, elements and is not looking like a hierarchy node structure...Can somebody help in this regard please?
As discussed, you probably mean the DOM Element properties like element.childNodes, element.firstChild or similar.
Have a look at the DOM Element property reference over at JavaScriptKit, you'll get a good overview there how to access the hierarchy.
var currentTD = document.getElementsByTagName("td")[0];
var currentTable = document.getElementsByTagName("table")[0];
currentTD.parentNode // contains the TR element the TD resides in.
currentTable.childNodes // contains THEAD TBODY and TFOOT if present.
DOM Tables even have more properties like a rows collection and a cells collection.
A reminder of caution: Beware that these collections are live collections, so iterating over them and accessing collection.length in each iteration can be really slow because to get the length, the DOM has to be queried each time.
document.getElementById and document.getElementByTagname are using the DOM. They take an object within the DOM (specifically the document object, though you can also call both of those on elements) and return an object which is a single element or a collection of zero or more elements, respectively. That's a DOM operation. From there you can do other DOM operations on the results like getting children, parents or siblings, changing values etc.
All DOM operations come down to:
Take a starting point. This is often document though it's so often that the first thing we do is call document.getElementById or document.getElementByTagname and then work from the result that we could really consider that the starting point.
Find the element or elements we are interested in, relative to the starting point whether through startingPoint.getElementById* or startingPoing.getElementByTagname perhaps combined with some test (e.g. only working on those with a particular classname, if they have children of particular types, etc.
Read and/or change certain values, add new child nodes and/or delete nodes.
In a case like yours the starting point will be one or more tables found by document.getElementById(someID), document.getElementById(someID).getElementsByTagname('table')[0], or similar. From that table, myTable.getElementsByTagname('th') will get you the column headings. Depending on the structure, and what you are doing with it, you could just select corresponding elements from myTable.getElementsByTagname('td') or go through each row and then work on curRow.getElementsByTagname('td').
You could also just use firstChild, childNodes etc. though it's normally more convenient to have elements you don't care about filtered out by tagname.
*Since there can only be one element with a given id in a document, this will return the same if called on any element higher in the document hierarchy, so we normally just call this on document. It can be useful to call it on an element if we want to do something if the element is a descendant of our current element, and not otherwise.

what happens when i say arrayCollection.addItemAt(object,0);

Lets say i have an Array collection, filled with some elements. If i say
myArrayCollection.addItemAt(object,0);
What exactly happens here? Does all the elements gets shifted rigthwards? or element at 0th position gets replaced with new one?
To summarize, the reason there are two different methods, addItemAt() and setItemAt(), is because one of them adds a new item (not replacing any of the existing ones), and the other sets/overwrites the existing index.
For more info, check out the ArrayCollection documentation.