Search code examples
javaandroid-uiautomatorappium-androidpage-factoryresource-id

Appium Or( | ) Condition for UiSelector().ResoureIdMatches gives NoSuchElementException


I'm creating a POM class for a Header class/widget in an Main Activity section (Reddit app is the example. See screenshots below.) Going through Inspector, I see header would have Search box available, but if I were to move to another section/tab of the Main Activity the Search box becomes unavailable. The id/resource-id also changes ending with either :id/search_view or :id/toolbar_title. My initial reaction to this question is no, but want to reach out to anyone who has encountered this specific subject matter before calling it quits.

I wanted to see if I was able store either Id into a single MobileElement for my Header class using a Regex condition inside the UiSelector when calling ResourceIdMatches method.

Here is what I have for my currently in My Header class. (Focus is on navTitle MobileElement):

@AndroidFindBy(id="com.reddit.frontpage:id/toolbar")
public MobileElement headerSection;

@AndroidFindBy(id = "com.reddit.frontpage:id/nav_icon")
public MobileElement userIcon;

//Needs work
@AndroidFindBy(uiAutomator = "new UiSelector()"
        + ".resourceIdMatches(\".*id/^([search_view|toolbar_title])+$\")")
public MobileElement navTitle;

public RedditMainActivityHeader(AppiumDriver<MobileElement> driver) {
    super(driver);
}

While researching on the Regex topic, I've edited the Regex condition before using word bounderies(\b), not using [], using * instead of +. The alternative to get around this would be to create a second Header class and have the navTitle would find the id by either :id/search_view or :id/toolbar_title, but I would not want to do that on a practice standpoint for managing classes.

Screenshot: Ver 1: Header Section Ver 2: enter image description here


Solution

  • Found an alternative for using multiple conditions. I did more research on using locator strategies using multiple conditions, and found you can use xpath locators with className and id/resource-id. However, it would depend if the className tag remains the same along with the changes to resource-id. At the moment, my situation meets those conditions.

    @AndroidFindBy(xpath="//android.widget.TextView[@resource-id='com.reddit.frontpage:id/search_view' or @resource-id='com.reddit.frontpage:id/toolbar_title']")
    public MobileElement navTitle;