I need to match the view which is highlighted by a red rectangle. Which Espresso expression should I write for it?
This is a table layout, all cells are instances of TextView. There are no unique IDs for cell views. The view of interest may or may not have text inside. All I know is that this view is always sitting below the "Food Group" cell.
Any clues would be welcome.
Here is the test I would write in your case.
public void testCellBelowFoodGroup() {
getActivity();
onView(
allOf(
isDescendantOfA(isAssignableFrom(TableLayout.class)),
isInRowBelow(withText("Food Group")),
hasChildPosition(0)
)
).check(matches(withText("TEXT TO BE FOUND")));
}
So, we are looking for a view inside a given TableLayout, that is in a row below the "Food Group" text, and that is the leftmost element of the row. Then we can do whatever we want with that view, e.g. check its text.
isInRowBelow
and hasChildPosition
are not provided by Espresso, they are custom methods, as is usual when testing with Espresso: you are encouraged to create your own view assertions and view matchers.
Here is the implementation.
static Matcher<View> isInRowBelow(final Matcher<View> viewInRowAbove) {
checkNotNull(viewInRowAbove);
return new TypeSafeMatcher<View>(){
@Override
public void describeTo(Description description) {
description.appendText("is below a: ");
viewInRowAbove.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
// Find the current row
ViewParent viewParent = view.getParent();
if (!(viewParent instanceof TableRow)) {
return false;
}
TableRow currentRow = (TableRow) viewParent;
// Find the row above
TableLayout table = (TableLayout) currentRow.getParent();
int currentRowIndex = table.indexOfChild(currentRow);
if (currentRowIndex < 1) {
return false;
}
TableRow rowAbove = (TableRow) table.getChildAt(currentRowIndex - 1);
// Does the row above contains at least one view that matches viewInRowAbove?
for(int i = 0 ; i < rowAbove.getChildCount() ; i++) {
if (viewInRowAbove.matches(rowAbove.getChildAt(i))) {
return true;
}
}
return false;
}};
}
static Matcher<View> hasChildPosition(final int i) {
return new TypeSafeMatcher<View>(){
@Override
public void describeTo(Description description) {
description.appendText("is child #" + i);
}
@Override
public boolean matchesSafely(View view) {
ViewParent viewParent = view.getParent();
if (!(viewParent instanceof ViewGroup)) {
return false;
}
ViewGroup viewGroup = (ViewGroup) viewParent;
return (viewGroup.indexOfChild(view) == i);
}};
}
The full source code can be downloaded from https://github.com/acontal/android-stackoverflow-espresso-match_table_cell