I run a test where I have to dismiss a warning that is a DIV that overlays the whole page. First I send a click to a button that adds something, then a warning is displayed. Finally I enter a string in a field
The code looks something like this
SeleniumLibrary.Click element add_button
Wait Until Element is visible warning-overlay-div
SeleniumLibrary.Click element dismiss-warning
SeleniumLibrary.Click element something-else
Running this code results in an error message:
WebDriverException: Message: unknown error: Element <input
type="text" class="upperCaseClass modified" id="something-else"
maxlength="15" style="width: 143px; text-transform: uppercase;"> is
not clickable at point (230, 679). Other element would receive the
click: <div class="warning-overlay-div" style="width: 100%; height:
853px; z-index: 2003;"></div>
That is, I can't click in something-else because warning-overlay-div is on top of it.
Ok, so I added a check to make sure the warning-overlay-div is gone between the the click dismiss-warning and the click on something-else. I have tried multiple variants but these three all give the same result
(from the log)
00:00:15.050KEYWORD SeleniumLibrary . Wait Until Element Is Not Visible ${warning-overlay-div}
00:00:15.003KEYWORD SeleniumLibrary . Wait Until Page Does Not Contain ${warning-overlay-div}
00:00:15.039KEYWORD SeleniumLibrary . Wait Until Page Does Not Contain Element ${warning-overlay-div}
It might take half a second or so for the overlay to disappear but as you can see, all these wait until they timeout after 15 seconds before they return success. I want to continue as soon as the warning-overlay-div is gone, not wait 15 seconds for that.
How do I check that this overlay is gone and then immediately continue?
You could potentially try using "Wait Until Keyword Succeeds" allowing yourself a custom retry timeout. Especially useful if you want to ensure the warning is removed from display in an appropriate amount of time.
Wait Until Keyword Succeeds ${retry} ${retry-interval} Element Should Not Be Visible ${warning-overlay-div}
${retry} = the amount of time overall to perform the check
${retry-interval} = the time between each retry
Time Formats
(I would have made this just a comment but I cannot until I have 50rep - this is just something that might be worth trying)
Related
I'd like to preface this by saying that I really tried looking here and anywhere else for an answer but without a succes.
Here is the problem:
I'm trying to automate a test for a web application that is loading a bigger amount of data and therefore has to be loading for a while. I have to wait for the page to load to do the next step and I'm trying to figure how to wait for the loading gif to be complete so that my tests can continue. The gif is a basic spinning thingy.
I would like to avoid using implicit wait time (cy.wait()) that is really only the last resort if noone is able to solve this.
What I found o far are these two functions:
cy.waitFor - this seems to be used mostly in situations, where you are waiting for an element to apper - I've tried this in different scenarios and works perfcetly but I havent been able to apply it here.
cy.waitUntil - this seems to be the thing I'm looking for but there is one huge problem. This function seems to have a timeout and I haven't been able to change it any other way than by changing timeouts globally for all the functions. If I set the global timeout to some longer period (minute +), then it works exactly how I would want it to work but obviously I dont really want to have such a long timeout for everything.
The way I see it, there are two possible solutions to this problem>
to change/turn off the timeout for the waitUntil function.
2)Or to somehow make it work with waitFor, because there seems to be no implicit timeout there and it just kind of waits forever for something to happen.
here is the code snippet of the situation:
cy.get('#load-data-button').click() // this clicks the button that stars the loading proces
cy.waitUntil(() => cy.get('body > div > my-app > billing > div > div > div.text-center > img').should('not.be.visible',) ) // this is the function that waits until the loading gif is invisible
I would be eternaly grateful for a solution, because unfortunatelly no one at my company is really a Cypress expert so they are not able to help.
Could you try something like:
cy.get([loading-spinner-identifier]).should("not.be.visible", { timeout: 60000 });
cy.get([an element that should now be visible]).should("be.visible");
It's a bit rough and ready, but I've used it when waiting for spinners to finish up. This waits a minute to see the spinner isn't there and then checks to see that something I'm expecting is there. I'd had varying success with this, but it has helped in some situations.
You can indeed use cy.waitUntil(). As you can see in the documentation of that package (https://www.npmjs.com/package/cypress-wait-until#arguments), the timeout that the function has is just the default (5000 ms) of an argument you can change it. You can even change how often cypress checks the condition you want, so if you do something like:
cy.waitUntil(() => cy.get('body > div > my-app > billing > div > div > div.text-center > img').should('not.be.visible'), {
errorMsg: 'The loading time was too long even for this crazy thing!',
timeout: 300000,
interval: 5000
});
...it will try for 300 seconds (5 minutes) each 5 seconds (just an example with very long timeout).
Also, maybe you can consider to wait until some element is visible after that loading spinner, instead of checking if it dissapeared. If you want to specifically test it, is fine, but if some element appears or becomes interactable after the loading, it could happen that is still not in the state you want, for a fraction of a second, after the spinner is not visible. If that is the case, I would avoid the checking of the spinner dissapearing in first place, unless it adds value to your test, and I would just wait for that element to be in the state you want (for example wait until some input is not disabled, element is visible, text appeared somewhere...).
Add positive and negative assertion to make sure loading spinner is visible.
Default Time is 4s for assert statement.
You can increase defaultTime to wait for assertion to validate by adding configuration in cypress.json
{
...
"defaultCommandTimeout": 4000,
...
}
const waitForSpinner = () => {
// First, make sure the loading indicator shows up (positive assertion)
cy.get('[data-qa="qa-waiting-spinner"]').should('be.visible')
// Then Assert it goes away (negative assertion)
cy.get('[data-qa="qa-waiting-spinner"]').should('not.be.visible')
}
For example, HTML:
<input type="hidden" name="ie" value="utf-8">
this element don't have child element, when I use code:
List<WebElement> childElements = ele.findElements(By.xpath("./*"));
the program uses a very long time (about 30s) return a result. And the result size is right which is zero.
So how can I resolve this problem? Thanks.
As per the documentation findElements() method is affected by the implicit wait duration in force at the time of execution. When implicitly waiting, findElements() method will return as soon as there are more than 0 items in the found collection, or will return an empty list if the timeout is reached.
Possibly you have set implicitlyWait() somewhere before this block of code and configured as 30 seconds. Hence the TimeOut occurs at 30 seconds.
I am trying to drag and drop an element over another but I am not able to do so. I am trying to perform the above operation on http://the-internet.herokuapp.com/drag_and_drop
This is my code
we1=driver.findElement(By.xpath("//*[#id='column-a']"));
we2=driver.findElement(By.xpath("//*[#id='column-b']"));
action.clickAndHold(we1);
action.moveToElement(we2, 450, 250);
Thread.sleep(3000);
action.release().build().perform();
Instead of action.moveToElement(we2,450,250) I have even tried using action.moveToElement(we2) and action.moveByOffset(450,250).
I even tried to perform this operation using Robot class.
robot.mouseMove(230, 170);
Thread.sleep(3000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseMove(450, 200);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Nothing happens in any of the above code. No error or exception is thrown and Code execution gets completed successfully.
After a lot of effort (hit & try :) ) I was able to find a solution for my problem. It is working fine for the site I mentioned as well as for other sites also where drag and drop functionality is present. Here is the solution:
we1CenterX=we1Points.x+we1Dimensions.width/2;
we1CenterY=we1Points.y+we1Dimensions.height/2;
we2CenterX=we2Points.x+we2Dimensions.width/2;
we2CenterY=we2Points.y+we2Dimensions.height/2;
robot.mouseMove(we1CenterX, we1CenterY);
waitForMe(1); //custom wait
robot.mousePress(InputEvent.BUTTON1_MASK);
waitForMe(1);
robot.mouseMove(we2CenterX, we2CenterY);
waitForMe(1);
robot.mouseMove(we2CenterX+100, we2CenterY-70);
/*Moving the cursor over the element before releasing
the mouse button solved my problem*/
waitForMe(1);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
waitForMe(1);
Implicit Wait : If wait is set, it will wait for specified amount of time for each findElement/findElements call. It will throw an exception if action is not complete.
Assume we set implicit wait to 10 secs. My question is will selenium move on to next step if findElement action is complete before 10 secs?
Yes. Setting implicit wait causes the driver object to wait for the set time if the element it is looking for is not found immediately. The driver object keeps polling the DOM every 500 milliseconds until it finds the element or the time-out expires.
This is the explanation from official Selenium documentation page:
An implicit wait is to tell WebDriver to poll the DOM for a certain
amount of time when trying to find an element or elements if they are
not immediately available. The default setting is 0. Once set, the
implicit wait is set for the life of the WebDriver object instance.
So, to answer your question in short, yes it continues with executing next steps as soon as it finds the element(s) it is looking for. You may also understand that to be the case from a simple experiment like #sircapsalot has shown in his answer.
Answer:
Yes. It will continue with the next step if it finds the element before the implicit timeout is hit.
Proof of concept:
#Test
public void test29800926() {
driver.get("http://ddavison.io/tests/getting-started-with-selenium.htm");
driver.manage().timeouts().implicitlyWait(30000, TimeUnit.MILLISECONDS);
System.out.println(driver.findElement(By.id("click")).getText());
}
Instead of waiting the total of 30 seconds that I set the implicit wait to (30000ms / 1000 = 30sec), it found it immediately and continued to print the text of the element.
I have been using Selenium WebDriver. I want to wait until the element is present on the webpage, for which i am using:
WebDriverWait wait = new WebDriverWait(driver, Long.parseLong(timeout));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
but my test get stucks in the second line if the element I am looking for, is not present and even beyond the timeout. Pls Help. Thanks.
Maybe:
- the element is present, so no exception is thrown
- then gets stuck because you are not doing anything else afterwards
Try printing smt after the until call. My guess is it will get printed.
Otherwise maybe it's the timeout:
It must be in seconds, not milli seconds.
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html#WebDriverWait(org.openqa.selenium.WebDriver, long)
I got it worked. I changed the timeout from 60000 to 60 since it takes the second argument as seconds and not millisecs.