I have been testing with element.IsPresent(), for some reason my test start failing when trying to do browser.wait(element(by.id('id').IsPresent()). It never get away from the wait, even the element being present.
I started using the code with protractor.ExpectedConditions and it start working. just want to know what is the difference between one and the other.
Here is the code with the Expected Conditions.
const EC = protractor.ExpectedConditions;
const ele = element(by.id('id'));
return browser.wait(EC.presenceOf(ele));
What is the main difference between one and the other? I have search in google but haven't found a proper answer.
If you take a look at this answer on another question you will see that both presenceOf() and isPresent() are almost entirely the same. The primary difference being that presenceOf() wraps around isPresent() and returns a Function rather than a Promise.
So why is this important? Well it has to do with how browser.wait() works. If we take a look at the docs we can see that it:
Schedules a command to wait for a condition to hold or promise to be resolved.
This means that if you pass a Promise to browser.wait() it will only wait until that Promise is resolved before continuing on and executing further commands (it doesn't necessarily matter if it resolved true or false). Whereas if you pass a Function to it, it will wait until that condition "holds" before continuing.
Additionally, you can specify a custom timeout parameter for the browser.wait() method. If you do not specify a timeout it will default to 30 seconds according to the docs. I believe this is why you felt that the wait never resolves when using isPresent() (it was likely just taking 30 seconds).
What I would suggest to do is use isPresent() when you expect an element to be present at a specific moment in time and use presenceOf() when you want to wait for an element to be or become present.
Here's an example of how I would use the two:
const EC = protractor.ExpectedConditions;
const ele = element(by.id('id'));
browser.wait(EC.presenceOf(ele), 5000); // Waits a maximum of 5000 milliseconds (5 seconds)
expect(ele.isPresent()).toBe(true); // Expects this element to be present **right now**
Related
I want to test a feature that requires a pageload to be updated. Since selenide only checks if the element has appeared without reloading the page, it will not pick up on the updated state.
I am currently doing it like this:
element(byAttribute("type", "submit")).click()
try {
element(byText("some specific text")).shouldBe(visible)
} catch (e: com.codeborne.selenide.ex.ElementNotFound){
refresh()
element(byText("some specific text")).shouldBe(visible)
}
This is bad in multiple ways:
it catches an error, which is not intended to be caught (otherwise it would have been an exception)
it triggers side effects, like creating error-screenshots
it only retries exactly once
it waits the full first timeout, which may not even be needed. e.g. maybe it could have refreshed immediately then be successful
in case you are wondering: the feature in question is related to a cache being warm or cold. Forcing the cache to be cold at the beginning of the test would probably be possible, but it would also add a lot of complexity (e.g. interacting directly with the database), which I would like to avoid.
I'm not familiar with selenide, but I think you can fix at least several problems you listed with the following changes:
Put the try-catch block inside a while true loop so as if the element found visible break is applied, otherwise continue looping.
In case you want to avoid infinite loop add some counter there so that in case after X iterations the element was not found visible - leave it.
Decrease the timeout for waiting for the expected condition. You did not share here where you define if, so I don't know how to change that.
The first paragraph changes could be something like the following:
element(byAttribute("type", "submit")).click()
for(int i=0;i<100;i++){
try {
element(byText("some specific text")).shouldBe(visible)
break
} catch (e: com.codeborne.selenide.ex.ElementNotFound){
refresh()
element(byText("some specific text")).shouldBe(visible)
}
}
I'm reading the docs on Implicit Waiting with Webdriver but I'm not sure I totally understand.
As I understand it,
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
This will put in place a timeout of 10 seconds whenever looking up any element.
What, exactly, does this do?
Does it mean that when looking up any element, I will wait 10 seconds every time, even if the element is present? Or, when looking up any element, will the driver give the browser a 10-second grace period to load the element before deciding the element missing?
Since this is applied to every element, am I correct in supposing that this is just executed only once for each instance of Webdriver?
This will look for the element up to 10 seconds, trying to locate it every 500 milliseconds (default timeout).
From the docs
Specifies the amount of time the driver should wait when searching for
an element if it is not immediately present.
When searching for a
single element, the driver should poll the page until the element has
been found, or this timeout expires before throwing a
NoSuchElementException. When searching for multiple elements, the
driver should poll the page until at least one element has been found
or this timeout has expired.
The locating algorithm is described in W3C specifications
The Find Element, Find Elements, Find Element From Element, and Find
Elements From Element commands allow lookup of individual elements and
collections of elements. Element retrieval searches are performed
using pre-order traversal of the document’s nodes that match the
provided selector’s expression. Elements are serialized and returned
as web elements.
When required to find with arguments start node, using and value, a
remote end must run the following steps:
Let end time be the current time plus the session implicit wait
timeout.
Let location strategy be equal to using.
Let selector be equal to value.
Let elements returned be the result of trying to call the relevant
element location strategy with arguments start node, and selector.
If a DOMException, SyntaxError, XPathException, or other error occurs
during the execution of the element location strategy, return error
invalid selector.
If elements returned is empty and the current time
is less than end time return to step 4. Otherwise, continue to the
next step.
Let result be an empty JSON List.
For each element in elements returned, append the serialization of
element to result.
Return success with data result.
implicitlyWait is defined once for the WebDriver and last its lifetime.
Defines a wait time globally in your project. Your telling your driver to wait for n number of seconds before selenium throws an exception. If element is found earlier then the n number of seconds you mentioned, webdriver will click it once its available and dont wait for the maximum n number of seconds. It does have to wait before it throws an exception.
When i write some implicit wait like 10 sec and then for a element i give 5 seconds time in explicit wait...then will the implicit wait become zero and only wait for 5 sec or it will add the implicit wait time as well means will it wait for 15 secs
Let me answer you one by one:
Whenever you put an ImplicitlyWait Selenium will perform that wait after each action. So it becomes contagious.
When you put an Explicit Wait, those are defined as per certain conditions like "visibility of an element" within until block.
So each type of wait behaves in their own fashion just by the way you implement them.
Once you assign timeunits for each type of wait, they are followed in execution. They never gets added or substructed.
ImplicitlyWait is mentioned only once within your code. This instruction is for the Webdriver to follow. ImplicitlyWait have no effect on any element in particular.
Where as Explicit Wait is assigned to ask the Webdriver to wait for a defined time period (e.g. 5 seconds) with a until condition which specifies the state of an element (e.g. element_to_be_visible) the Webdriver should look for.
Now answering your question: 10 seconds ImplicitlyWait for a element is not a valid statement. Explicit Wait of 5 second you have to put for a certain state/behavior of the element (e.g. element_to_be_clickable). If the element doesn't shows that behavior within the defined time slot Selenium will throw an exception.
Let me know if this answers your question.
I face some issue whereby the test just hang there (Browser open and not able to proceed next test) due to my test statement not able to find the element.
My TestStatemet like this:
driver.findElement(By.xpath("//input[#name='AID' and contains(#value,'sampleDataThatwillNotFound')]"));
The test hang only when find by XPATH, no issue when find by NAME/ID. I had set the timeout to 60 seconds, after the 60 seconds, it still hang.
Anyone out there facing this issue before? or Anyone got any idea how to resolve this issue?
Well, I had the same problem and found this in webdriver api doc:
findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.
So I use something like
List<WebElement> found = driver.findElements(By.id("elementid"));
if (found.size() > 0)
{
// get the 1st element
} else {
// time out
}
to resolve this issue. And implicit timeout works fine with findElements in my case.
I was having the same issue after upgrading Firefox (25 to 26) and Selenium (2.37.1 to 2.39.0 driver + server). No Exception thrown, hang forever, etc. It got "solved" by removing the implicitlyWait declaration. Not a real solution but good enough in my case.
try this one locator
driver.findElement(By.xpath("//input[#name='AID'][contains(#value,'sampleDataThatwillNotFound')]"));
I got some feedback from darrell from Google Groups, and i agree with him, below is his feedback:
https://groups.google.com/forum/#!topic/webdriver/Vt0DuQHOAg8
*I haven't seen these locators hanging but anything is possible.
Generally, if the DOM is large and/or complex a combination locator
(one with contains plus an and) could make it really slow. My general
experience has been the more complex the locator the long it takes.
The longer it takes the more likely you will see a
NoSuchElementException. It could be that something else you are doing
is causing a second problem, i.e. the hanging.
An and statement is multipling. So #name='AID' is relatively fast.
There is no substring checking. It either matches or it does not. So
this locator will run in order n, where n is the number of input tags.
A locator like contains(#value, 'someString') will have to scan each
tag for each attribute for a match to every possible substring. If the
contains() is implemented well it could be a little faster than brute
force but the type of data in the DOM will determine how long this
search will take. It will definitely be slow.
Now if you take the contains() search (relative slow) and the exact
match (relatively fast) then look for the AND of the two matches, you
are multiplying them. Two exact matches are going to be order n times
order n (or n squared). This is not good. An exact match times a
contains is REALLY bad. Depending on the DOM it could be order n
cubed. This means if n takes 10 seconds, n cubed is 10 * 10 * 10
seconds (1000 seconds or over 16 minutes). If the DOM causes things to
be even worse you could be looking at exact match is seconds and
combination is hours.
Darrell*
So to solve this issue, i think it is time to enforce the development team to apply to the common development practise to put in unique id for every element/control. So that the test automation script can directly perform any verification/input thru ID, instead of xPath.
I had try some answer above, but still having same issues.. i switch back to old firefox version 17.0.3 .... everything just solve.. abit funny.. those that facing the same issue you can try at FF Version 17.0.3
Is this possible?
I have a file in which a movie clip is launched when the user roles over another element. To make the user experience more pleasant this happens after a 3 second delay using setInterval. Is there a way of stopping and resetting this time if the user rolls off the element before the 3 seconds is up?
var xTimer = setInterval(wait, 3000);
function wait(){
show('all');
play('all');
clearInterval(xTimer);
}
Above is the code I have used to set the delay, and below is the code I had assumed would interrupt and reset the timer.
invisBtn.onRollOut = function(){
rollover_mc.gotoAndStop(1);
stop();
clearInterval(xTimer());
trace('off');
}
Any help on this would be massively appreciated.
First, the setInterval & clearInterval functions use a Number variable to work.
setInterval() returns a Number variable, and clearInterval() takes that Number in parameter to remove the previous started interval. Here you seem to keep the interval ID inside a function variable instead of a Number one.
Thus, clearInterval(xTimer()); should in reality be clearInterval(xTimer); (without the parenthesis after xTimer).
And secondly, so you can use it in the invisBtn.onRollOut function, just be sure that the xTimer variable is scoped correctly (not inside a function where the invisBtn.onRollOut isn't also), and not on different keyframes of the timeline (timeline keyframes in Flash tends to forget the code you've written on it as soon as the reading head passes onto a new keyframe of the layer which has the code on it).
Feel free to ask more details if you need !