I need to wait for a modal to close so I am waiting for the absence of an element. I'm trying to do something like this:
browser.driver.wait until.stalenessOf(By.css '.modal-header')
Unfortunately Coffeescript has reserved until. So I tried using:
browser.driver.wait browser.driver.until.stalenessOf(By.css '.modal-header')
but it is undefined (until that is). browser.driver exists but it doesn't contain until.
How can I access the until object? Also, is there another way to wait until an element is no longer on the page?
You can use the isPresent() function instead:
browser.wait ->
not element(By.css '.modal-header').isPresent()
,
5000
NOTE: isPresent() will not return false until it has finished implicitly waiting for the element, so if you have set the browser.manage().timeouts().implicitlyWait property very high you may want to temporarily decrease its value.
Related
I'm learning GEB in IntelliJ and have two issues.
When I click button on the top of the page I'm redirected to very bottom of the page.
After this I need to do assertion that the site slided down.
I try to do assertion in this example:
assert page.element_on_the bottom.isDisplayed() == true
// element_on_the bottom {$('css_selector)
The above assertion always returns true even I don't click button to slide down.
I need to check if element is visible on the part of website which is actually displayed on my monitor screen. Is there a way to do this?
I try to use waitFor statement in example:
waitFor{page.element.isDisplayed()}
but it doesn't work:
geb.waiting.WaitTimeoutException: condition did not pass in 5.0 seconds (failed with exception)
instead of this I use:
Thread.sleep(3000) //which is not desirable here
and then my test passes. I think my element don't trigger any js or ajax script actions.
I'm not sure how to use waitFor that should wait for all elements to load.
Element doesn't have to be in view for is isDisplayed() to return true - it will return true as long as the element is visible on page, e.g. it's display property is not set to hidden. You will need to detect your scroll position using javascript because WebDriver does not expose scroll information. See this response for how to detect that scroll is at the bottom of the page and see this section of the Book of Geb for how to execute javascript code in the browser.
What is the exception and its stacktrace that you're getting from your waitFor {} call? It probably contains the clue on what is actually going on.
For your first problem, can you please try the following as displayed should work fine for the visibility and present should be good to check the presence of the css selector in the DOM:
waitFor { page.element_on_the bottom.isDisplayed() }
or
waitFor { page.element_on_the bottom.displayed() }
For the second problem, you need to edit your Gebconfig file, like below as the waiting time you have right now is 5 seconds that's why it's failing whereas your sleep time is way more than 5 seconds:
waiting {
timeout = 30
retryInterval = 0.1
}
or, you can also try that at the same line of the code as below:
waitFor (30, 0.1) {page.element.isDisplayed()}
Please let us know if that worked fine or not! On another note, why don't you simply write the function name from the imported class instead of always writing className.functionName()? Best of luck and Cheers!!
I've got an application which I want to test with selenium/codeception. It has a lot of ajax function which changes the pages (show/hide sections of the page) which codeception at the moment doesn't handle well.
The problem I am having is I want to click on buttons/elements which either
are already on the page (ajax calls finished early)
which are not yet on the page (waiting for ajax response)
If I use waitForElement() it only seems to works in the second case (it waits for the element to appear and continues) but if the element is already present waitForElement will timeout and fire an Fail.
What I am looking for is a seeOrWaitForElement() function but I can't figure out how to insert logic in codeception.
Is this function available somewhere or how can I solve this problem in another way?
You could use
waitForJs("return document.querySelector('".$element."') != null", $seconds);
which will wait until the element exists (and returns instantly if the element already is present).
Codeception introduced a feature called SmartWait in version 2.3.4 which seems like an elegant solution to your problem. Note that it does not work for all kind of locators.
From the Codeception documentation:
SmartWait
since 2.3.4 version
It is possible to wait for elements pragmatically. If a test uses element which is not on a page yet, Codeception will wait for few extra seconds before failing. This feature is based on Implicit Wait of Selenium. Codeception enables implicit wait only when searching for a specific element and disables in all other cases. Thus, the performance of a test is not affected.
SmartWait can be enabled by setting wait option in WebDriver config. It expects the number of seconds to wait. Example:
wait: 5
With this config we have the following test:
<?php
// we use wait: 5 instead of
// $I->waitForElement(['css' => '#click-me'], 5);
// to wait for element on page
$I->click(['css' => '#click-me']);
It is important to understand that SmartWait works only with a specific locators:
#locator - CSS ID locator, works
//locator - general XPath locator, works
['css' => 'button''] - strict locator, works
But it won’t be executed for all other locator types. See the example:
<?php
$I->click('Login'); // DISABLED, not a specific locator
$I->fillField('user', 'davert'); // DISABLED, not a specific locator
$I->fillField(['name' => 'password'], '123456'); // ENABLED, strict locator
$I->click('#login'); // ENABLED, locator is CSS ID
$I->see('Hello, Davert'); // DISABLED, Not a locator
$I->seeElement('#userbar'); // ENABLED
$I->dontSeeElement('#login'); // DISABLED, can't wait for element to hide
$I->seeNumberOfElements(['css' => 'button.link'], 5); // DISABLED, can wait only for one element
I used waitForJS from the docs and it worked. Example:
$I->see('Jane Doe', '#table tbody tr');
$I->click(['css' => '#reload-ajax']); // Ajax trigger here
$I->waitForJS("return $.active == 0;", 60);
$I->see('John Doe', '#table tbody tr');
What is the best way to wait for an element to appear on a web page? I have read that we can use implicit wait and functions like webdriverwait, fluentwait etc and last but not the least thread.sleep()...which i use the most but want to stop using at all.
My scenario:
User logs in to a website...website checks the credentials and provides an offer to the user in the form of an overlay (kind of popup but not a separate window). I need to verify text on the the overlay.
There is a time gap between user signing in and the overlay getting displayed. what is the best approach so that selenium waits only till the time the element is not visible. As the overlay is not a separate page but part of the main page, implicit wait does not work at all.
All suggestions are welcome...:)
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(By.id("optionsBuilderSelect_input")));
I'm a professional scraper (http://nitinsurana.com) I've written 30+ softwares using selenium and I've never faced any such issue, anyways above is a sample code.
All I can think of is that what until condition has to be checked because many a times elements are already visible, but they are not clickable and things like that. I guess you should give different options a try and I hope you'll find the one required.
Always start by using a implicit wait. I think Selenium defaults to 5 seconds and so if you do a driver.findElement(), the implication is that it will wait up to 5 seconds. That should do it. If you are experiencing a scenario where the time it takes is unpredictable, then use FluentWait (with the same 5 second timeout) but also using the .ignoring method and wrap that inside a while loop . Here is the basic idea:
int tries=0;
while ( tries < 3 ) {
//fluent wait (with .ignoring) inside here
tries ++1;
}
public boolean waitForElement(WebElement ele, String xpath, int seconds) throws InterruptedException{
//returns true if the xpath appears in the webElement within the time
//false when timed out
int t=0;
while(t<seconds*10){
if(ele.findElements(By.xpath(xpath)).size()>0)
return true;
else{
Thread.sleep(100);
t++;
continue;
}
}
System.out.println("waited for "+seconds+"seconds. But couldn't find "+xpath+ " in the element specified");
return false;
}
You could wait for the presence of the element to appear as follows:
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.id("someId")));
I am using Selenium to get div value, but the fallowing code is not waiting for the page, just for URL. I used time.sleep, which is very primitive and totally not flexible. I want to change it on the explicit, but I am not too experienced in Python and I have a problem with that.
The website name has been changed just in case :
def repeat():
import wx
while True:
botloc = driver.find_element_by_id('botloc').text
print botloc
botX,botY = map(int,botloc.split(','))
print botX
print botY
wx.Yield()
def checker():
if driver.current_url == 'logged.example.com':
time.sleep(5)
repeat()
else:
checker()
checker()
How can I replace time.sleep with something flexible to wait the shortest time as possible after the page will be loaded? How to use explicit correctly with my code?
I know that's possible with using an element from the website, but I can't write anything sensible, I just need an example.
Is possibility to use element_by_id('botloc') for wait till it will be visible then start repeat() ?
How can i replace time.sleep with something flexible to wait shortest
time as possible after the page will be loaded?
I suppose you use get(url) to load the page. Generally you don't have to do anything, WebDriver automatically waits until page is being loaded. So you can remove time.sleep(). However there are some issues reported when loading the page using get with firefox driver, because of that you will have to wait for some target element which is supposed to be in the loaded page as mentioned below.
How to use explicit correctly with my code?
Have you checked Selenium webdriver documentation ? you can wait for botloc element explicitly as below
//assuming you have a valid webdriver reference
//Ex: DEFAULT_WAIT = 10 means
//waits up to 10 seconds before throwing a TimeoutException or if it finds the element will return it in 0 - 10 seconds.
element = WebDriverWait(webdriver, DEFAULT_WAIT).until(EC.presence_of_element_located((By.ID, "botloc")))
Refer this page for more information
Ive got an problem currently on an mobile site that i'm running directly in my pc's firefox browser. Everytime a button is clicked, the page reloads, thus resetting my variables. I've got this script:
// ==UserScript==
// #name trada.net autoclick 55_1min_mobile
// #namespace airtimeauction auto click
// #include http://www.trada.net/Mobile/
// #version 0.1
// #description Automatically click // ==/UserScript==
var interval = 57000;
var bidClickTimer = setInterval (function() {BidClick (); }, interval);
var numBidClicks = 0;
function BidClick ()
{var bidBtn1=document.getElementById("ctl00_mainContentPlaceholder_AirtimeAuctionItem7_btn_bidNow");
numBidClicks++;
if (numBidClicks > 500)
{
clearInterval (bidClickTimer);
bidClickTimer = "";
}
else
{
bidBtn1.click (1);
}
};
BidClick();
It should click the button every 57 seconds, but the moment it clicks the button, the page reloads, thus resetting the variables. How can i get greasemonkey to "remember" or carry over the variables to the next page/script when it reloads? Will it have something to do with GM_setValue? It will only be this few variables, but the second problem or question wil be, will it subtract the few seconds it takes the page to reload from the "57" seconds? How do i compensate for that?
In addition to GM_setValue...
you also can use the new Javascript "localStorage" object, or a SQL Javascript API.
The advantage of the SQL approach is it is very meager in its resource consumption in a script (think about it; rather than concatenating a humongous string of results, you can tuck away each result and recall it if needed with a precise query. The downside is you have to set up a SQL server, but using something like SQLite that's not a big deal these days. Even postgres or mysql can be quickly spun on a laptop...
Yes, I think you have to use GM_setValue/GM_getValue.
And if you have to do something exactly every 57 seconds, then calculate the time when the next action should take place after the reload, and store it using GM_setValue.
When your script starts, read first if the next action is stored, if it is, use that time to schedule the next action, and calculate the time for the action after that, and so on...
GM.setValue will set a value indefinitely and is scoped to the script, but will work if your script runs across multiple domains.
window.localStorage will set a value indefinitely and is scoped to the domain of the page, so will not work across domains, but will work if you need several GreaseMonkey scripts to access the same value.
window.sessionStorage will set a value only while the window or tab is open and is scoped to only that window or tab for that domain.
document.cookie can set a value indefinitely or only while the browser is open, and can be scoped across subdomains, or a single domain, or a path, or a single page.
Those are the main client-side mechanisms for storing values across page loads that are intended for this purpose. However, there is another method which is sometimes possible (if the page itself is not using it), and can also be quite useful; window.name.
window.name is scoped to the window or tab, but will work across domains too. If you need to store several values, then they can be put into an object and you can store the object's JSON string. E.g. window.name = JSON.stringify(obj)