Check if the resource identifier is displayed from the view in the array and click on it (Android-Espresso)

I have the following case. We use the Gherkin language to control our own ui automation using Espresso. In our Gherkin lines, we have a line called:

And I tap on button "Next"

Where "Next" is the String variable, we go to our glue code (we use the Cucumber structure).

As it happens, our application has many "Next" buttons with different resource identifiers. I ended up using gherkin lines with variables like:

And I tap on button "Next in screen 1"
And I tap on button "Next in screen 2"

Now I want to use only the Gherkin "Next" variable in my code. I get an Integer array that contains all the resource identifiers from all the Next buttons, but when I want to check which identifier is displayed on the screen, I got a NoMatchingViewException.

This is my current solution:

    final int[] uiElementIds = getArrayWithIdsFromUIElement("Next");

    int testId = 0;
    for(int id : uiElementIds) {
        try {
            onView(withId(id)).check(matches(isDisplayed()));
            testId = id;
            break;
        } catch(NoMatchingViewException ex) {
            // do nothing
        }
    }

    final int uiElementId = testId;
    onView(withId(uiElementId)).withFailureHandler(new FailureHandler() {
            @Override
            public void handle(Throwable error, Matcher<View> viewMatcher) {
                onView(withId(uiElementId)).perform(scrollTo(), click());
            }
        }).perform(click());

As you can see, I just catch the NoMatchingViewException that is thrown and do nothing with it until I find the correct identifier and exit the for loop.


My question is:

Is there a better approach we can use to scroll it to see which identifier is displayed, and if so, click on it?

In my mind, I came up with this idea, but it is not integrated into Espresso:

for(int id : uiElementIds) {
 if(onView(withId(id)).exist()) {
    performClick();
 }
}
+4
1

:

, , , , ?

, :

for(int id : uiElementIds) {
 if(onView(withId(id)).exist()) {
    performClick();
 }
}

Espresso framework Activity:

@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DetailsActivityTest {

    @Rule
    public ActivityTestRule<MainActivity_> mRule = new ActivityTestRule<>(MainActivity_.class);

    //TODO: Write tests to check if views are visible
    private final int[] allDetailsActivityViewsIdis = {
            R.id.dItem,
            R.id.dDayAndDate,
            R.id.dDay,
            R.id.dDate,
            R.id.dCity,
            R.id.dTempAndIcon,
            R.id.dTemperature,
            R.id.dHighTemp,
            R.id.dLowTemp,
            R.id.dDescriptionLayout,
            R.id.dDescription,
            R.id.dForecast,
            R.id.dHumidityLayout,
            R.id.dHumidityDesc,
            R.id.dHumidityVal,
            R.id.dPressureLayout,
            R.id.dPressureDesc,
            R.id.dPressureVal,
            R.id.dWindLayout,
            R.id.dWindDesc,
            R.id.dWindVal

    };

    private final int[] detailsActivityTextViewsIdis = {
            R.id.dDay,
            R.id.dDate,
            R.id.dHighTemp,
            R.id.dLowTemp,
            R.id.dDescription,
            R.id.dHumidityVal,
            R.id.dPressureVal,
            R.id.dWindVal,

    };

    private final int[] detailsActivityTextViewsDefaultValues = {
            R.string.day,
            R.string.date,
            R.string.high_temp,
            R.string.low_temp,
            R.string.description,
            R.string.humidity_val,
            R.string.pressure_val,
            R.string.wind_val,

    };

    @Before
    //TODO: Rewrite this code using espresso-intents
    public void checkIfAllDetailActivityViewsAreDisplayed() throws InterruptedException {
        for (int viewId : allDetailsActivityViewsIdis)
           onView(withId(viewId)).perform(click());

    }

    @Test
    public void checkIfDetailsActivityViewsHaveNoDefaultValue() throws InterruptedException {
        for (int viewId : detailsActivityTextViewsIdis)
            for (int valueId : detailsActivityTextViewsDefaultValues)
                onView(withId(viewId)).check(matches(not(withText(valueId))));

    }

}

, foreach , exists() check(matches(...) : isDisplayed, isDisplayedAtLeast isCompletelyDisplayed

, .

+1

Source: https://habr.com/ru/post/1652346/


All Articles