Showcase of issue
Unable to click on this dropdown list since it does not have an ID, how could I click on this select class?
You can use the classname, classname with the element name to locating the element.
await t.click(Selector("select.product_sort_container"));
You will have to master location strategies to locate elements in the web pages. All elements will not have IDs.
Reference :
Select Page Elements
Mastering CSS for web automation
Recipe : Test <Select> Elements
Refer to this documentation to learn how to use selectors to select elements.
Since your dropdown has an html attribute you can use Selector.withAttribute Method.
Related
Hi I am looking for an explanation on how selenium searches for an element on a website. For us, we use inspect element to find the id, name, xpath, etc. of an element, and then put it in selenium for some action to be done. How does selenium find the element we tell it to find? Does it ctrl shift J like us and inspect element?
Note: I am not looking for how to code selenium to find element.
Html pages are just documents with elements structured like in a tree.
In general
Selenium uses element locators to find things. Locators work lazily. When you look up an element Selenium first checks if its cached. If not, it uses SearchContext which finds all elements within the current context (eg. DOM element) using a given mechanism, for example by XPathEvaluator.
SearchContext runs findElement() if you are looking for one element or findElements() if you are looking for more than one.
In simple terms, findElement() tries to run JavaScript script to find the element asynchronously. If it can’t, it tries to find it directly by using an interestingly called method – xpathWizardry, i.e. by using XPathEvaluator evaluation.
XPath
When you use XPath (XML Path Language) in Selenium, this is just a way to navigate through hierarchical structure of an XML-like document, such as html.
XPath uses a non-XML syntax to provide a flexible way of pointing to different parts of an XML document.
Internally selenium uses W3 XPathEvaluator, which evaluates XPath expressions.
You can study XPathEvaluator source code here.
Search Context
The SearchContext is a topmost interface present in the Selenium WebDriver hierarchy. It has two methods that will be the abstract as SearchContext is an interface.
findElement(): Find the first WebElement using the given method.
WebElement findElement(By by)
Parameters:
by - The locating mechanism
Returns:
The first matching element on the current context
Throws:
NoSuchElementException - If no matching elements are found
findElements(): Find all elements within the current context using the given mechanism.
java.util.List<WebElement> findElements(By by)
Parameters:
by - The locating mechanism to use
Returns:
A list of all WebElements, or an empty list if nothing matches
The browser DOM exposes API like querySelector,querySelectorAll, getElementById, getElementsByClassName, getElementsByName, etc through javascript that can be used to locate elements.
For example :
Navigate to www.bing.com
Press F12 to open developer console.
Enter document.querySelector("#sb_form_q") to locate search box input by css selector. I am using #Id here as css selector.
Enter document.getElementById("sb_form_q") to locate search box input by it's Id
Enter document.getElementsByClassName("sb_form_q")[0] to locate search box input by it's class name
Enter document.getElementsByName("q")[0] to locate search box input by it's name
All of above should return "<input id="sb_form_q" class="sb_form_q" name="q" type="search" maxlength="1000" autocomplete="off" aria-label="Enter your search term" autofocus="" aria-controls="sw_as" aria-autocomplete="both" aria-owns="sw_as" aria-activedescendant="sa_5004">" same result.
Selenium uses these DOM API to retrieve the elements. However, selenium might use these DOM API via some other mechanism (e.g C ++) and not by executing javascript for faster execution. XPath lookup is something not supported directly by browser DOM API. Selenium probably provides it's own implementation for XPath lookup or rely on some browser polyfill for this functionality.
Can't click to Customize link when div+link together with FakeAnchor class using selenium web driver
In my Ajax application, we have dropdown + link (Customize) together in div and i want to click to Customize link. I have locator and which was working fine for Customize link with old selenium but it doesn't with latest web driver. Can anyone please point me the problem or suggest something to make it work?
Expected:
Clicking to Customize link should open respected option (it actually opens dialog).
Actual:
Below locator clicks to dropdown button instead of Customize link due to such a complex page DOM which has no actual href or anchor tag.
Locator:
css=div[id$='_repeatDesc'][class='FakeAnchor']
Html:
<div id="zcs1_repeatDesc" class="FakeAnchor" style="cursor: pointer;">Customize</div>
Code:
webDriver().findElement(By.cssSelector("div[id$='_repeatDesc'][class='FakeAnchor']")).click();
I think your locator is not unique, may be it is locating dropdown element that's why it clicks to dropdown button instead of Customize link.
You should try using By.xpath() with text() node to locate this element as below :-
webDriver().findElement(By.xpath(".//div[text() = 'Customize']")).click();
Or As I'm seeing in HTML element has id attribute, if it's unique I'd to locate desire element and it's not being changed dynamically, you can try also using By.id() as below :-
webDriver().findElement(By.id("zcs1_repeatDesc")).click();
Edited :- If you want to click using JavascriptExecutor try as below :-
((JavascriptExecutor)driver).executeScript("arguments[0].click()", webDriver().findElement(By.xpath(".//div[text() = 'Customize']")));
i'm trying to find a web element in a web page coded with Polymer,
the source is:
<iron-ally-announcer>==0
<div class="style-scope iron-ally-announcer" aria-live="polite">Invalid credentials</div>
</iron-ally-announcer>
I can find with xpath but i want to find by classname or id
if i try =
driver.findElement(By.className("style-scope iron-ally-announcer"));
it cannot find.
The element is an alert message.
By.className receives one class as parameter, style-scope and iron-ally-announcer are actually two classes in that WebElement. It should be
driver.findElement(By.className("style-scope"));
// or
driver.findElement(By.className("iron-ally-announcer"));
If you want to use both of them you can do it with cssSelector
driver.findElement(By.cssSelector(".style-scope.iron-ally-announcer"));
In my WebDriver project, I have planned to add Jsoup to get 'parent' and 'siblings' and few other features. I need to find an element through Jsoup and click its parent using WebDriver. That means I need to convert a Joup element object to WebElement object. Please let me know how I can do this, if this is feasible.
If it is not possible to integrate Jsoup and WebDriver in such way, then please discuss on how I can get parents and all using WebDriver.
Also, is it possible to list ALL possible elements present under a particular WebElement?
It's quite interesting we're doing the similar approach, integrating JSoup and Selenium WebDriver. I can understand your issue especially dealing with some dynamic website based on some Javascript framework which has no stable IDs or attributes.
Our solution looks like the following, and hopefully it could be some advice for you:
webDriver.getPageSource() to get the current HTML source
use JSoup to parse this HTML source, and leverage Jsoup selector (which is much more powerful than Selenium) to locate the target element
get parents or siblings of this element
write an iteration function to get element xPath, such as //body/div[2]/form[1]/input[3]
webDriver.findElement(By.xpath(...)) to locate element in selenium context
EDITED
The idea of the iteration function is:
first check the tag of your parent node, if it is body, then iteration ends
if not , then use getSiblings to check the index of the node among all the nodes with same tag, e.g, the 3rd div, then equals to div[3]
iterate to your parent node, and do the same procedures
Once you get the xpath of the child node, and parent node, just replace parent node xpath to be empty string inside the child node xpath, finally you can get the relative xpath.
You can use xpath selectors to select parent and child elements
Related questions
Select parent using xpath
XML xpath, get the parent element till a specific element
Getting child nodes using xpath?
What about running findElements with xpath : .//* on your particular element? Also, look into xpath parent::* and following-sibling::*. For the particular case I understand, there is no need for Jsoup.
All the elements in the application which i am testing have dynanic ID's . The test always passes when i replay it without refreshing the page but as soon as i refresh the page, The Test Fails because Id's of all the elements changes randomly and selenium cannot match the recorded id's with the new ones .
I tried to use Xpath-position, It works for some objects but in case of Dropdown list and Buttons, it dosent work!
Can anyone please tell me how to find the Xpath (Meathods in JAVA or S*elence*) of an object OR How to create a new Locator Finder for Dropdown list and Buttons
I can show the properties (Inspected by Firebug) of the dropdown which is teasing me.
properties of Dropdown :
<div id="ext-gen1345" class="x-trigger-index-0 x-form-trigger x-form-arrow-trigger x-form-trigger-last x-unselectable" role="button" style="-moz-user-select: none;"></div>
properties of Dropdown*Choice*:
<ul>
<li class="x-boundlist-item" role="option">Rescue</li>
</ul>
Please search before posting, I have been answering this over and over.
ExtJS pages are hard to test, especially on finding elements.
Here are some of the tips I consider useful:
Don't ever use dynamically generated IDs. like (:id, 'ext-gen1345')
Don't ever use absolute/meaningless XPath, like //*[#class='someclass']/li/ul/li[2]/ul/li[2]/table/tbody/tr/td[2]/div
Take advantage of meaningful auto-generated partial ids and class names. (So you need show more HTML in your example, as I can make suggestions.)
For example, this ExtJS grid example: (:css, '.x-grid-view .x-grid-table') would be handy. If there are multiple of grids, try index them or locate the identifiable ancestor, like (:css, '#something-meaningful .x-grid-view .x-grid-table'). In your case, (:css, '#something-meaningful .x-form-arrow-trigger')
Take advantage of button's text.
For example, this ExtJS example: you can use XPath .//li[contains(#class, 'x-boundlist-item') and text()='Rescue']. However, this method is not suitable for CSS Selector or multi-language applications.
The best way to test is to create meaningful class names in the source code. If you don't have the access to the source code, please talk to your manager, using Selenium against ExtJS application should really be a developer's job. ExtJS provides cls and tdCls for custom class names, so you can add cls:'testing-btn-foo' in your source code, and Selenium can get it by (:css, '.x-panel .testing-btn-foo').
Other answers I made on this topic:
How to find ExtJS elements with dynamic id
How to find unique selectors for elements on pages with ExtJS for use with Selenium?
How to click on elements in ExtJS using Selenium?
Using class names in Watir
how to click on checkboxes on a pop-up window which doesn't have name, label
I would suggest you build a xpath from any of the parent of your DIV. you may get messed if there is no immediate parent node has such one.
example,
//*[#id='parentof div']/div
//*[#class='grand parent of div']/div/div
i did even something like this,
//*[#class='someclass']/li/ul/li[2]/ul/li[2]/table/tbody/tr/td[2]/div
But still, its not encouraged to do so.