dijit -- registry.byNode vs registry.getEnclosingWidget - dojo

Refer to the http://dojotoolkit.org/reference-guide/1.9/dijit/registry.html
Both can input a Node and Return Widget?
What is the practical use of them?

registry.byNode just checks the given node and returns the widget that it belongs to.
registry.getEnclosingWidget will walk up the DOM until it finds a node that represents a widget.
This means that when given a DOM node of a widget, they will both return the same thing. See this note in the documentation about that specific case. registry.getEnclosingWidget is useful if you have a node that you know is associated with a certain widget but that it is not necessarily a root widget node itself.

Related

Why do two identical looking elements return when using XPath to map elements for Selenium WebDriver?

I have had this question a while, but I had never done anything about it. When mapping some elements for UI tests I sometimes come across elements that return two identical results.
We have got around this in the past by using findelements and then using an index [1].
But I still don't understand why it returns two elements when I can only see one in the code that should be located.
An example would be the following. You can see this username field box below.
And if I use some XPath expression like,
//input[#name='username']
I'm expecting only to get one element in return, but using the tool Chropath I can see that I get two elements in return.
These elements look identical, one is not hidden, etc.
I have never understood why this is happening, because if I use a findelement, I get an element, not interactable error, as I guess the driver can’t decide which one to use? Or they are in the way of one another.
So the workaround I have always used is:
return self.browser.find_elements(by=By.XPATH, value="//input[#name='username']")[1]
when I realisticly should be able to use:
return self.browser.find_element(by=By.XPATH, value="//input[#name='username']")
Why is this?
Some excellent response and it has made me understand what’s going on now. Moving forward, I will use the following:
for e in self.browser.find_elements(by=By.XPATH, value="//input[#name='username']"):
if e.is_displayed():
return e
This seems to work for me.
I see this often when a website has both the "desktop" version and a mobile or smaller screen version. At full (or near full) screen, the desktop elements are visible while the small screen elements are hidden. Once you resize the browser small enough, the desktop elements are hidden and the small screen elements become visible.
To get around this in a generic way, filter the returned two elements based on visibility, e.g.
return [e in self.browser.find_elements(by=By.XPATH, value="//input[#name='username']") if e.is_displayed()]
That should always return the visible element of the two.
The answer is within the snapshot:
The following xpath
//input[#name='username']
Identifies 2 different elements within the HTML DOM. Among the two matching elements, the first matching element is for mobile displays which remains hidden while you access the DOM Tree in Desktop mode. In the given snapshot of the Chropath the classname as modal-content-mobile is the best hint.
Solution
In these cases there are different approaches to identify the desired element. While some users tends to use an index and some users tends to probe the displayedness, from a personal perspective I find it quite easier and handy to traverse up the DOM to find the difference in attribute values in any of their ancestors and then finally follow down till the desired element.
It is possible you can have more than one same element on the page with same name attribute. One must be hidden.
If you want to access the first one use following xpath.
return self.browser.find_element(by=By.XPATH, value="(//input[#name='username'])[1]")
If you want to access last one use following
return self.browser.find_element(by=By.XPATH, value="(//input[#name='username'])[last()]")
It's quite often occurs that multiple elements will match the same locator.
For example, several code blocks may be implemented for login: one for a computer browser, another for a mobile browser, etc. The proper elements will be presented according to what you use to browse that page.
Selenium find_element always returns the first element found matching the passed locator on the page.
So, in case the first matching element is hidden return self.browser.find_element(by=By.XPATH, value="//input[#name='username']") will always retunt that hidden element.
You will need to make your locator more precise to match the desired web element.
A locator like "(//input[#name='username'])[2]" may be good, but it's better to use a unique parent element here, something like "//div[#class='pc_modal']//input[#name='username']", so your code would be something like this:
return self.browser.find_element(By.XPATH, "//div[#class='pc_modal']//input[#name='username']")
Well, in the strictest sense of way, no two elements have the same XPath expression. If you look at the absolute path, you will find the difference. The key is to find a path which is unique. In many case, you will find a web page where you find many textboxes/labels/dropdowns that have the same ids but are only differentiated by their absolute path.
Most of the times, such things depend on the framework used to develop the webpage and also developer's preference. An application developed in React will have a different DOM structure than one developed using Angular, for instance.
Yes, you are correct that it becomes difficult to find out which is the element of interest in such situations. In such cases, do not only depend on the particular element but add either a parent/sibling or ancestor to access the element. Although it might take some time and will jot be straightforward but it will be possible to find a unique XPath most of the times.
There are some test automation tools, like Ranorex, that have an object browser (objext spy as it is called) that can be used to pin on any web element and access its properties like hidden, visible. enabled, etc. But such tools are not free :(

Angular 2 testing nativeElement

I have been going through the testing tutorial on the angular website. I am curious if there is a listing of all of the items that are available for test through the debugElement. For example
let nav = fixture.debugElement.query(By.css('h1')).nativeElement;
expect(nav.innerText).toBe(fixture.componentInstance.homeHeader);
What other elements are there like the innerText value that I am testing.
Thank you for any help.
The list is too long. These are native JS DOM elements It depends on what type element it is to get a complete list of properties. You should learn to navigate the MDN site. Here is a link to HTMLHeadingElement (this is what an h1 is). If you look at the sidebar, you will see
Properties (missing from HTMLHeadingElement, see below). This is a list of all direct properties of this element (see parent for inherited properties)
Inheritance. This is inheritance the hierarchy for HTMLHeadingElement
EventTarget
|
Node
|
Element
|
HTMLElement
|
HTMLHeadingElement
You can click any one of those links, and you will see the inherited properties. For instance, if you click on Node, you will see that that's where the HTMLHeadingElement gets the innerText property from. If you go back to HTMLHeadingElement, you will see that it has no direct properties. That means that all of its properties are inherited from its parents
Methods (missing for HTMLHeadingElement, see parent for inherited methods)
Events. These are all the events that can be triggered for the element
Related pages for HTML DOM. This is a list that is common to all the pages. You can see a list of all the different kinds of DOM elements. You can click through them. For the most part though, most of the properties you will use from any of the DOM elements will be inherited properties from the parent. So you probably want to just look at the parent properties list. Though some do have their own properties.

selenium elementIdElement functionality

The documentation on code.google.com describes the elementIdElement functionality as "Search for an element on the page, starting from the identified element". Does this mean the search is done for every element following that element throughout the rest of the web page or only for dependents of that element?
If it is the former, then how would I construct the "value" entry if the "using" parameter is "css selector" and I want to find a descendant of the current element's sibling? I thought the value would be "+ div .classname", but this doesn't seem to work.
One way you can do it is by emulating Selenium ByChained, by calling one wait after another:
browser
.useXpath()
.url('http://www.google.com')
.waitForElementVisible('.//body', 1000)
.waitForElementVisible(".//div[contains(#class, 'classVar')]")
.click('button')
The correct xpath string for navigating to an element's parent's following sibling for the existence of another element with a given class is
'(//div[#id="currentElementID"]/../following-sibling::*[1]//div[contains(#class,"classToLookFor")])[1]'
In this example, I know the current element's ID so that's what I use, but the '//div[#id="currentElementID"]' can be replaced with whatever you need to navigate to the starting element. Also, this example assumes the element I'm looking for is a div.

How to use ExpectedConditions.visibilityOfElementLocated for multiple hits

I have a HTML site containing several context menues.
The xpath is: .//*[#id='TopIcon_Edit']/a/span. (This path will hit several elements)
In my test one of the context menues is visible.
I now want to verify that one context menu is visible, using
ExpectedConditions.visibilityOfElementLocated(By.xpath(".//*[#id='TopIcon_Edit']/a/span")).
Although I can see that the context menu is visible, the test tells me:
"Element does not meet condition visibility of element located by By.xpath: ..."
I assume that the method visibilityOfElementLocated(...) just evaluates the visibility of the first element it finds by the locator, which is not visible, as Selenium rightly sais.
I would appreciate any hints on how to solve this problem.
With kind regards,
Gerhard Schuster
Yes, when you search single element with Selenium and result returns more than one element, the method takes the first element and returns it.
So, you have to specify more precisely the xpath you using, for example: ".//*[#id='TopIcon_Edit']/a[1]/span", or similar, that will point only desired element.
If you can do away with xpath that would help. FindElement(By.cssSelector("#TopIcon_Edit span")).click() or do a list of web elements we = FindElements (By.cssSelector("#TopIcon_Edit span")); then filter your list based on style. Its far easier and provides greater flexibility to use cssSelectors.

Can a node in dynatree have several parents?

Using this http://wwwendt.de/tech/dynatree/
I know the answer is probably no, but I want to verify this: can a node have several parents in this component?
That would mean, that nodes with identical properties (title, icon, and other attributes) appear at different locations in the tree.
This is possible, of course.
The only restriction is: It's not allowed to have two nodes with the same key property in one tree.
I think that the behaviour would be hard to define, if nodes where really 'identical'. For example, when you activate one node that has multiple parents, would you expect all instances to be highlighted? And then, when you press [Cursor-Left]: which parent should be navigated to?
But you could add a new property like myBackendKey whith the same value for all node instances.
Yes, a node in DynaTree can have multiple parents. That is: one identical node can be assigned to more than one parent node in the same tree. I am using jQuery Dynatree Plugin v1.2.2.
I've just now encountered a situation where I've had to deal with duplicate nodes in conjunction with navigating from current node to its next/prev sibling.
Since I had dublicate nodes in the tree, the navigation was broken. When querying the tree for a node with key "abc", dynatree will give you only the first occourance of the node with that key (and not care about the remaining nodes with the same key).
Solution: To prevent this from happening, I've simply prefixed the key for duplicate nodes with a unique string.