package com.prateekj.snooper.espresso; import android.support.test.espresso.IdlingResource; import android.util.Log; import android.view.View; import org.hamcrest.Matcher; import static java.lang.Thread.sleep; public class ViewMatcherIdlingResource implements IdlingResource { private static final int MATCHER_POLLING_INTERVAL_IN_MILLIS = 100; public static final String TAG = ViewMatcherIdlingResource.class.getSimpleName(); private int waitTimeInMillis; private final Matcher<? super View> viewMatcher; private final View view; private ResourceCallback resourceCallback; private long startTime; private boolean matched; public ViewMatcherIdlingResource(final int waitTimeInMillis, final Matcher<? super View> viewMatcher, final View view) { this.waitTimeInMillis = waitTimeInMillis; this.viewMatcher = viewMatcher; this.view = view; matched = false; } @Override public String getName() { return this.getClass().getName(); } @Override public boolean isIdleNow() { boolean timeExceeded = now() - startTime >= waitTimeInMillis; if(matched || timeExceeded) { resourceCallback.onTransitionToIdle(); } return matched || timeExceeded; } public boolean isMatched() { return matched; } @Override public void registerIdleTransitionCallback(final ResourceCallback resourceCallback) { startTime = now(); this.resourceCallback = resourceCallback; pollViewUntilMatchesOrTimeout(resourceCallback); } private void pollViewUntilMatchesOrTimeout(final ResourceCallback resourceCallback) { Thread thread = new Thread(new Runnable() { @Override public void run() { while (!viewMatcher.matches(view) && now() - startTime < waitTimeInMillis) { try { Log.d(TAG, "polling view to match " + viewMatcher.toString()); sleep(MATCHER_POLLING_INTERVAL_IN_MILLIS); } catch (InterruptedException ignored) { } } matched = viewMatcher.matches(view); resourceCallback.onTransitionToIdle(); } }); thread.start(); } private long now() { return System.currentTimeMillis(); } }