package com.artemzin.qualitymatters.functional_tests.rules;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingResource;
import com.artemzin.qualitymatters.functional_tests.TestUtils;
import com.artemzin.qualitymatters.performance.AsyncJobsObserver;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class AsyncJobsObserverRule implements TestRule {
@Override
@NonNull
public Statement apply(@NonNull Statement base, @NonNull Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
final AsyncJobsIdlingResource asyncJobsIdlingResource = new AsyncJobsIdlingResource(TestUtils.app().applicationComponent().asyncJobsObserver());
try {
Espresso.registerIdlingResources(asyncJobsIdlingResource);
base.evaluate();
} finally {
asyncJobsIdlingResource.release();
Espresso.unregisterIdlingResources(asyncJobsIdlingResource);
}
}
};
}
static class AsyncJobsIdlingResource implements IdlingResource {
@NonNull
final AsyncJobsObserver asyncJobsObserver;
@Nullable
private AsyncJobsObserver.Listener listener;
AsyncJobsIdlingResource(@NonNull AsyncJobsObserver asyncJobsObserver) {
this.asyncJobsObserver = asyncJobsObserver;
}
@Override
@NonNull
public String getName() {
return "AsyncJobsObserver-IdlingResource";
}
@Override
public boolean isIdleNow() {
return asyncJobsObserver.numberOfRunningAsyncJobs() == 0;
}
@Override
public void registerIdleTransitionCallback(@NonNull ResourceCallback callback) {
if (listener != null) { // Just in case if Espresso call this several times per instance.
asyncJobsObserver.removeListener(listener);
}
listener = numberOfRunningAsyncJobs -> {
if (numberOfRunningAsyncJobs == 0) {
callback.onTransitionToIdle();
}
};
asyncJobsObserver.addListener(listener);
}
public void release() {
if (listener != null) {
asyncJobsObserver.removeListener(listener);
}
}
}
}