Selenium: Checking if several elements are not visible takes too much time - selenium

In one of my testcases, im checking if some elements are NOT visible.
Its very simple:
Login
Check if 5 buttons inside the left menu bar are not visible (As the user has no rights)
End test
This shouldnt take more than 10 seconds to test.
But as im using implicit wait, it does always wait 5 seconds for each button, which causes the test to take way too much time to finish. Currently it takes more than 30 seconds just to test if 5 buttons are not visible.
Im using this method:
var elements = _webDriver.FindElements(By.XPath(selector));
if (elements.Count > 0)
{
throw new Exception(selector + " still displayed");
}
Are there any other ways how to make this work?

Use a explicit wait to check for the first element and then just check the other elements directly (with implicitly_wait = 0).
something like:
try:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH, selector))
)
except TimeoutException:
# no element found
if element:
# check the presence of the other elements with find_element
documentation:
https://selenium-python.readthedocs.io/waits.html

Related

WebDriverWait.until.expected_conditions.presence_of_element_located not waiting for reloaded DOM

I have an app with 2 buttons. Button A takes the app to a new page with no buttons, then returns to the page with 2 buttons. My automated test is meant to click on Button A, wait while the app heads to the new pages and returns, then click on Button B.
The code:
el05a = WebDriverWait(driver, 120).until(
expected_conditions.presence_of_element_located((By.ID, "id_of_button_a"))
)
el05a.click()
el05b = WebDriverWait(driver, 120).until(
expected_conditions.presence_of_element_located((By.ID, "id_of_button_b"))
)
el05b.click()
However, I receive a StaleElementReferenceException about button B not being in DOM anymore.
Obviously, button B is not gonna be in the DOM while the app is at the new page, but why does my code not know to wait until the presence of button B is located? I thought presence_of_element_located means the code would be on hold until the element is located.
I know this could "technically" be patched with a time.sleep module but I'm trying to avoid that.
As per your query it seems likes as your checking presence_of_element_located and which only check for it presence and not the visibility of the element.
Try replacing the presence_of_element_located with visibility_of_element_located.
There is difference between visibility_of_element_located and presence_of_element_located.
1) visibility_of_element_located
Checking that an element is present on the DOM of a page and visible. Basically it tests if the element we are looking for is present as well as visible on the page.
2) presence_of_element_located
Checking that an element is present on the DOM of a page. Basically it tests if the element we are looking for is present somewhere on the page.
Code:
el05a = WebDriverWait(driver, 120).until(
expected_conditions. visibility_of_element_located((By.ID, "id_of_button_a"))
)
el05a.click()
el05b = WebDriverWait(driver, 120).until(
expected_conditions. visibility_of_element_located((By.ID, "id_of_button_b"))
)
el05b.click()
visibility_of_element_located: Returns the WebElement once it is located and visible.
An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.
presence_of_element_located: Returns the WebElement if element is present on DOM and not even visible.
An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
Please change it from
expected_conditions.presence_of_element_located((By.ID, "id_of_button_a"))
to
expected_conditions.visibility_of_element_located((By.ID, "id_of_button_a"))

How to use findElements for img class?

On inspect element I can see number of records is 15 but when I tried using findelements it does not show all records.
Below is the tag:
<img class="md-user-avatar" ng-src="/../../resources/image_thumb.png" src="/../../resources/image4_thumb.png">
And I am using as below:
java.util.List<WebElement> elements = driver.findElements(By.xpath("//img[#class='md-user-avatar']"));
System.out.println("Number of elements:" +elements.size());
for (int i=0; i<elements.size();i++){
System.out.println("Radio button text:" + elements.get(i).getAttribute("value"));
}
But it returns me size as 1. And when I fire //img[#class='md-user-avatar'] in inspect elements it shows me 15 records.
try adding some implicit wait or Thread.sleep before doing findElementsand see if it works. If it does, then you will have to use explicit waits to make sure all images have loaded.
And if it doesn't, then in that case you will have to see that how all 15 images are visible manually.

Can't select option: element is found but invisible

