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.
Related
This question is conceptual, and I am asking on this help forum in order to look for a lead to go off and research, and will not contain any code examples other than one to demo what I am using to grab the element value described below, here is some background:
The test I am writing involves signing in to the same application using two driver sessions each of which open a webdriver chrome window. Each one logs in to our app as a different user, and then from one, you can see the "online/offline" status of the other.
We use one class of methods for the first session, and another class of methods for the second session, and if a feature file title appears in a third class containing a LinkedList of strings, then the system knows to open the second session, and we then call methods in the relevant class to run jobs in the appropriate window.
In the current test case I am creating, the objective is to assert in a window we shall call "A", that the element being checked has a specific CSS property, namely its color property. It is grey when the other window that we shall call "B" does not have focus, and it is green, meaning online, when it does have focus, and is logged in.
The logged in side I can take care of, and manually I can see that it is working, but after this log in, when I use from the class that runs commands for window "A" the following line, directly after the last line that directs window "B" to have focus and do something, then it writes the value for "offline" in to the variable shown, as the window "B" has had to lose focus in order to check the element in window "A".
String color = seleniumClient.getWebDriver().findElement(By.xpath("//div[#id='user-content-button']/span/span")).getCssValue("background-color");
I am not able to influence the development of our app, as I am a QA, but I am asking if anyone knows how to maybe freeze the state of the chrome session for window A showing window B to be online before I run the above line, or any other way that I can get my test to see the correct state when the focus is not on the window "B"
Thanks.
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
Hello Fellow Stack Overflow members and coders,
I am trying to make an automation script using Selenium WebDriver on Instagram where I want to follow every member a particular account is following.
I am stuck at a point where after navigating to user's profile (who's follower I want to follow) when I click on "following" link a new window opens and it contains all the members this user follows (as shown in following screenshot):
Window opened after clicking "following" link
Now as you can see in above window only first few followers are initially loaded and then as you keep on scrolling down the users keeps on getting loaded.
I am completely lost here on how can I move the focus to this new jquery kind of window and keep on scrolling down until the full list is loaded and then find once full list is loaded, click on follow button for each user.
Your help would be really appreciated in this regard.
I have tried various options like moving the mouse over to the window and clicking at blank location and then using Keys.Arrow_Down multiple times, finding first Follow button and then keep on pressing down button etc but it doesn't seem to be right approach and it doesn't work. Kindly help me solve this issue.
what if you...
Using a while, get all the visible elements in a list, move using JavascriptExecutor to the last of the element in the list, and keep getting the elements(doing the same, moving to the last pos in the list) until you reach the number(this is the while condition) of following(or following-1 if he/she follows you)
(JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElementInList);
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 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)));
}