(Wait doesn't work) Selenium Java <a> Element not interactable - selenium

Yes, already tried with all kind of waits.
I have to click on the big "Dress" block on this site: http://automationpractice.com/index.php
I CAN get the /a> and the /li> elements with Xpath, but none of them are ever "clickable" or "visible"
The following does work but I need a more "use like" solution
((JavascriptExecutor)driver).executeScript("arguments[0].click();", driver.findElement(By.xpath("//a[#title=\"Dresses\"]")));
Again, already tried with waiting until clickable and visible, but it just timeout after 2 minutes.

The issue is that there are two elements that match your locator. Since you are using .findElement (singular), it returns the first one which happens to be the one that is hidden and stays hidden unless you hover the first nav item, "Women".
There are two ways to work around this:
Keep the same locator, use .findElements (plural) and click the second element.
driver.findElements(By.xpath("//a[#title='Dresses']")).get(1).click();
^ gets the second element, the first is index 0.
Modify your locator to find the element you want uniquely.
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.cssSelector("#block_top_menu > ul > li > a[title='Dresses']"))).click();
I prefer the second because you can add a wait and also because it's a CSS selector. CSS selectors are more compatible, more flexible, easier to read (simpler syntax), etc.
Additional note: The way to avoid this issue is to always check your locators in the browser. I use Chrome because I find it to be the easiest to use and most powerful. You can open the devtools using F12. Press ESC if the Console isn't shown. In the console you can test XPaths using $x(), e.g. $x("//a[#title='Dresses']") returns 2 elements. You can test CSS selectors using $$(), e.g. $$("#block_top_menu > ul > li > a[title='Dresses']") returns only one element.

Related

Robot Framework - Locating input element with accept attribute fails

I am writing an automation script for an avatar upload module with the following CSS locator:
input[accept="image/png,image/jpeg,image/gif,image/bmp"]
I am using Robot Framework's Wait Until Element Is Visible keyword to look for the locator above but is unsuccessful with the error:
Element 'css=input[accept="image/png,image/jpeg,image/gif,image/bmp"]' not visible after 30 seconds.
Increasing the timeout also doesn't work. Using the same in Chrome Dev Tools would successfully find the element. My guess is that the commas/slashes are messing with Robot's locator parsing. My question is: What is the correct way to write the locator?
Though present in the DOM, an element may not be visible/rendered. This is very often the case with file upload input elements - the UI renders something different, a button, div that had applied styling and fits in better with the overall design.
Thus a check is it visible will rightfully fail. Change your pre-usage approach to validate the input is in the HTML - this is actually the same as what you did in the browser's dev tools - with the Page Should Contain Element keyword, and proceed on success.
There is no problem with the CSS locator your are using. Maybe the element is in another iframe?

Robot Framework- Loading Spinner selector

I have this problem where I have to validate if a loading spinner is present, it's present for about 1 second on the page, i have found the xpath selector of the loading spinner but selenium library could not find it is there another way to find out a selector of something that dissapears after a short while? Note: The xpath is definitely correct. There is no id on the loading spinner either.
This is the code i have tried
Validate Loading Spinner
Wait until page contains xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
I have also tried Element should contain and Page should contain but that does not find the locator.
You should be using one of the keywords that is validating an element is present - Wait Until Element Is Visible, or Wait Until Page Contains Element - both of which support a timeout argument, for how much to wait.
Afterwards, you'd better use the opposite keyword - Wait Until Element Is Not Visible, to make sure the spinner disappears and you can continue with the test.
There is a problem with your locator - xpath has some issues if the element is svg, most of the times it can't address it directly. So instead of specifying it explicitly in the path, look for a node whose name happens to be "svg"; e.g.:
xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/*[local-name() = "svg"]
(^ changed the last element in the path)
Slightly offtopic - try to have less rigid locators - this one specifies an absolute path from the element with id "app" and down (a div child, then its first div child, then that one's third div child, and so on and so forth). If the element structure changes even slightly, the locator will stop working (say, in a bug fix, or re-positioning it, or just with using a HF of an JS library).
Try to find an element that's 1-2 levels higher than your target svg - by a solid class value, or structure that's unique, and use it as an anchor.
I reckon you used wrong keyword
Validate Loading Spinner
Wait until page contains ELEMENT xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
Both work:
Validate Loading Spinner
wait until page contains element xpath=//*
[#id="app"]/div/div[1]/div[3]/div/div/div/div/*[local-name() = "svg"]
and
Wait until page contains ELEMENT xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
I had a very similar issue

Issue with getting Behat test to find "Search" input that is injected into page by jQuery datatables plugin

The following HTML is inserted into a page by the jQuery Datatables plugin:
<label>Search:
<input type="search" class="" placeholder="" aria-controls="datatable-1">
</label>
The existing Behat test I have, which will not pass:
Given I am on "/courses"
And I fill in "Search" with "course"
The resulting error is:
Form field with id|name|label|value|placeholder "Search" not found.
I have tried the following:
Updating the And to And I fill in "Search:" with "course"
Adding variations of a wait When I wait for "Search:" to appear (timeout in 60 seconds)
Adding variation of a wait When I wait for "[type='search']" (timeout in 60 seconds)
This scenario opens up Firefox and I can see the label "Search:" and the search box.
What do I need to do to get this test to pass?
Behat's I fill in "field" with "value" command is awfully slow, I tend to not use it for this reason.
In this case the label matching is probably not working because of the whitespace around the label text. It's expecting an exact text match, but the extra whitespace is throwing it off.
You can avoid using this function with something like the following:
$this->getSession()->getPage()->find('css', 'input[type=search]')->setValue('course');
If the element is not available when the page loads, you will need to wait for it. I note that you mention that waiting for the label text times out, so you should check to see if the element you're interested in is inside an iframe. In this case, you need to use the switchToIFrame command before selenium can interact with the elements inside the iframe.
For example:
//Switch to iframe with id 'iframeID'
$this->getSession()->switchToIFrame('iframeID');
//Do some stuff with the elements contained in the iframe.
//Switch back to parent iframe.
$this->getSession()->switchToIFrame(null);
One more thing to note is that if there is a hierarchy of iframes, you need to switch one level at a time.

What ExpectedConditions should i use in order to

So sometimes when i want to click on WebElement i am using elementToBeClickable.
Now when i want to get text etc. i have 2 options (maybe more ???) that i usually use:
presenceOfElementLocated - An expectation for checking that an element is present on the DOM of a page.
visibilityOfElementLocated - An expectation for checking that an element is present on the DOM of a page and visible.
My questions:
Whats the different between the both ?
When i want to get text from element/attribute maybe should i use another ExpectedCondition ?
presenceOfElementLocated would just wait for the presence of an element in the DOM tree.
visibilityOfElementLocated would not only ensure that an element is present, but also check if the element is displayed. The logic behind the visibility determination is described here:
Element Displayedness
Which Expected Condition to use is not that simple as in case of elementToBeClickable and a button needed to be clicked - in this case depends on the actual use case - how the desired element is loaded, is it loaded with the text, or the text is set later and dynamically etc.
There is also textToBePresentInElement which might be more suitable, but it requires you to know a part of the element's text.
And, there is always an option to write a custom Expected Condition - for instance, you can wait for any text to be present in element.

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.