package co.unruly.matchers; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import java.util.Optional; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.OptionalLong; public class OptionalMatchers { /** * Matches an empty Optional. */ public static <T> Matcher<Optional<T>> empty() { return new TypeSafeMatcher<Optional<T>>() { @Override protected boolean matchesSafely(Optional<T> item) { return !item.isPresent(); } @Override public void describeTo(Description description) { description.appendText("An empty Optional"); } }; } /** * Matches a non empty Optional with the given content * * @param content Expected contents of the Optional * @param <T> The type of the Optional's content */ public static <T> Matcher<Optional<T>> contains(T content) { return new TypeSafeMatcher<Optional<T>>() { @Override protected boolean matchesSafely(Optional<T> item) { return item.map(content::equals).orElse(false); } @Override public void describeTo(Description description) { description.appendText(Optional.of(content).toString()); } }; } /** * Matches a non empty Optional with content matching the given matcher * * @param matcher To match against the Optional's content * @param <T> The type of the Optional's content * @param <S> The type matched by the matcher, a subtype of T */ public static <T, S extends T> Matcher<Optional<S>> contains(Matcher<T> matcher) { return new TypeSafeMatcher<Optional<S>>() { @Override protected boolean matchesSafely(Optional<S> item) { return item.map(matcher::matches).orElse(false); } @Override public void describeTo(Description description) { description.appendText("Optional with an item that matches" + matcher); } }; } /** * Matches an empty OptionalInt. */ public static Matcher<OptionalInt> emptyInt() { return new TypeSafeMatcher<OptionalInt>() { @Override protected boolean matchesSafely(OptionalInt item) { return !item.isPresent(); } @Override public void describeTo(Description description) { description.appendText("An empty OptionalInt"); } }; } /** * Matches a non empty OptionalInt with the given content * * @param content Expected contents of the Optional */ public static Matcher<OptionalInt> containsInt(int content) { return new TypeSafeMatcher<OptionalInt>() { @Override protected boolean matchesSafely(OptionalInt item) { return item.isPresent() && item.getAsInt() == content; } @Override public void describeTo(Description description) { description.appendText(Optional.of(content).toString()); } }; } /** * Matches a non empty OptionalInt with content matching the given matcher * * @param matcher To match against the OptionalInt's content */ public static Matcher<OptionalInt> containsInt(Matcher<Integer> matcher) { return new TypeSafeMatcher<OptionalInt>() { @Override protected boolean matchesSafely(OptionalInt item) { return item.isPresent() && matcher.matches(item.getAsInt()); } @Override public void describeTo(Description description) { description.appendText("OptionalInt with an item that matches" + matcher); } }; } /** * Matches an empty OptionalLong. */ public static Matcher<OptionalLong> emptyLong() { return new TypeSafeMatcher<OptionalLong>() { @Override protected boolean matchesSafely(OptionalLong item) { return !item.isPresent(); } @Override public void describeTo(Description description) { description.appendText("An empty OptionalLong"); } }; } /** * Matches a non empty OptionalLong with the given content * * @param content Expected contents of the Optional */ public static Matcher<OptionalLong> containsLong(long content) { return new TypeSafeMatcher<OptionalLong>() { @Override protected boolean matchesSafely(OptionalLong item) { return item.isPresent() && item.getAsLong() == content; } @Override public void describeTo(Description description) { description.appendText(Optional.of(content).toString()); } }; } /** * Matches a non empty OptionalLong with content matching the given matcher * * @param matcher To match against the OptionalLong's content */ public static Matcher<OptionalLong> containsLong(Matcher<Long> matcher) { return new TypeSafeMatcher<OptionalLong>() { @Override protected boolean matchesSafely(OptionalLong item) { return item.isPresent() && matcher.matches(item.getAsLong()); } @Override public void describeTo(Description description) { description.appendText("OptionalLong with an item that matches" + matcher); } }; } /** * Matches an empty OptionalDouble. */ public static Matcher<OptionalDouble> emptyDouble() { return new TypeSafeMatcher<OptionalDouble>() { @Override protected boolean matchesSafely(OptionalDouble item) { return !item.isPresent(); } @Override public void describeTo(Description description) { description.appendText("An empty OptionalDouble"); } }; } /** * Matches a non empty OptionalDouble with the given content * * @param content Expected contents of the Optional */ public static Matcher<OptionalDouble> containsDouble(double content) { return new TypeSafeMatcher<OptionalDouble>() { @Override protected boolean matchesSafely(OptionalDouble item) { return item.isPresent() && item.getAsDouble() == content; } @Override public void describeTo(Description description) { description.appendText(Optional.of(content).toString()); } }; } /** * Matches a non empty OptionalDouble with content matching the given matcher * * @param matcher To match against the OptionalDouble's content */ public static Matcher<OptionalDouble> containsDouble(Matcher<Double> matcher) { return new TypeSafeMatcher<OptionalDouble>() { @Override protected boolean matchesSafely(OptionalDouble item) { return item.isPresent() && matcher.matches(item.getAsDouble()); } @Override public void describeTo(Description description) { description.appendText("OptionalDouble with an item that matches" + matcher); } }; } }