I'm using Quamotion to test an iOS application. My tests are failing from time to time because it looks like Find-Element can't find the element on the screen.
This seems to happen when I switch to a new window and the UI takes some time to load.
Is there any way make Find-Element wait for the UI to have loaded completely?
You can use Set-Timeout to set the implicit wait timeout. When you use Find-Element to find an element, for example Find-Element -xpath "//*[#name='Login']", the Quamotion WebDriver will attempt to find an element that satisfies that XPath expression for the amount of specified by Set-Timeout.
You should check whether Find-Element returns an actual element ID or not.
If you don't get an element ID, the timeout was hit and the element was not found. Try increasing the timeout.
If you do get an element ID, an element was found but:
It was not the element you expected. This can happen if you do a Find-Element almost immediately after Click-Element and the UI structure of the previous page was still in memory;
Another element matches your XPath expression. You can use Get-ElementRectangle to get the rectangle of your element and determine whether it's the element you expect or not
The element has been created in memory but has not been drawn on the screen. You can use Is-Displayed to determine whether your element has been drawn or not.
Related
I am trying to write an integration test in which I must check the visibility of an element on button click. The code works perfectly in one machine and failing in the other. The element is displayed until the data comes from the backend. So its visibility depends on the speed of the machine also. Is that the problem? This is the code:
assert page.has_css?('#my_element_id')
assert find('#my_element_id', visible: true)
But I am getting an error: expected false to be truthy.
Is there any other way to assert the visibility of the element?
You can also try:
assert find('#my_element_id').visible?
from: https://rubydoc.info/gems/capybara/0.4.0/Capybara/Element#visible%3F-instance_method
It does say however:
visible? ⇒ Boolean
Whether or not the element is visible. Not all drivers support CSS, so
the result may be inaccurate.
I assume you are talking about whether #my_element_id is visible.
EDIT:
If you are waiting for an element to be visible first before checking for the element with the id #my_element_id this posts might be helpful:
How to make Capybara check for visibility after some JS has run?
So you could wait for the backend data to come through then check visibility. If you are try to check that it is visible before that data, I am not quite sure, it seems like it would depend on the machine's internet connection to me.
Don’t use plain assert, use the assertions provided by Capybara which include retrying behavior
assert_css(‘#my_element_id’)
By default that would check only for visible elements, but if you’ve set Capybara.ignore_hidden_elements = false (don’t do that, really dont) then you would need to also pass the :visible option
Note: you may still have issues if it’s only visible for a very short time - in that case if you’re using Chrome you can set the network conditions to very slow in order to increase the time data takes to return
I'm writing test cases in Robot Framework using AppiumLibrary.
I'm importing AppiumLibrary with the following code to get a screenshot whenever something goes wrong:
AppiumLibrary.__init__(self, run_on_failure="Capture Page Screenshot")
Is there a way to NOT take a screenshot for a specific keyword? This keyword will for example create 15 screenshots (if it's not able to find Donald):
Wait Until Keyword Succeeds 30 seconds 2 seconds Element Text Should Be Username Donald
There is nothing built-in to do what you want. There are many solutions, however.
One solution would be to turn off capturing the keyword (using register keyword to run on failure) immediately before calling wait until keyword succeeds. You could then call wait until keyword succeeds, and then turn capturing back on afterwards.
Or, you can register your own custom keyword instead of Capture page screenshot. Your own keyword can use whatever logic it wants to determine whether to capture screenshots or not. For example, it could look for a global variable that tells it whether to capture or not.
You could also write your own keyword to use in place of wait until keyword succeeds which also uses one of the other two solutions.
For example, create a keyword named wait until element contains text which turns off the capturing, runs wait until keyword succeeds, and then turns it back on. Then, in your test you still just have a single statement:
wait until element contains text Username Donald
Register Keyword To Run On Failure NONE
${Status} Run Keyword And Return Status Wait Until Keyword Succeeds 30 seconds 2 seconds Element Text Should Be Username Donald
Register Keyword To Run On Failure Capture Page Screenshot
IF ${Status}==False
Element Text Should Be Username Donald
END
-Lets Walkthrough whats happening in the above code snippet
Register Keyword To Run On Failure NONE (To avoid multiple
screenshots when Element Text Should Be keyword fails in the
next line )
After waiting for 30 seconds it will return status If the keyword passes it returns pass and if it fails it returns fails and gets stored in status variable (Remember no screenshots are generated in this process since we turned off screenshots in point 1.)
Again setting back Capture Page Screenshot Keyword on Failure to take screenshot.
Lastly one more time it will run Element Text Should Be and if it fails it generates a screenshot and keyword fails.(Since ${Status}==False that means it will run only if Wait Until Keyword Succeeds keyword fails otherwise this IF block will not run since our keyword already passed)
I've got an integration test here which is passing flawlessly using the poltergeist driver every time, but when I run this test using Selenium it passes on average 3 times and fails 1 time.
def fill_in_inclusion_criteria
find("div.measure#age label[for='16']").click
find("div.measure#substance_use_met label[for='1']").click
find("div.measure#participant_consent label[for='1']").click
click_link("Next")
end
When it fails, the error that I get back is this
expected to find css "div.measure#participant_consent" but there were no matches. Also found "", which matched the selector but not all filters.
The participant consent button appears when div.measure#age label[for='16'] is clicked, so it's dependent on Javascript. I see this happening in Firefox most of the time, but when it errors, the div isn't visible on the page.
It seems like it's not waiting for the element to display on the page before clicking it, but I thought that wrapping it in a "find" waits for the element to be visible on the page before trying to click it?
Any idea why this could be happening?
The one confusing thing with your question is that the error message you posted isn't actually for the code you've shown, since if it was the error message would be expected to find css "div.measure#participant_consent label[for='1']" ... . Assuming that's just a copy paste error/from a previous slightly different version of the code and the line you specified is where the error is actually coming from:
Since the previous find/click lines are working there are 2 potential reasons for the third one to not find the label element
The age label[for='16'] element click either isn't actually occurring, or is occurring before the JS that enables the showing behavior is attached. You can check for this by adding a sleep for a few seconds before it and seeing whether the failures go away
The participant_consent find/click isn't waiting long enough for the element to appear. find waits up to Capybara.default_max_wait_time seconds for elements to appear, so if that is long enough you could increase that setting, or pass a :wait option to find to override the setting for that call
find("div.measure#participant_consent label[for='1']", wait: 10).click
Technically, there is a third potential cause but it's highly unlikely due to the sporadic nature of the failure, which would be a JS failure on the page. You can check for this by rescuing the error and pausing your test so that you can look at the developer console in the browser for any errors.
I am getting an "Element is no longer attached to the DOM" error from Geb tests. The thing that's confusing me is that the error is from within waitFor itself -- I inserted the wait specifically to allow the async activity on the page to complete before moving ahead with clicking a link, which was previously the source of the same error. If the wait itself fails, now I'm at a loss.
The code is something like
waitFor { $("div", text: "... search string ... ") }
$("a", id: "element-id").click()
and the stack trace shows that the waitFor itself is actually the problem:
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:187)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:152)
at geb.navigator.NonEmptyNavigator.matches_closure28(NonEmptyNavigator.groovy:474)
at geb.navigator.NonEmptyNavigator.matches(NonEmptyNavigator.groovy:471)
at geb.navigator.NonEmptyNavigator.filter_closure2(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.filter(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.find(NonEmptyNavigator.groovy:48)
at geb.content.NavigableSupport.$(NavigableSupport.groovy:96)
at geb.Browser.methodMissing(Browser.groovy:193)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at [my test]_closure7([my test].groovy:147)
at [my test]_closure7([my test].groovy)
at geb.waiting.Wait.waitFor(Wait.groovy:106)
From the stacktrace I can see that you use that selector inside of a test class and not a module so the possibility of a module base element being detached can be ruled out.
If this is happening consistently for you then it means that one of the elements selected by the div selector gets removed from DOM before its text is being retrieved to filter on it.
There are two reasons why this can happen:
Your selector is very slow - selecting all div elements in a page and then filtering them based on text in the JVM can take a lot of time. Assuming that you use the default waiting preset then if that selector takes more than 5 seconds then the waitFor {} block will simply run once, get the exception and never retry because it runs out of time. You should do as much filtering as possible in the browser, that is use a CSS3 compatible selector and use Geb's text filtering extension on an as small as possible element set.
Your page is async in a periodic way and it changes quicker than the selector is able to filter based on element text. This would be again possible because your selector looks like it could be potentially very slow.
Basically I would suggest coming up with a more specific selector than what you have there currently.
during the migration from RichFaces 3 to 4, we are facing an unexpected behaviour of rich:tree element. We registered a selectionChangeListener which is supposed to include a facelet with h:inputText fields next to the tree depending on the new selection. The facelet is supposed to show detailed information on the selected node.
This works correctly when the first selection is made. However, when we select another node of the same type, the same facelet is included (which is correct in this case as the node type is the same), but the values of the previous node are displayed in the facelet, even though the object holding the value of the component is instantiated correctly.
Inspecting the log files revealed that the TreeSelectionChangeEvent is processed during the Apply Request Phase (2). During that phase, the object holding the textfield's value is updated correctly, but is changed back to the old value during Update Model Phase (4).
General question on this issue is: Is it correct that this event is processed during Apply Request Phase even though the immediate attribute of the tree is set to false? (I would have expected the event to be processed during Invoke Application Phase (5)) And, if this is correct behaviour, how could we circumvent the problem that the old value is restored?
Thanks for your suggestions in advance.
as much as I understood, during the Apply Request Phase, the listener-event is executed and you update fields which are also represented as h:inputFields in the currently rendered view?
During Update Model Phase, the data out of the original h:inputText overwrites the already made changes?
Without being able to test it out locally: With switchType="ajax" the rich:tree-component gives two attributes
execute and
render.
You want the facelet-part to re-render, but not the input values to be executed (because that's what the listener already did).
Assuming you use rich:tree in ajax switch-type, have you tried to set execute="#this" and render="<theFaceletComponent>"?
If the component id wasn't found, use :#{rich:clientId('<theFaceletComponent>')} for an absolute identifier.
Hope, that helps ...