I'm trying to automate a website which is not under my control, so I can't change its HTML and CSS. I need to select an option from a combo box.
I can successfully find a "select ../>" element but when I try to select an option via SelectByText, ByValue, ByIndex it results in the ElementNotVisibleException. The html is pretty complex on that page and I believe that developers assigned "display:none" by a css-style. I can navigate to the "div" which contains that combo box and click on it via Actions but it doesn't help to select an option after that. After such a click I see for a second the options on the screen and then the combo box collapses.
Is it possible at all to overcome such a problem?
Since Selenium API tries to be "user-centric" it will not allow interaction with non-visible elements. There are two approaches you can try:
1) Click on the select element, then perform an explicit wait for the option to become visible. This is useful if the page is using JavaScript to display the select options which can cause slight delay.
By bySelect = By.id("id_of_select_element");
By byOption = new ByChained(bySelect, By.xpath(".//option[contains(text(), 'text_of_option')]");
WebElement select = driver.findElement(bySelect);
select.click();
try {
// wait at-most 5 seconds for element to become visible
WebElement option = new WebDriverWait(driver, 5)
.until(ExpectedConditions.visibilityOfElementLocated(byOption)));
} catch(TimeoutException t) {
System.err.println("Timed out while waiting for dropdown to become visible: " + byOption.toString());
}
2) If the above doesn't work, you can be a little more invasive and execute some JavaScript to force the option to be selected. This is only recommended as a last resort.
public void selectDropdownByText(WebDriver driver, WebElement select, String text) {
((JavascriptExecutor) driver).executeScript(
"var select = arguments[0]; for(var i = 0; i < select.options.length; i++) {if(select.options[i].text == arguments[1]) {select.options[i].selected = true; }}", select, text);
}
ok, Element is not visible exception is thrown because of "user-centric" behavior of selenium,
In my working experience i found out that,
Selenium is not able to select element which are not visible to clients.
I mean can't select those who not appears on UI Window,
Still those are you can inspect on HTML DOM but cant access through selenium.
When those are visible on screen you can very well select those elements.
solution is before finding out select tag you must click on it to get visible full options tags.
Clicking makes all options that needs to be selected are now visible to clients.
Then you find that select element and then select options under select tag. when those List of options are completely visible on screen.

Waiting function for CSS element in Capybara

There are waiting and non-waiting functions in Capybara. I am trying to use the first as much as possible.
Is there a way to use find (or one of its derivatives) to look for a CSS element that appears asynchronously?
Unfortunately, function page.has_css? is a non-waiting function.
Your claim that page.has_css? is a non-waiting function is not correct. page.has_css? will wait up to Capybara.default_max_wait_time seconds for an element to appear on the page and return true or false based on whether or not the element is on the page within that time. Therefore, given Capybara.default_max_wait_time = 5
if page.has_css?("div#my_div")
puts "on page"
else
puts "not on page"
end
will wait for up to 5 seconds. As soon as a div with id of "my_div" is visible on the page it will print "on page". If a matching div doesn't become visible within 5 seconds it will print "not on page". If you want it to wait longer for a specific call you can override default_max_wait_time by passing the :wait option
if page.has_css?("div#my_div", wait: 10) # will wait up to 10 seconds
...
If rather than wanting a boolean response you want to ensure the element exists you can do any of
page.assert_selector(:css, 'div#my_div') # :css is the default so can usually be omitted
page.assert_css('div#my_div') # minitest
expect(page).to have_css('div#my_div') # RSpec
which will wait for the element to appear as previously, but raise an exception rather than returning false if the element does not appear
If you need the actual element you can use find which will also wait. So
el = page.find(:css, 'div#my_div') # :css is the default and can usually be omitted
will wait for the element to appear and return the element when found. If the element is not found within default_max_wait_time seconds it will raise an exception.
Note: Basically, the only non-waiting methods are all and first and even those can be made to wait if you pass in any of the count options (:count, :minimum, :maximum, :between), although the elements returned from them would still be non-reloadable and can therefore have further behavior effects if used for scoping, etc. Even methods like click_link, click_button, etc will wait since they are implemented as find(...).click, etc

Best way to automate loop in Selenium

I would like to automate some repetitive task - say submitting some form more than once. I am stumbling on the page load issues, so I want you to ask you how do you do it. Say, I want to submit ten different entries to our form. so I can do something like this:
for (int i =0; i<10; i++){
String name = getNextName();
String surname = getNextSurname();
Webelement newUserButton = driver.findElement(By.id("newUser")));
newUserButton.click();
WebElement name = driver.findElement(By.id("name")));
name.sendKeys(name);
WebElement surname = driver.findElement(By.id("surname")));
surname.sendKeys(surname);
WebElement submit = driver.findElement(By.id("submit")));
submit.click();
}
But I found out that if my test environment is slowlier, the above loop can crash. I tried to add some Thread.sleep() to the code, but if I want so submit, say, 200 entries, it can be really long to do the script.
Is there any function which can wait only the time when the form is ready?
Sounds like you need to add an explicit wait - see the Webdriver page Advanced Usage - Explicit and Implicit Waits
With the explicit waits, you can tell webdriver to wait until the form is in the ready state - typically a certain field is visible or reset (depends on what happens to your form when you click submit).
If you are using Selenium 2.0 you can make the WebDriver to wait until some action takes place by creating a WebDrivewWait object in you code. You can check out this link for more info - http://selenium.googlecode.com/svn/trunk/docs/api/java/index.html