public class ComponentBuilder {
    private AppComponent appComponent;

    public ComponentBuilder(AppComponent appComponent) {
        this.appComponent = appComponent;
    }

    public PlacesComponent placesComponent() {
        return appComponent.plus(new PlacesModule());
    }

    public PurchaseComponent purchaseComponent() {
        return appComponent.plus(new PurchaseModule());
    }
} public interface IPurchaseApi {
    Observable<Boolean> submitPurchase(String creditCard, String email);
} @Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
    PlacesComponent plus(PlacesModule placesModule);
    PurchaseComponent plus(PurchaseModule purchaseModule);
} @ViewScope
@Subcomponent(modules = {PurchaseModule.class})
public interface PurchaseComponent {
    void inject(PurchaseActivity purchaseActivity);
} @Module
public class PurchaseModule {
    @Provides
    @ViewScope
    public IPurchaseApi providePurchaseApi(Gson gson) {
        return new PurchaseApi(gson);
    }

    @Provides
    @ViewScope
    public IPurchaseViewModel providePurchaseViewModel(IPurchaseApi purchaseApi) {
        return new PurchaseViewModel(purchaseApi);
    }
} public class ApplicationUtils {
    public static TestApplication application() {
        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
        return (TestApplication) instrumentation.getTargetContext().getApplicationContext();
    }
} public class UiUtils {
    public static void resetTintColor(Context context, View view) {
        TintManager tintManager = TintManager.get(context);
        ViewCompat.setBackgroundTintList(view,
                tintManager.getTintList(android.support.design.R.drawable.abc_edit_text_material));
    }

    public static void showDialog(String text, Context context) {
        new AlertDialog.Builder(context)
                .setMessage(text)
                .setPositiveButton(android.R.string.yes, (dialog, which) -> {
                })
                .show();
    }

    public static void closeKeyboard(Activity context) {
        // Check if no view has focus:
        View view = context.getCurrentFocus();
        if (view != null) {
            InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
} public static Matcher<View> hasListener() {
    return new TypeSafeMatcher<View>() {
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        @Override
        protected boolean matchesSafely(View view) {
            return view.hasOnClickListeners();
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("has onclick listener");
        }
    };
} public static Matcher<View> hasResId(int resId) {
    return new TypeSafeMatcher<View>() {
        @Override
        public void describeTo(Description description) {
            description.appendText("has resId");
        }

        @Override
        public boolean matchesSafely(View view) {
            try {
                return ((MyTextView) view).getBackgroundResource() == resId;
            } catch (Exception exception) {
                return false;
            }
        }
    };
} public static Matcher<View> isVisible() {
    return new TypeSafeMatcher<View>() {
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        @Override
        protected boolean matchesSafely(View view) {
            return view.getVisibility() == View.VISIBLE;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("is visible");
        }
    };
} public static void waitText(final String viewText, final long millis) throws Exception {
    Thread.sleep(millis);
    onView(withText(viewText)).check(matches(isDisplayed()));
}
import android.content.Intent;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.MediumTest;
import com.google.gson.Gson;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import apidez.com.android_mvvm_sample.ComponentBuilder;
import apidez.com.android_mvvm_sample.R;
import apidez.com.android_mvvm_sample.model.api.IPurchaseApi;
import apidez.com.android_mvvm_sample.dependency.component.AppComponent;
import apidez.com.android_mvvm_sample.dependency.component.PurchaseComponent;
import apidez.com.android_mvvm_sample.dependency.module.PurchaseModule;
import apidez.com.android_mvvm_sample.utils.ApplicationUtils;
import apidez.com.android_mvvm_sample.utils.UiUtils;
import rx.Observable;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static apidez.com.android_mvvm_sample.utils.MatcherEx.hasListener;
import static apidez.com.android_mvvm_sample.utils.MatcherEx.hasResId;
import static apidez.com.android_mvvm_sample.utils.MatcherEx.isVisible;
import static apidez.com.android_mvvm_sample.utils.MatcherEx.waitText;
import static org.hamcrest.Matchers.not;
package apidez.com.android_mvvm_sample.view.activity;






/**
 * Created by nongdenchet on 10/3/15.
 */

/**
 * Test the whole flow mocking long running task
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class PurchaseActivityIntegrationTest {
    private String FAIL_CARD = "222222222222";

    @Rule
    public ActivityTestRule<PurchaseActivity> activityTestRule =
            new ActivityTestRule<>(PurchaseActivity.class, true, false);

    @Before
    public void setUp() throws Exception {
        PurchaseModule mockModule = new PurchaseModule() {
            @Override
            public IPurchaseApi providePurchaseApi(Gson gson) {