Espresso check view either doesNotExist or not isDisplayed

12.4k views Asked by At

The following statement does not work because doesNotExist() returns a ViewAssertion instead of a matcher. Any way to make it work without a try-catch?

.check(either(matches(doesNotExist())).or(matches(not(isDisplayed()))));
4

There are 4 answers

1
Sivakumar Kamichetty On

If you want to check if a view doesn't not exist in the hierarchy, please use below assertion.

ViewInteraction.check(doesNotExist());

If you want to check if a view exist in the hierarchy but not displayed to the user, please use below assertion.

ViewInteraction.check(matches(not(isDisplayed())));

Hope this helps.

1
Jacek Marchwicki On

not(isDisplayed) is not perfect because i.e. the view might be displayed but below the screen in a ScrollView.

Simple checking view.getVisibility() != View.GONE also is not a 100% solution. If view parent is hidden, the view is effectively hidden so the test should pass the scenario.

I suggest checking if view and its parents are visible:

fun isNotPresented(): ViewAssertion = object : ViewAssertion {
    override fun check(view: View?, noViewFoundException: NoMatchingViewException?) {
        if (view != null) {
            if (view.visibility != View.VISIBLE) {
                return
            }
            var searchView: View = view
            while (searchView.parent != null && searchView.parent is View) {
                searchView = searchView.parent as View
                if (searchView.visibility != View.VISIBLE) {
                    return
                }
            }
            assertThat<Boolean>(
                "View is present in the hierarchy and it is visible" + HumanReadables.describe(view),
                true,
                `is`(false)
            )
        }
    }
}
0
user2143491 On

I had the same issue, one of my views will not have a certain view initially but could add it and hide it later. Which state the UI was in depended on wether background activities were destroyed.

I ended up just writing a variation on the implementation of doesNotExist:

public class ViewAssertions {
    public static ViewAssertion doesNotExistOrGone() {
        return new ViewAssertion() {
            @Override
            public void check(View view, NoMatchingViewException noView) {
                if (view != null && view.getVisibility() != View.GONE) {
                    assertThat("View is present in the hierarchy and not GONE: "
                               + HumanReadables.describe(view), true, is(false));
                }
            }
        };
    }
}
0
Scott Merritt On

I encountered a similar situation. I believe this works and will check to ensure that a displayed view does not exist. It needs to either be not displayed or not in the view hierarchy:

onView(allOf(withId(R.id.viewId), isDisplayed())).check(doesNotExist())