TextInputLayoutのエラー表示を確認する
EditText用のエラーテキスト内容を確認するMatcherは存在するが、InputTextLayout用がなかったので
カスタムMatcherをwithTextのMatcherを参考に作成した
エラーかどうか、エラーのテキストを文字列、または文字列リソースでマッチングできるようにしている
public static Matcher<View> withErrorText(String text) {
return withErrorText(is(text));
}
public static Matcher<View> withErrorText(final Matcher<String> stringMatcher) {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
@Override
public void describeTo(Description description) {
description.appendText("with Error Text: ");
stringMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
CharSequence error = textInputLayout.getError();
return error != null && stringMatcher.matches(error.toString());
}
};
}
public static Matcher<View> withErrorText(final int resourceId) {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
private String resourceName = null;
private String expectedText = null;
@Override
public void describeTo(Description description) {
description.appendText("with string from resource id: ");
description.appendValue(resourceId);
if (null != resourceName) {
description.appendText("[");
description.appendText(resourceName);
description.appendText("]");
}
if (null != expectedText) {
description.appendText(" value: ");
description.appendText(expectedText);
}
}
@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
if (null == expectedText) {
try {
expectedText = textInputLayout.getResources().getString(resourceId);
resourceName = textInputLayout.getResources().getResourceEntryName(resourceId);
} catch (Resources.NotFoundException ignored) {
// NOP
}
}
CharSequence actualText = null;
actualText = textInputLayout.getError();
if (null != expectedText && null != actualText) {
// FYI: actualText may not be string ... its just a char sequence convert to string.
return expectedText.equals(actualText.toString());
} else {
return false;
}
}
};
}
public static Matcher<View> hasError() {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
@Override
public void describeTo(Description description) {
description.appendText("has Error");
}
@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
CharSequence error = textInputLayout.getError();
return error != null;
}
};
}
使用例
ログイン画面で同じ内容のエラー文言が並ぶ場合などで効果を発揮する
allOf(withId(),withText())でも確認できるが、カスタムmatcherの方がスッキリすると思った
public void エラーテスト() {
onView(withId(R.id.textInputLayout_mail)).check(matches(isDisplayed()));
onView(withId(R.id.textInputLayout_mail)).check(matches(hasError()));
onView(withId(R.id.textInputLayout_mail)).check(matches(withErrorText("入力してください")));
onView(withId(R.id.textInputLayout_mail)).check(matches(withErrorText(R.string.error_message_required)));
onView(withId(R.id.textInputLayout_password)).check(matches(not(hasError())));
}