Search code examples
javaappiumpageobjectsgetelementsbyclassnamepage-factory

AppiumDriver MobileElement not found despite Existing ClassName can be found


I've setup my AppiumDriver automation class and attempting simple tests, such as testing parallel, identifying MobileElements and general swipe commands are working. Working through the kinks, I'm getting an error stating that a MobileElement I initialized as part of the Class for a web page, such as Google main page on Chrome browser. I'm getting no such element even though the className undereneath the id I picked is correct. From my Appium Server, it's attempting to find by className (android.widget.EditText), but it can't find it. I've tried that class and ".//android.widget.EditText" and no luck.

I would use search by name, but no its not giving me alot of options. I even tried to do a List of WebElements, but it doesn't have a size bigger than zero.

Here is my page-object classes:

PageObject:

public class PageObject {
    public AppiumDriver<MobileElement> driver;
    protected WebDriverWait wait;
    Dimension size;


    public PageObject(AppiumDriver<MobileElement> driver){
        this.driver = driver;
        wait = new WebDriverWait(driver, 15);

        PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }

    @SuppressWarnings("rawtypes")
    public  void  swipeVertical  (double startPercentage, double finalPercentage, int duration) {
        size = driver.manage().window().getSize();
        int width = (int) (size.width/2);
        int startPoint = (int) (size.getHeight() * startPercentage);
        int endPoint = (int) (size.getHeight() * finalPercentage);
        new TouchAction(driver)
            .press(PointOption.point(width, startPoint))
            .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
            .moveTo(PointOption.point(width, endPoint))
            .release()
            .perform();
    } 

    @SuppressWarnings("rawtypes")
    public void swipeHorizontal (double startPercentage, double finalPercentage, int duration) {
        size = driver.manage().window().getSize();
        int height = (int) (size.height/2);
        int startPoint = (int) (size.getWidth() * startPercentage);
        int endPoint = (int) (size.getWidth() * finalPercentage);
        new TouchAction(driver)
            .press(PointOption.point(startPoint, height))
            .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
            .moveTo(PointOption.point(endPoint, height))
            .release()
            .perform();
    }

(Update, not using PageFactory Approach this time): GoogleMainPage:

public class GoogleMainPage extends PageObject {

    //@AndroidFindBy(id="com.android.chrome:id/tsf")
    private MobileElement searchSection = driver.findElement(By.id("main"));

    //@AndroidFindBy(id="com.android.chrome:id/tophf")
    //private MobileElement searchCategories;


    public GoogleMainPage(AppiumDriver<MobileElement> driver) {
        super(driver);


    }

    public void searchQuery(String query) {

        MobileElement searchText = searchSection.findElement(By.className(".//android.widget.EditText"));
        MobileElement confirmSearch = searchSection.findElement(By.name("Google Search"));
        searchText.click();
        searchText.sendKeys(query);
        confirmSearch.click();
    }

}

The class where I'm performing my tests, after I setup my driver/drivers (generalWait() is just a Thread Sleep method):

@Test
    public void testActivation() {
        assertTrue(driver != null);

        pageObject = new PageObject(TLDriverFactory.getTLDriver());
        pageObject.driver.get("https://www.google.com");
        System.out.println(pageObject.driver.getCurrentUrl());
        assertTrue(pageObject.driver.getCurrentUrl().equals("https://www.google.com/"));

        try {generalWait(8000);} catch (InterruptedException e) {e.printStackTrace();}

        GoogleMainPage googleMainPage = new GoogleMainPage(TLDriverFactory.getTLDriver());

        googleMainPage.searchQuery("star wars");

        GoogleSearchResultsPage resultsPage = new GoogleSearchResultsPage(TLDriverFactory.getTLDriver());

        resultsPage.swipeVertical(0.20, 0.80, 2000);
    }

I'm currently running this with Maven, and io.appium java client is 6.1.0.

Is there something I'm missing while setting this up? Let me know if you need more info.


Solution

  • After more research on finding elements with Appium on Web Page browsers, if the web page you want to test through its elements has a desktop version, (and haven't switched to a non-webview context,) the desktop layout takes precedence over the mobile version of the web page.

    The other half you have to consider is looking at the page source for the mobile web page version in case the AppiumDriver can't find the desktop element. You can get find the Element setup in Mobile version with driver.getPageSource(). Now my GoogleMainPage class works when typing some text and selecting the Google Search Button

    public class GoogleMainPage extends PageObject {
    
        private MobileElement searchSection = driver.findElement(By.id("tsf"));
    
        public GoogleMainPage(AppiumDriver<MobileElement> driver) {
            super(driver);
    
        }
    
        public void searchQuery(String query) {
    
            MobileElement searchText = searchSection.findElement(By.name("q"));
            MobileElement confirmSearch = searchSection.findElement(By.className("Tg7LZd")); 
            searchText.click();
            searchText.sendKeys(query);
            confirmSearch.click();
        }
    
    }