I need to click on the dynamically generated element using Selenium WebDriver (Java API).
I'm waiting for this element to appear with WebDriverWait and then clicking on it. This click succeeds but the following click on the different static element freezes the whole test. Here is the code:
webDriver.get(alfrescoURL + "/share/page/create-document");
WebDriverWait wait = new WebDriverWait(webDriver, 10);
WebElement documentTypeList = webDriver.findElement(By.id("template_x002e_create-document_x002e_create-document_x0023_default_documenttype-selected-form-button-button"));
documentTypeList.click();
WebElement listItem = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("yui-gen100")));
listItem.click();
// Choosing to create in new project
WebElement projectLink = webDriver.findElement(By.id("template_x002e_create-document_x002e_create-document_x0023_default_projecttype-entry1"));
projectLink.click();
documentTypeList.click() opens a drop-down list, listItem.click() chooses an item, projectLink.click() makes a choice in the group of radiobuttons. Test silently freezes on projectLink.click(). It looks like this click() infinitly waits for page reloading that happens by some reason while it shouldn't. (Disappearing of the list after choosing an item is made by javascript that doesn't make any AJAX requests.)
I think there is something about click() blocking i don't understand. It says in it's javadoc that it attempts to block only if it causes a page to load. Nevertheless here i get a block for some reason.
If i insert a thread sleep before projectLink.click() then test works fine. It agrees with a hypothesis that i get a infinite block on click().
Thanks in advance.
I've run into this before where the test runs faster than the drop down can contract and can't click the following element. Instead of using arbitrary sleeps (although in rare cases they are necessary), can you put in a wait for a class change in the drop down?
For example, if I want to wait for the drop down to contract before moving on, I'll wait for the class of the select to change from "active" to "closed". This, of course, assumes your HTML has these dynamic classes in place.
Another possibility is to set an implicit wait, giving yourself enough padding for instances like these:
driver.manage().timeouts().implicitlyWait(1000, TimeUnit.MILLISECONDS);
I would suggest that you try other click options too:
a) Actions#click()
b) Javascript click()
If any of those click works then it means the issue is with the selenium's WebElement Click method which needs to be reported.
Related
I have this error "element not interactable" When I try to click a drop down list with selenium. However in debug mode, when I inspect ( press F12 ) before the break points and I continue to run then the test is passed. So my question is Why the elements can be clicked and what should I do to prevent the situation again. Many thanks!
You have to add wait / delay before accessing the elements to let the elements be fully loaded on the page before accessing them.
The simplest way is to add hardcoded sleep, like
time.sleep(5)
The better way is to use explicit way implemented by expected conditions.
Few things to note down,
Always launch browser in full screen mode.
driver.maximize_window()
this code should be written before driver.get()
Whenever you get element not interactable, try to use action chains to click or send_keys :
something like this :-
from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver)
action.move_to_element('your web element here').click().perform()
Make sure that using Selenium, the desired web element should be in Selenium view port.
in order to resolve this, you may have to scroll down to let Selenium know where exactly the element is.
I am using selenium 3.9.1 and java to automate testing of a web application. The web application has some dynamic content based on pressing of a button for example. The page refreshes whenever this button is clicked. A java script runs on button click and updates the DOM I think. At this time, when I try to access the button (which is visible on the page), I get a staleElementReferenceException.
Does Selenium automatically reload the DOM once it is changed? I am relatively new to selenium. I have researched into this and I have tried to refresh the page using driver.navigate().Refresh() to try to see whether this will solve the problem. It does not solve the issue.
Any pointers will be deeply appreciated.
Since the page has been refreshed, the button reference you have is to the button on the old page that no longer exists.
I'd say you need to get a new reference to the button on the refreshed page (eg call FindElementById).
If the page is refreshed all the items in the DOM are now stale. What this means is that all items found before the button press will have to be found again. Any attempts to use those items will more than likely be treated with a stale element exception.
However, if the button click mearilly affects items on the page without having to ask the webserver to give you a new page you could interact with the old items.
You could do something like this:
public void SaveAndAgainClick() throws Exception{
try{
clicksaveButton(); //method to click save button
WebElement someValue = driver.findElement(By.xpath("(//input[#name='someValue'])[1]"));
someValue.click();
}catch (StaleElementException e){
WebElement someValue = driver.findElement(By.xpath("(//input[#name='someValue'])[1]");
someValue.click();
}
}
If findElement gets staleElementError while looking for (//input[#name='someValue'])[1] then it will again try one more time in the catch block and most certainly find the element and clicks on it. Your test will pass if you follow this approach.
Here are the answers to your questions :
A java script runs on button click and updates the DOM I think : If you inspect the HTML of the element through Development Tools / Inspect Element the element attributes will reveal it all.
Consider the following HTML :
<input value="Click me" onclick="alert('Click!')" type="button">
In the given HTML as per the onclick attribute of this element, if you invoke click() method on the WebElement, an alert would be generated. Similarly the onclick attribute may invoke a JavaScript or Ajax which may bring-in/phase-out new/old elements from the HTML DOM
At this time, when I try to access the button I get a staleElementReferenceException : In this case you should induce WebDriverWait for the WebElement to be interactive before attempting to interact with the element. Else you may face either of the following exceptions :
StaleElementReferenceException
WebDriverException
ElementNotInteractableException
InvalidElementStateException
Does Selenium automatically reload the DOM once it is changed? Short answer, Yes it does.
Refresh the page using driver.navigate().refresh() : No invoking driver.navigate().refresh() wouldn't be a optimum solution as it may not invoke the intended JavaScript or Ajax properly. Hence the intended WebElement may not be interactive in a optimum way.
Is there a way to reliably wait for pages to load when using Behat with Mink using the Selenium2Driver?
I've inherited some legacy tests that wait like this:
Background:
Given I am on "http://test.example.com"
And I wait for "20000"
Given I click on the element with css selector ".button1"
And I wait for "30000"
Given I click on the element with css selector ".button2"
And I wait for "30000"
Given I click on the element with css selector ".button1"
And I wait for "10000"
i.e. just this single test takes 1minute 30seconds.
What I'd like to do is have a generic way of waiting for the previous click to result in a page load, without having to wait a large fixed amount of time each time.
All of the suggestions I can see for waiting for page load, all refer to checking that a particular page element is loaded.
However these tests run against a variety of legacy websites, where there isn't always a standard element that can be checked to be present, so I'm hoping to use a more generic method.
You can use a wait method with javasccript condition like:
/**
* #When /^wait for the page to be loaded$/
*/
public function waitForThePageToBeLoaded()
{
$this->getSession()->wait(10000, "document.readyState === 'complete'");
}
Another good practice is to have a method that waits for the element, if element is found returns the element object else it will throw an exception.
For the click method you can have something like this:
$this->waitForElement("css_selector")->click();
I am using selenium 2.46 (firefox driver) to develop an application. There are a lot of element.click() in my code. Sometimes that elements are not visible or not clickable make the application throws selenium exception.
To resolve that issue, i use WebdriverWait(driver, 10).until(...) for each single element which needs to be clicked.
My question is there is any other better way Or design pattern that can help me to solve the problem best.
Or at least i dont have to use WebdriverWait for each single element needs to be click().
You cannot avoid WebDriverWait. If you send a webdriver click command, webdriver will blindly assume that "element is clickable". You need to instruct webdriver to wait because your element is special and needs some synchronization before it can click on it. I don't think you need to do this for every other element. You can incorporate ExpectedConditions so that you can keep your code snippets manageable and small. So something like,
WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.elementToBeClickable(By.id("foo"))).click();
The other option you can try other than clicking is hit enter on respective element, for that you can refer ID of that element.
driver.findElement(By.id("elementid")).sendKeys(Keys.ENTER);
use implicit wait instead of explicit wait and give the expected condition till the element doesn't visible on screen.
for more info you can check
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#invisibilityOfElementLocated-org.openqa.selenium.By-
Hope this will help you
After implementing filepicker.io, some of our Selenium regression tests have started failing. The failures (intermittent, but more often than not in some circumstances) are that clicks are ignored on WebElements found via XPath queries. e.g.
driver.findElement(By.xpath("//a[text()='Demo data']")).click();
Adding a Sleep(2000) between findElement() and click() generally resolves the problem. (I say generally because Sleep(1000) was mostly enough, until it wasn't, so I made it Sleep(2000)...)
Checking element.isDisplayed() has not helped. The problem disappears if we stop including the filepicker.io JavaScript file.
Is it something to do with filepicker.io introducing an IFRAME? We have also noticed that JQuery's document.ready() seems to be now invoked twice.
As usual with this kind of problems, you are trying to find an element that is not yet available on the page due to AJAX request still downloading/processing it. You need to wait for the element to appear on the page.
There are three ways to do this:
Using sleep(). This is the discouraged way. You should not use hardcoded sleeps, because you'll either wait too long (making the tests unnecessarily slow) or too short (failing the test).
Use Implicit wait. That will always wait for an element if it's not found.
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Use explicit wait. That enables you to wait explicitly for one element to (dis)appear / become available / whatever.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Demo data")));
We now run this code first after opening any page that includes filepicker.js:
while (FindElementsMaybeNone(By.cssSelector("#filepicker_comm_iframe")).size() == 0)
Sleep(50);
while (driver.switchTo().frame("filepicker_comm_iframe") == null)
Sleep(50);
driver.switchTo().defaultContent();
We guess that filepicker's dynamic IFRAME insertion is discombobulating Firefox or Selenium. I'm not marking this as the answer because I don't really know why it works.