2

I am testing a mobile application using Appium + Selenium + Java.

I have a page who contains several elements with the following ids:

  • field_1
  • field_2
  • field_3
  • bouton_1

When I open the page. The element "field_1" and "field_2" are visible but the other two need to be scrolled into view.

Since I need to interact with all four of these elements, I first need to find them. Here is how I do it:

WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditions.presenceOfElementLocated((By.xpath("//*[@resource-id='"+id+"']"))));
WebElement element = driver.findElement(By.xpath("//*[@resource-id='"+id+"']"));

This way of doing things work fine for my elements "field_1" and "field_2" but doesn't for the other two and I got the following error:

org.openqa.selenium.TimeoutException: Expected condition failed: waiting for presence of element located by: By.xpath: //*[@resource-id='field_3'] (tried for 10 second(s) with 500 milliseconds interval)

However, if I manually scroll into view, the elements are found without any issues.


Is it expected behavior that selenium can't find an element who is here but need to be scrolled into view? I never had this issue when I was testing web applications on desktops.

How can I find those elements when the only information I have about them is their id? I'm thinking of using some "scroll method", but I wasn't able to find one that fit my needs.

I'm aware of this one but it seems like you have to specify how much you want to scroll and I don't know that (it depends of what mobile phone you are using. So I would need to get this information dynamically).

I'm also aware of this "scroll to text" method (another link about this here), but I don't have a text/name here. I just have an id.


Here are the relevant information on my pom:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

<dependency>
    <groupId>io.appium</groupId>
    <artifactId>java-client</artifactId>
    <version>7.3.0</version>
</dependency>
  • You never mentioned application type? It is native android app or mobile web app. – Muzzamil Feb 4 at 21:43
  • @Muzzamil It's a native android app, but I will also need to test the iOS version of it (I'm saying this in case there is a way to code the test that will work for both) – BelovedFool Feb 5 at 13:18
  • I know the solution to scroll till element in IOS too both you have to use 2 different function. Uiautomator2 is only for andriod which has this feature. If you will say I can upload separate solution for IOS. – Muzzamil Feb 5 at 13:26
  • @Muzzamil That would interest me indeed. I would be grateful if you were to share this in your answer as well. Otherwise, I guess I'll just have to ask a new question in the future – BelovedFool Feb 5 at 13:28
  • Updated. Plesae have a look. – Muzzamil Feb 5 at 13:35
1

When it comes to content that has to be scrolled, there are 2 cases:

  1. Everything is always present and Selenium can interact with it (even the stuff that user has not yet scrolled to).
  2. Elements get loaded when user scrolls down to some content (infinite scroll, i.e. Twitter).

To check which one are we dealing with open the webpage, do not scroll and open console window (F12). In console type:

document.querySelectorAll("div[resource-id='SOME_ID']")

(I am using css selector based on your xpath, the 'div' part will probably need some adjusting)

If this does not return any WebElements it means you need to scroll it into view to be loaded. If so, I suggest to implement a FluentWait, which will do 2 things:

  • scroll the webpage by some small amount,
  • try to locate the WebElement.

This FluentWait function should return a WebElement and have a set timeout.

| improve this answer | |
  • Hey Mono, thanks for the answer! Just to be clear though, I'm testing a mobile app and not a web app. Do you know if this changes something? – BelovedFool Feb 4 at 14:29
  • You can still inspect the page via remote debugging (developers.google.com/web/tools/chrome-devtools/…). Scrolling should be easier as you get access to Scroll method from Appium. The rest remains the same - FluentWait comes with Selenium. – Moro Feb 4 at 14:40
1

For Android:

You can scroll till you don’t find element with given resource id. This can be achieved with UiAutomator2as automation engine. You need to use automation name as UiAutomator2 in desires capabilities.

Add in desired capability UiAutomator2 if you are using appium as automation engine.

capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");

Now use below functions if you have element's resource id, and index as 0 if there is one element on page.

public void scrollByID(String Id, int index) {

        try {

             driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().resourceId(\""+Id+"\").instance("+index+"));")); 

        } catch (Exception e) {
           e.printStackTrace();
        }
    }

This is dynamic approach it will scroll till element is not visible.

For IOS:

Best practice for performing controlled scrolling using the Appium “mobile:scroll” script command. This command is performed using the executeScript() method.

RemoteWebElement element = (RemoteWebElement)driver.findElement(By.className("XCUIElementTypeTable"));
String elementID = element.getId();
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("element", elementID); 
scrollObject.put("direction", "down");
driver.executeScript("mobile:scroll", scrollObject);

element: The id of the element that you want to scroll – “element” must be scrollable.

direction: “up”, “down”, “left, “right”.

More details about scrolling on IOS check here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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