3

For example, I'm sending a message. While it's being sent to the recipient it has the resource-id "pending_indicator". When it is delivered, it has the resource-id "delivered_indicator".

So, I'm checking if the message is delivered using the following code:

List<MobileElement> messages = driver.findElements (By.id ("body_bubble")); // Get all messages in chat
MobileElement lastMessage = messages.get (messages.size () - 1);            // Get the last message

//Xpath query to check if the message has been delivered
String query = "//*[contains(@resource-id, 'delivered_indicator')]";

WebDriverWait wait = new WebDriverWait (driver, 10);
wait.until (ExpectedConditions.visibilityOfNestedElementsLocatedBy (lastMessage, By.xpath(query)));

But it does not work. I checked that the message has been delivered within 10 seconds, but the wait does not return anything. When I checked in IntelliJ evaluation mode, it showed that the lastMessage still has the "pending_indicator" resource-id in the "footer_delivery_status" container. Why is it not updated?

The lastMessage variable (message body) stays the same in app sources. It does not change itself, so it should not affect the result.

I also tried to use this wait, but it did not help:

wait.until(ExpectedConditions.visibilityOf (lastMessage.findElement (By.xpath(query))));

However when I use this Xpath, it works properly:

"(//*[contains(@resource-id,'body_bubble')])[last()]//*[contains(@resource-id, 'delivered_indicator')]"

So why it does not work with the nested explicit wait?

pendingdelivered

2 Answers 2

2

When you use xpath that is to locate nested elements you have to start your query from .. Like String query = ".//*[contains(@resource-id, 'delivered_indicator')]";

https://selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html#presenceOfNestedElementLocatedBy-org.openqa.selenium.By-org.openqa.selenium.By-

11
  • Tried with the dot - doesn't work.
    – LexSav
    Dec 10, 2019 at 10:27
  • 1
    Can you drill into the method and set breakpoint to line ` List<WebElement> allChildren = element.findElements(childLocator);`? What would be the list content then?
    – wec
    Dec 10, 2019 at 10:59
  • I've already done the simular thing. The result is that the lastMessage variable still has the "pending_indicator" resource-id in the "footer_delivery_status" container. Even though the message had been already delivered.
    – LexSav
    Dec 10, 2019 at 11:26
  • It seems that the lastMessage var is taken the first time I call wait.until() with the "pending_indicator" (because at that time the message has not been delivered yet). And then the wait does not update children of the lastMessage, because when I call the same wait again in debug evaluation mode after the message was delivered, it works just fine ...
    – LexSav
    Dec 10, 2019 at 11:27
  • I hope you understand what I'm trying to say :) It's just that I'm confused with this behavior. The wait should update children to check if they are visible yet. But in this case the lastMessage var stays with the pending indicator, even when the message had been already delivered a long time ago.
    – LexSav
    Dec 10, 2019 at 11:32
2

Solution:1
From your code “wait.until (ExpectedConditions.visibilityOfNestedElementsLocatedBy (lastMessage, By.xpath(query)))”
The expectation of the method (visibilityOfNestedElementsLocatedBy) used for checking the child WebElement as a part of parent WebElement to be visible.

Since Nested explicit wait does not work in Appium instead we can use the visibiltyOf(WebElement element) or visiblityOfElementLocated(By locator) methods.

visibiltyOf(WebElement element) - to check whether the element is visible in the DOM or not.
visiblityOfElementLocated(By locator) - to check whether the locator is visible in the DOM as well as in the UI.

Solution:2
Since Appium DOM is not updated with the latest UI changes, we need to update the DOM which will not automatically update in Appium.
Try the below line of code, before checking the visibility of the element.
Code: driver.getPageSource();

As a suggestion, you can also try to swipe to refresh the Appium then get the page source and check the visibility of the element.
Code:

/**
* @description Is use to swipe from bottom to top. It use to take the mobile window dimension and swipe from bottom to top
* @param step: Nil
*/
public void swipeUpAction() {
try {
               ((AppiumDriver<WebElement>) driver).context("NATIVE_APP");
               Dimension size = driver.manage().window().getSize();
               System.out.println(size);
               // Find swipe start and end point from screen's width and height. Find starty point which is at bottom side of screen.
               int starty = (int) (size.height * 0.80);
               // Find endy point which is at top side of screen.
               int endy = (int) (size.height * 0.20);
               // Find horizontal point where you wants to swipe. It is in middle of screen width.
               int startx = size.width / 2;
               writeToLogFile("INFO", "starty = " + starty + " ,endy = " + endy + " , startx = " + startx);
               // Swipe from Bottom to Top.
               ((AndroidDriver<WebElement>) driver).swipe(startx, starty, startx, endy, 3000);
} catch (Exception e) {
               testStepFailed("SwipeElementsScreen failed ");
               e.printStackTrace();
               }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.