hi, my first time posting so hope to get some help
first, I will explain my situation - I am testing an app, both in android and ios. android code works consistently but the ios is flickery due to the Stale exception.
basically, I get to the end page on the app which consists of a lot of data and popups. when I use a popup and click āDoneā, the page is refreshing with the new data according to what I gave it in the popup.
my goal is to catch the element after I used the popup as well and the page was refreshed.
what happens is, that when I click on āDoneā in the popup, the driver tries to find an element in the page(same page) and a situation which calls ārace conditionā occurs. there is a race between the refresh of the page and appium trying to find the element. because of that the test some times passes and some times donātā¦
I found some solutions on the web which I want to discuss first in order to understand them better and make a better decision.
to use ExpectedCondition.refreshed - how to use it? should I find the element before the refresh and give it to the webDriverWait after the refresh started? or just use refreshed after the refresh started(without catching the element before the refresh)?
if the first one is correct - than, should I catch all the element I want to use after the refresh before it happens as well? it might be a lot of elements.
if the second one is correct - what happens if the refreshed happened before getting to the webDriverWait?
use try catch - find an element, than try to click(example) on it in a try block, if it gets to the catch block, then, try to catch the element again. question - if the Stale exception is thrown does it say that the element already refreshed or I might try to catch it again and the Stale exception will occur again?
overrides ExpectedCondition apply method - may use the try catch option here. any other suggestions?
my employer suggests that the app developer will generate an id to a predetermined element when the page is refreshed (but then it should be deleted for the next time I will want to know if a refresh occurred).
as well, how can we detect that a page is fully reload using appium?
which one do you think I should use, why and how?
thanks for answering and I will love to get some other suggestion to handle it correctly, or some explanation on how to avoid that.
log.info(āchange back to default standardā);
wait.until(visibilityOf(driver.findElements(MobileBy.name(āeditā)).get(1))).click(); //tigers popup
wait.until(visibilityOfElementLocated(MobileBy.name(āSelect Standardā))); //waiting for the popup title
wait.until(elementToBeClickable(MobileBy.name(āstandardā))).click();
wait.until(elementToBeClickable(MobileBy.name(āDoneā))).click();
//popup closed
//refreshing
//looking for elements
for example:
log.info(ācheck number of activitiesā);
String activities = wait.until(presenceOfElementLocated(MobileBy.name(āActivity (12)ā))).getText(); //some times fail, and some time passes
assertEquals(āIncorrect number of activitiesā, āActivity (12)ā, activities);
*it is a bit hard coded now, there are things that need to be changed. @Aleksei
lets say I am moving to the next page and trying to find an element with the same selector as in the previous page. I would try to find an unique element (of the second page) first and then try to search the desirable element.
if I find the unique element does it insure me that all the other elements are rendered as well?
maybe just its children? (I guess that each element renders to the page on a different time).
or maybe there is a way to detect that a page is fully loaded, in web context you can use document.reayState == ācompleteā. is there any way to do that with mobile commands?
it is basically the same problem as refreshed page @Aleksei
before we do anything we identify what page we have now. something like:
myApp()
.homePage()
.tapAddMoneyButton() // we have tap and expecting new page ->
.isAddMoneyPageLoaded() // check we really have expected page
.tapInstantTopUpCard()
in your case more immediate effect is make ONE click function and add minor sleep right after tap to allow page start changing. so code should look like:
log.info(āchange back to default standardā);
click(wait.until(visibilityOf(driver.findElements(MobileBy.name(āeditā)).get(1)))) //tigers popup
wait.until(visibilityOfElementLocated(MobileBy.name(āSelect Standardā))); //waiting for the popup title
click(wait.until(elementToBeClickable(MobileBy.name(āstandardā)));
click(wait.until(elementToBeClickable(MobileBy.name(āDoneā)));
protected void click(MobileElement el) {
el.click();
sleep(100); // 100 ms
}
yes, I get you, but how do I write the isAddMoneyPageLoaded()? or what check should be in it.
because if I check for an unique element it does not mean the other elements(including the one I want to click) are rendered already. maybe just the unique element is rendered. @Aleksei
an example for my error
ERROR - The previously found element āāDoneā Buttonā is not present in the current view anymore. Make sure the application UI has the expected state. You could also try to switch the binding strategy using the āboundElementsByIndexā setting for the element lookup. Original error: No matches found for Identity Binding from input {(
Button, {{272.5, 20.0}, {43.5, 44.0}}, label: āDoneā
)}
To make isSomePageLoaded you need find some unique element. No such unique ID -> ask dev to add it. I do it myself for iOS code. For Android this is not a problem for our app.
PS but temporarily add second solution. It will reduce much āStaleElementā error. Later with checking page loaded it will 100% vanish.
hi, just want to thank you for helping. eventually the problem occurred because the page rendered each second for updating the content(data) on the page.
If button Done doesnāt change the position after refreshing the page. Before the page is loaded, find the element to get the coordinate width and height. After the page is loaded, tap on coordinate at point (x+width/2, y+height/2)
Hey guys,
I created this topic in the Appleās forum, maybe if everyone send some message to bump up this subject, we can get some help from the Apple on it: