I have a scenario where I am not able to proceed further:
I have two buttons on the page (both the buttons are in the same frame). I'm using an Iterator for the Button 1. When we click the Button 1, it makes an AJAX call. I see a mouse loading animation for a second and then the product is added to the cart.
Say, if I have 5 buttons of the same type & want to click all the 5 buttons, when I use the iterator to click the 5 buttons, the control is going out of the loop instead of clicking the second button.
Iterator<WebElement> button1 = T2.iterator();
while(button1.hasNext()) {
button1.next().click();
Thread.sleep(10000);
}
driver.findElement(By.id("button2 id")).click();
If I use the Thread.sleep(), it's working fine. But I don't want to use that as its not the proper way.
The button2 id is also in enabled state, I wasn't able to use the Wait for the element to be enabled. When the execution comes to the button1.next().click(), i,mediately it's going to the next line, without completing the loop. If i print some text after the button1.next().click(), the text gets printed 5 times. But don't know why the button is not clicked.
Even tried implicit wait, but no luck.
What is the best way to avoid such kind of issue?
The proper way is to wait explicitly for the product to be added to the cart. Something changes on the page after the operation finishes, right? So wait for that change to occur! I don't know your webpage, obviously, but something along the lines:
// earlier
import static org.openqa.selenium.support.ui.ExpectedConditions.*;
// also earlier, if you want, but you can move it to the loop
WebDriverWait wait = new WebDriverWait(driver, 10);
Iterator<WebElement> button = T2.iterator();
while(button.hasNext()) {
// find the current number of products in the cart
String numberOfProductsInCart = driver.findElement(By.id("cartItems")).getText();
button.next().click();
// wait for the number of items in cart to change
wait.until(not(textToBePresentInElement(By.id("cartItems"), numberOfProductsInCart)));
}
Related
I am writing some UI automated tests with Java using Selenium page objects.
I'm having some problems with one element on the page. The element in question is a clickable panel which will expand once clicked and reveal some fields and other items of UI that were previously hidden. When the panel is clicked once more the the fields revert to being hidden again.
The problem I have is when I initiate the click on the panel it will sometimes show the previously hidden fields and other times it will show them but very quickly hide them again. This will then make my next action, to click one of the previously hidden fields, fail as the field is not present.
I have an explicit wait on both fields present using elementToBeClickable.
I'm thinking that the best way to tackle this is to write a return method that checks if the hidden field is there or not and if the method returns false then initiate the click to the panel again. I display if TRUE or FALSE is returned and I can some cases where FALSE is returned where this fix works as it goes on to expand the panel correctly but I still get cases where it doesn't work.
I'm hoping there is an easy way to solve this.
Below is my code:
//this is my method to click the pannel
public void clickPanel() {
WebDriverWait wait = new WebDriverWait(driver, 20);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(panelLink));
element.click();
//call another method to see if the hidden field is visible or not
boolean isHiddenLinkPresent = methodToCheckIfLinkPresent();
//show the results of if the field is hidden or not
System.out.println(isHiddenLinkPresent);
//if link is not present, try and click again
if (isHiddenLinkPresent == false){
element.click();
}
Im going to guess that your javscript hasnt executed on page before the click happens. You probably need to refine your wait code to make sure the js has definitely executed before Selenium continues. You can use a great big dirty
Thread.wait(10000);
to validate that assumption at cert parts of your code but dont leave it in place as that will obviously kill your test suite speed. Without seeing more of your code its hard to completely reproduce the issue locally so you might want to post some more code. Your wait methods for example and a snippet of the html and javascript.
Id also take a look at https://www.swtestacademy.com/selenium-wait-javascript-angular-ajax/
the above link gives some detail on waiting for js .. theres a javscript executor you can use to do that. HTH.
Yesterday I ask question how to deal with: "Element is not clickable at point - other element would receive the click" exception in Selenium WebDriver.
I receive several answers with this solution:
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id(...));
Yes, it has sense but in practice it doesn't work.
Below is piece of my code:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView();", categoryItem);
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(categoryItem));
categoryItem.click();
List<WebElement> selects = driver.findElements(By.tagName("select"));
Select ticketsSelect = new Select(selects.get(3));
ticketsSelect.selectByValue("2");
By addToBasket = By.xpath("//div[contains(text(),'Add to Basket')]");
Thread.sleep(1000);
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(addToBasket));
driver.findElement(addToBasket).click();
I had to put 1 second sleep before each wait until element to be clickable because without this it still throw exception that other element would receive the click.
My question is why WebDriver clicks this element if element is not clickable ?
ElementToBeClickable – An expectation for checking an element is visible and enabled such that you can click it.
But it seems that it doesn't imply that this element is not "hidden" under some other element, even if it's a transparent part of another tag. In my experience, this exception is mostly occur when you are trying to interact with a page, which currently loads, and you have typical loading div overlapping the whole page with loading icon, or in other cases when you have an open modal, which also often cover page with overlays transparent overlay, to prevent user from interacting with a page.
In this answer you can see that you basically have two options:
You can send a click event via JavaScript call. It will always work, but it's not something you want to do. If you want to test your page, you should always trigger real click events.
Wait. There is not much you can do. Something you just need to wait till your page fully loads. In a way maybe this will show you the slow parts of your application, which you can improve in a future
There's a menu item that I want to click.
However just before this click, in my test flow I have a modal open, which prevents clicking on the menu item. Also, when closed, the modal will fade instead of disappearing instantly.
What I do is close the menu item and then place a wait for the menu item to be clickable, before performing the click:
WebDriverWait wait = new WebDriverWait(getDriver(), time);
wait.withMessage(message);
try {
wait.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
Logging.logException(e);
}
clickOn(locator);
However this does not work, as I'm running each time into the following exception:
org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (158, 565). Other element would receive the click: <div class="globalpopup with-data slideout">...</div>
I also have Selenium set-up to take a screenshot each time an exception occurs and in the screenshot I can clearly see that the modal is in the process of fading out.
So the close button for it has been clicked, but at this point I'm thinking the wait should come into effect and pause execution until the modal fully disappears and the menu item can be clicked. Which does not happen.
Now I usually fix this by adding a bit of sleep time, as it's quite predictable how long it takes the modal to fade out. However I'd really like to figure out a more elegant solution, which can apply in all situations.
My understanding is that elementToBeClickable does not account for when the element is covered by another element, which I find quite silly. Is there a way to simulate such a wait (notCoveredByOtherElement), as it's exactly what I'd need?
P.S. I'm using Selenium 2.53. Have not tried v3 yet, although I'd happily make the effort to start switching to it if someone can confirm that this case is handled properly in this new version.
I also faced this issue number of time and tried some solution which always worked for me.
1-Updated chrome driver to latest one 2.23
2-Get the coordinate then click on the link or button
3-Try to click using Y coordinates
// Find an element
WebElement elementToClick = driver.findElement(By.xpath("Your xpath"));
// Scroll the browser to the element's Y position
((JavascriptExecutor)driver).executeScript("window.scrollTo(0,"+elementToClick.getLocation().y+")");
// Click the element
elementToClick.click();
// Find an element
WebElement elementToClick = driver.findElement(By.xpath("Your xpath"));
// Scroll the browser to the element's Y position
((JavascriptExecutor)driver).executeScript("window.scrollTo(0,"+elementToClick.getLocation().y+")");
// Click the element
elementToClick.click();
I have documented all in below link kindly check
Solutions for Element is not clickable in Selenium
Is there a difference between testing perspective and not usability, on clicking elements with selenium like this:driver.findElement(By.id("foobar")).click();
instead of using coordinates and the robot class.
Example: If an element is not clickable because of a bug, robot will not be able to click it. Will selenium be able to click it ?
Selenium tries as much as possible to emulate what a regular user can and cannot do. When you use findElement(...).click() Selenium will raise an exception if operation cannot be performed. For instance, if an element exists in the DOM but is not displayed, an exception will be raised. And note that Selenium's .click() will try to scroll elements. If you ask it to click an element that is not visible but could be visible by scroll it, Selenium will scroll to bring it into view.
Also note that Selenium will usually take the element's coordinates and perform a click at those coordinates. So the idea that a moving element will always be hit by findElement(...).click() (expressed in this answer) is incorrect. Using findElement minimizes the window between which the coordinates are acquired and the click event is sent, but it does not completely eliminate it. The reason that Selenium works with coordinates is, again, to reproduce what a user would do. The user would see the element, move the mouse to the coordinates of the element, and click on it. If the element has an transparent overlay over it, then the overlay will get the click, rather than the element. This works because Selenium clicks at the coordinates rather than send a click directly to the element that you selected with findElement.
If you are using Robot to perform the click, the stakes are roughly the same as above, with a few caveats:
Trying to click moving elements is more of an issue because the window of time between acquiring the coordinates and performing the click is greater.
Robot does not know how the DOM is structured so won't scroll elements for you.
Rogério Peixoto pointed out that you can use JavaScript to perform the click. This will cause the event handler for click to be called for the element, irrespective of whether a user would be in fact able to access the element. This can allow clicking on elements that are not otherwise clickable but I would not do this unless there are overriding reasons to do so. I've gone over the difference between Selenium's click and the JavaScript click in this answer.
If an element is not clickable because of a bug, robot will not be able to click it. Will selenium be able to click it?
It depends on what the bug is that is preventing the click. I would suggest that you use element.click() in almost all cases because it's more maintainable. For coordinate clicks, what if the element moves? Then you have to update your script with the new position where element.click() will just work. Another issue with coordinate clicking, what if your element moves and another one is in its place? That will likely cause your script to fail but will be very hard to track down. An example might be an unexpected popup that covers the element to be clicked. Now your coordinate click will hit the popup and eventually cause an error/failure. If you do element.click() you will at least get an error that another element would receive the click. You can then track down what is getting in the way from debugging.
Selenium clicks in my experience click an element within a browser window, where as Robot click seem to click whatever is on the desktop at the time. Personally I would recommend you try to use Selenium clicks where possible as you can specify the window in which you are clicking.
Using this:
driver.findElement(By.id("foobar")).click();
Means that you will click the element with the foobar id regardless where it is.
If you use coordinates, you won't be able to click the element if they change their position.
Updating answer due to your updated question:
I'm not quite sure where you're trying to get with this.
In Selenium, if the element is visible it will receive the click event, if not you'll have an exception.
You could force click it with javascript:
WebElement element = driver.findElement(By.id("foobar"));
((JavascriptExecutor)driver).executeScript("arguments[0].click();", element);
But it won't trigger the an eventual javascript event registered to that button, you would have to fire it manually.
I want to be able to click a logout button twice very rapidly like a user would?
WebElement logout = driver.findElement(By.id("dijit_form_Button_0_label"));{
if(logout.isDisplayed()){
logout.click();
I want to be able to click on the logout button twice at less than a second like a user would? Is this possible in selenium webdriver?
EDIT:
Make sure the dom is loaded
Like atri said, you could use the double click function according to This thread.
WebElement logout = driver.findElement(By.id("dijit_form_Button_0_label"));{
if(logout.isDisplayed()){
logout.doubleClick();
if you don't want to use the doubleClick function, I would recommend the ExplicitWait from Selemium
Selenium: Implicit and explicit Wait
If you want to do this manually, could add a delay between your click using javascript Thread and selenium wait.
Based on This thread
WebElement logout = driver.findElement(By.id("dijit_form_Button_0_label"));{
if(logout.isDisplayed()){
logout.click();
Thread.sleep(100);
logout.click();
}
Better way is to use ExplicitWaits which you means you will wait
exactly as long as some action happens or some element gets rendered
on the page.
- petr-mensik
An explicit waits is code you define to wait for a certain condition
to occur before proceeding further in the code. The worst case of this
is Thread.sleep(), which sets the condition to an exact time period to
wait. - Selenium