private static Matcher<View> childAtPosition( final Matcher<View> parentMatcher, final int position) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("Child at position " + position + " in parent "); parentMatcher.describeTo(description); } @Override public boolean matchesSafely(View view) { ViewParent parent = view.getParent(); return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals(((ViewGroup) parent).getChildAt(position)); } }; }
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) public static Matcher<? super View> withUsageHintOnClick(final Matcher<? extends CharSequence> charSequenceMatcher) { return new TypeSafeMatcher<View>() { @Override protected boolean matchesSafely(View view) { if (!view.isClickable()) { return false; } AccessibilityNodeInfo.AccessibilityAction clickAction = findAction(view, AccessibilityNodeInfo.ACTION_CLICK); return charSequenceMatcher.matches(clickAction.getLabel()); } @Override public void describeTo(Description description) { description.appendText("is clickable and has custom usage hint for ACTION_CLICK: "); charSequenceMatcher.describeTo(description); } }; }
/** * A custom {@link Matcher} which matches an item in a {@link ListView} by its text. * <p> * View constraints: * <ul> * <li>View must be a child of a {@link ListView} * <ul> * * @param itemText the text to match * @return Matcher that matches text in the given view */ private Matcher<View> withItemText(final String itemText) { checkArgument(!TextUtils.isEmpty(itemText), "itemText cannot be null or empty"); return new TypeSafeMatcher<View>() { @Override public boolean matchesSafely(View item) { return allOf( isDescendantOfA(isAssignableFrom(ListView.class)), withText(itemText)).matches(item); } @Override public void describeTo(Description description) { description.appendText("is isDescendantOfA LV with text " + itemText); } }; }
private static Matcher<? extends Throwable> causalChainContains(final Class<?> cls) { return new TypeSafeMatcher<Throwable>() { @Override protected boolean matchesSafely(Throwable item) { final List<Throwable> causalChain = Throwables.getCausalChain(item); for (Throwable throwable : causalChain) { if(cls.isAssignableFrom(throwable.getClass())){ return true; } } return false; } @Override public void describeTo(Description description) { description.appendText("exception with causal chain containing " + cls.getSimpleName()); } }; }
public static Matcher<TypeName> typeName(final Matcher<? super ClassName> matcher) { final Matcher<? super ClassName> subMatcher = matcher; return new TypeSafeMatcher<TypeName>() { @Override protected boolean matchesSafely(TypeName item) { return subMatcher.matches(item); } @Override public void describeTo(Description description) { description.appendText("typename ").appendDescriptionOf(subMatcher); } }; }
public static Matcher<AnnotationSpec> hasMember(final String member) { return new TypeSafeMatcher<AnnotationSpec>() { @Override protected boolean matchesSafely(AnnotationSpec item) { return item.members.containsKey(member); } @Override public void describeTo(Description description) { description.appendText("has member " + member); } }; }
public static Matcher<View> nthChildOf(final Matcher<View> parentMatcher, final int childPosition) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("with "+childPosition+" child view of type parentMatcher"); } @Override public boolean matchesSafely(View view) { if (!(view.getParent() instanceof ViewGroup)) { return parentMatcher.matches(view.getParent()); } ViewGroup group = (ViewGroup) view.getParent(); return parentMatcher.matches(view.getParent()) && group.getChildAt(childPosition).equals(view); } }; }
/** * Matches a view that is a descendant of the nth item in a recyclerview * @param listMatcher * @param childPosition * @param subviewMatcher * @return */ public static Matcher<View> subfieldOfNthItemWithId(final Matcher<View> listMatcher, final int childPosition, final Matcher<View> subviewMatcher) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("Sub-view of an item from a list"); } @Override public boolean matchesSafely(View view) { // // Clearly "espresso + recyclerview != love" // return allOf( isDescendantOfA(nthChildOf(listMatcher, childPosition)), subviewMatcher ).matches(view); } }; }
private static Matcher<View> childAtPosition(final Matcher<View> parentMatcher, final int position) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("Child at position " + position + " in parent "); parentMatcher.describeTo(description); } @Override public boolean matchesSafely(View view) { ViewParent parent = view.getParent(); return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals( ((ViewGroup) parent).getChildAt(position)); } }; }
public static Matcher<CharSequence> equalTo(final CharSequence expected) { return new TypeSafeMatcher<CharSequence>() { final Matcher<String> stringMatcher = org.hamcrest.Matchers.equalTo(expected.toString()); @Override public void describeTo(final Description description) { stringMatcher.describeTo(description); } @Override protected boolean matchesSafely(final CharSequence actual) { return stringMatcher.matches(actual.toString()); } }; }
private static Matcher<Long> isDate(final long expected, DateTimeZone tz) { return new TypeSafeMatcher<Long>() { @Override public boolean matchesSafely(final Long item) { return expected == item.longValue(); } @Override public void describeTo(Description description) { description.appendText("Expected: " + new DateTime(expected, tz) + " [" + expected + "] "); } @Override protected void describeMismatchSafely(final Long actual, final Description mismatchDescription) { mismatchDescription.appendText(" was ").appendValue(new DateTime(actual, tz) + " [" + actual + "]"); } }; }
private static Matcher<SagaRequest> eqToRequest(SagaRequest expected) { return new TypeSafeMatcher<SagaRequest>() { @Override protected boolean matchesSafely(SagaRequest request) { return expected.id().equals(request.id()) && request.serviceName().equals(expected.serviceName()) && request.task().equals(expected.task()) && request.type().equals(expected.type()) && ((RestOperation) request.transaction()).path().equals(((RestOperation) expected.transaction()).path()) && ((RestOperation) request.transaction()).method().equals(((RestOperation) expected.transaction()).method()) && ((RestOperation) request.compensation()).path().equals(((RestOperation) expected.compensation()).path()) && ((RestOperation) request.compensation()).method().equals(((RestOperation) expected.compensation()).method()); } @Override public void describeTo(Description description) { description.appendText(expected.toString()); } }; }
private Matcher<SagaEventEntity> eventWith( long eventId, String type) { return new TypeSafeMatcher<SagaEventEntity>() { @Override protected boolean matchesSafely(SagaEventEntity event) { return eventId == event.id() && event.type().equals(type); } @Override protected void describeMismatchSafely(SagaEventEntity item, Description mismatchDescription) { mismatchDescription.appendText(item.toString()); } @Override public void describeTo(Description description) { description.appendText( "SagaEventEntity {" + "id=" + eventId + ", type=" + type); } }; }
private TypeSafeMatcher<List<ReleaseUpdate>> withReleaseUpdate(final String version, final String refDocUrl, final String releaseStatus) { return new TypeSafeMatcher<List<ReleaseUpdate>>() { @Override protected boolean matchesSafely(List<ReleaseUpdate> items) { ReleaseUpdate item = items.get(0); return "foo".equals(item.artifactId) && releaseStatus.equals(item.releaseStatus) && version.equals(item.version) && refDocUrl.equals(item.apiDocUrl) && refDocUrl.equals(item.refDocUrl); } @Override public void describeTo(Description description) { } }; }
public static Matcher<View> withIndex(final Matcher<View> matcher, final int index) { return new TypeSafeMatcher<View>() { int currentIndex = 0; @Override public void describeTo(Description description) { description.appendText("with index: "); description.appendValue(index); matcher.describeTo(description); } @Override public boolean matchesSafely(View view) { return matcher.matches(view) && currentIndex++ == index; } }; }
public static Matcher<View> childAtPosition( final Matcher<View> parentMatcher, final int position) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("Child at position " + position + " in parent "); parentMatcher.describeTo(description); } @Override public boolean matchesSafely(View view) { ViewParent parent = view.getParent(); return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals(((ViewGroup) parent).getChildAt(position)); } }; }
public static Matcher<View> validPosition() { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("not supports input methods"); } @Override public boolean matchesSafely(View view) { // At first glance, it would make sense to use view.onCheckIsTextEditor, but the android // javadoc is wishy-washy about whether authors are required to implement this method when // implementing onCreateInputConnection. return view.getX() != 0 || view.getY() != 0; } }; }
public static Matcher<String> equivalentTo(DateTime expected) { return new TypeSafeMatcher<String>() { @Override public void describeTo(Description description) { description.appendText(String.format( "a date time matching: %s", expected.toString())); } @Override protected boolean matchesSafely(String textRepresentation) { //response representation might vary from request representation DateTime actual = DateTime.parse(textRepresentation); return expected.isEqual(actual); } }; }
public static Matcher<String> withinSecondsAfter(Seconds seconds, DateTime after) { return new TypeSafeMatcher<String>() { @Override public void describeTo(Description description) { description.appendText(String.format( "a date time within %s seconds after %s", seconds.getSeconds(), after.toString())); } @Override protected boolean matchesSafely(String textRepresentation) { //response representation might vary from request representation DateTime actual = DateTime.parse(textRepresentation); return actual.isAfter(after) && Seconds.secondsBetween(after, actual).isLessThan(seconds); } }; }
public static Matcher<JsonObject> identifierMatches(String namespace, String value) { return new TypeSafeMatcher<JsonObject>() { @Override public void describeTo(Description description) { description.appendText(String.format( "an identifier with namespace: %s and value: %s", namespace, value)); } @Override protected boolean matchesSafely(JsonObject entry) { return entry.getString("namespace").equals(namespace) && entry.getString("value").equals(value); } }; }
public static Matcher<JsonObject> validationErrorMatches(String message, String property) { return new TypeSafeMatcher<JsonObject>() { @Override public void describeTo(Description description) { description.appendText(String.format( "a validation error message: %s for property: %s", message, property)); } @Override protected boolean matchesSafely(JsonObject entry) { List<JsonObject> parameters = JsonArrayHelper.toList( entry.getJsonArray("parameters")); return entry.getString("message").equals(message) && parameters.stream().anyMatch(p -> p.getString("key").equals(property)); } }; }
public static Matcher<List<JsonObject>> hasSoleMessgeContaining(String message) { return new TypeSafeMatcher<List<JsonObject>>() { @Override public void describeTo(Description description) { description.appendText(String.format( "a sole validation error message containing: %s", message)); } @Override protected boolean matchesSafely(List<JsonObject> errors) { if(errors.size() == 1) { return errors.get(0).getString("message").contains(message); } else return false; } }; }
static private <T> Matcher<List<T>> consistsOfConsistentBlocks(int blocks, int itemsInBlock) { return new TypeSafeMatcher<List<T>>() { @Override public void describeTo(Description description) { description.appendText(blocks + " consistent blocks of size " + itemsInBlock); } @Override protected boolean matchesSafely(List<T> item) { T value = null; for (int i = 0; i < 30; i++) { if (i % 3 == 0) { value = item.get(i); } else { if (!item.get(i).equals(value)) { return false; } } } return true; } }; }
private static Matcher<UsedJourneys> used(Journey journey) { return new TypeSafeMatcher<UsedJourneys>() { @Override public void describeTo(Description description) { description.appendText("used"); description.appendValue(journey); } @Override protected boolean matchesSafely(UsedJourneys journeys) { return journeys.used(journey); } @Override protected void describeMismatchSafely(UsedJourneys item, Description mismatchDescription) { mismatchDescription.appendText("not used"); mismatchDescription.appendValue(journey); } }; }
private static Matcher<View> childAtPosition( final Matcher<View> parentMatcher, final int position ) { return new TypeSafeMatcher<View>() { @Override public void describeTo(Description description) { description.appendText("Child at position " + position + " in parent "); parentMatcher.describeTo(description); } @Override public boolean matchesSafely(View view) { ViewParent parent = view.getParent(); return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals(((ViewGroup) parent).getChildAt(position)); } }; }
public static Matcher<View> hasTextInputLayoutErrorText() { return new TypeSafeMatcher<View>() { @Override public boolean matchesSafely(View view) { if (!(view instanceof TextInputLayout)) { return false; } CharSequence error = ((TextInputLayout) view).getError(); return error != null && error.length() > 0; } @Override public void describeTo(Description description) { description.appendText("Expected: TextInputLayout to have error, but was null or empty'"); } }; }