package com.llamacorp.equate.test; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.support.test.InstrumentationRegistry; import android.support.test.espresso.FailureHandler; import android.support.test.espresso.NoMatchingViewException; import android.support.test.espresso.base.DefaultFailureHandler; import android.support.test.rule.ActivityTestRule; import android.util.Log; import android.view.View; import com.llamacorp.equate.view.CalcActivity; import org.hamcrest.Matcher; import java.io.File; import static android.support.test.InstrumentationRegistry.getTargetContext; /** * This class was created to allow for custom setup and tear down code before * and after the activity runs. This includes a custom error handler that can * perform additional duties besides printing the stack trace (maybe take a * screenshot) */ class MyActivityTestRule<A extends CalcActivity> extends ActivityTestRule<A> { public MyActivityTestRule(Class<A> activityClass) { super(activityClass); } public MyActivityTestRule(Class<A> activityClass, boolean initialTouchMode) { super(activityClass, initialTouchMode); } public MyActivityTestRule(Class<A> activityClass, boolean initialTouchMode, boolean launchActivity) { super(activityClass, initialTouchMode, launchActivity); } /** * Override this method to execute any code that should run before your {@link Activity} is * created and launched. * This method is called before each test method, including any method annotated with * <a href="http://junit.sourceforge.net/javadoc/org/junit/Before.html"><code>Before</code></a>. */ @Override protected void beforeActivityLaunched() { super.beforeActivityLaunched(); resetSharedPrefs(); // setFailureHandler(new CustomFailureHandle(getInstrumentation().getTargetContext())); } /** * Override this method to execute any code that should run after your {@link Activity} is * launched, but before any test code is run including any method annotated with * <a href="http://junit.sourceforge.net/javadoc/org/junit/Before.html"><code>Before</code></a>. * <p> * Prefer * <a href="http://junit.sourceforge.net/javadoc/org/junit/Before.html"><code>Before</code></a> * over this method. This method should usually not be overwritten directly in tests and only be * used by subclasses of ActivityTestRule to get notified when the activity is created and * visible but test runs. */ @Override protected void afterActivityLaunched() { super.afterActivityLaunched(); } private void resetSharedPrefs() { File root = getTargetContext().getFilesDir().getParentFile(); String[] sharedPreferencesFileNames = new File(root, "shared_prefs").list(); if (sharedPreferencesFileNames == null) return; for (String fileName : sharedPreferencesFileNames) { SharedPreferences sp = InstrumentationRegistry.getTargetContext() .getSharedPreferences(fileName.replace(".xml", ""), Context.MODE_PRIVATE); sp.edit().clear().apply(); File fileToDelete = new File(root + "/shared_prefs/" + fileName); boolean wasSuccessful = fileToDelete.delete(); Log.d("ESPRESSO_LOG", "File deleted = " + String.valueOf(wasSuccessful)); } } private static class CustomFailureHandle implements FailureHandler { private final FailureHandler delegate; public CustomFailureHandle(Context targetContext) { delegate = new DefaultFailureHandler(targetContext); } /** * Handle the given error in a manner that makes sense to the environment * in which the test is executed (e.g. take a screenshot, output extra * debug info, etc). Upon handling, most handlers will choose to propagate * the error. * * @param error * @param viewMatcher */ @Override public void handle(Throwable error, Matcher<View> viewMatcher) { try { delegate.handle(error, viewMatcher); } catch (NoMatchingViewException e) { throw new MySpecialException(e); } } private static class MySpecialException extends RuntimeException { MySpecialException(Throwable cause) { super(cause); } } } }