public class ModelTest extends IntegrationBaseTest {

    @Inject
    protected ApiInterface apiInterface;

    @Inject
    protected Model model;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        component.inject(this);
    }

    @Test
    public void testGetRepoList() {

        TestSubscriber<List<RepositoryDTO>> testSubscriber = new TestSubscriber<>();
        model.getRepoList(TestConst.TEST_OWNER).subscribe(testSubscriber);

        testSubscriber.assertNoErrors();
        testSubscriber.assertValueCount(1);

        List<RepositoryDTO> actual = testSubscriber.getOnNextEvents().get(0);

        assertEquals(7, actual.size());
        assertEquals("Android-Rate", actual.get(0).getName());
        assertEquals("andrey7mel/Android-Rate", actual.get(0).getFullName());
        assertEquals(26314692, actual.get(0).getId());
    }

    @Test
    public void testGetRepoBranches() {

        TestSubscriber<List<BranchDTO>> testSubscriber = new TestSubscriber<>();
        model.getRepoBranches(TestConst.TEST_OWNER, TestConst.TEST_REPO).subscribe(testSubscriber);

        testSubscriber.assertNoErrors();
        testSubscriber.assertValueCount(1);

        List<BranchDTO> actual = testSubscriber.getOnNextEvents().get(0);

        assertEquals(3, actual.size());
        assertEquals("QuickStart", actual.get(0).getName());
        assertEquals("94870e23f1cfafe7201bf82985b61188f650b245", actual.get(0).getCommit().getSha());

    }

    @Test
    public void testGetRepoContributors() {

        TestSubscriber<List<ContributorDTO>> testSubscriber = new TestSubscriber<>();
        model.getRepoContributors(TestConst.TEST_OWNER, TestConst.TEST_REPO).subscribe(testSubscriber);

        testSubscriber.assertNoErrors();
        testSubscriber.assertValueCount(1);

        List<ContributorDTO> actual = testSubscriber.getOnNextEvents().get(0);

        assertEquals(11, actual.size());
        assertEquals("hotchemi", actual.get(0).getLogin());
        assertEquals("User", actual.get(0).getType());
        assertEquals(471318, actual.get(0).getId());

    }
} @RunWith(RobolectricGradleTestRunner.class)
@Config(application = IntegrationTestApp.class,
        constants = BuildConfig.class,
        sdk = 21)
@Ignore
public class IntegrationBaseTest {

    public IntegrationTestComponent component;
    public TestUtils testUtils;

    @Inject
    protected MockWebServer mockWebServer;

    @Before
    public void setUp() throws Exception {
        component = (IntegrationTestComponent) App.getComponent();
        testUtils = new TestUtils();
        component.inject(this);
    }

    @After
    public void tearDown() throws Exception {
        mockWebServer.shutdown();
    }

    protected void setErrorAnswerWebServer() {
        mockWebServer.setDispatcher(new Dispatcher() {
            @Override
            public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
                return new MockResponse().setResponseCode(500);
            }
        });
    }

    protected void setCustomAnswer(boolean enableBranches, boolean enableContributors) {
        mockWebServer.setDispatcher(new Dispatcher() {
            @Override
            public MockResponse dispatch(RecordedRequest request) throws InterruptedException {

                if (request.getPath().equals("/users/" + TestConst.TEST_OWNER + "/repos")) {
                    return new MockResponse().setResponseCode(200)
                            .setBody(testUtils.readString("json/repos.json"));
                } else if (request.getPath().equals("/repos/" + TestConst.TEST_OWNER + "/" + TestConst.TEST_REPO + "/branches") && enableBranches) {
                    return new MockResponse().setResponseCode(200)
                            .setBody(testUtils.readString("json/branches.json"));
                } else if (request.getPath().equals("/repos/" + TestConst.TEST_OWNER + "/" + TestConst.TEST_REPO + "/contributors") && enableContributors) {
                    return new MockResponse().setResponseCode(200)
                            .setBody(testUtils.readString("json/contributors.json"));
                }
                return new MockResponse().setResponseCode(404);
            }
        });

    }

} public class RepoInfoPresenterTest extends IntegrationBaseTest {

    @Inject
    protected List<Contributor> contributorList;

    @Inject
    protected List<Branch> branchList;

    @Inject
    protected RepoBranchesMapper branchesMapper;

    @Inject
    protected RepoContributorsMapper contributorsMapper;

    @Inject
    protected Repository repository;

    @Inject
    protected Model model;

    private RepoInfoView mockView;
    private RepoInfoPresenter repoInfoPresenter;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        component.inject(this);

        mockView = mock(RepoInfoView.class);
        repoInfoPresenter = new RepoInfoPresenter();
        repoInfoPresenter.onCreate(mockView, repository);
    }


    @Test
    public void testLoadData() {
        repoInfoPresenter.onCreateView(null);
        repoInfoPresenter.onStop();


        verify(mockView).showBranches(branchList);
        verify(mockView).showContributors(contributorList);
    }

    @Test
    public void testLoadDataWithError() {
        setErrorAnswerWebServer();

        repoInfoPresenter.onCreateView(null);
        repoInfoPresenter.onStop();

        verify(mockView, times(2)).showError(TestConst.ERROR_RESPONSE_500);
    }

    @Test
    public void testOnErrorBranches() {
        setCustomAnswer(false, true);

        repoInfoPresenter.onCreateView(null);

        verify(mockView).showError(TestConst.ERROR_RESPONSE_404);
        verify(mockView).showContributors(contributorList);
    }

    @Test
    public void testOnErrorContributors() {
        setCustomAnswer(true, false);

        repoInfoPresenter.onCreateView(null);

        verify(mockView).showError(TestConst.ERROR_RESPONSE_404);
        verify(mockView).showBranches(branchList);
    }


    @Test
    public void testSaveState() {
        repoInfoPresenter.onCreateView(null);

        Bundle bundle = Bundle.EMPTY;
        repoInfoPresenter.onSaveInstanceState(bundle);
        repoInfoPresenter.onStop();

        repoInfoPresenter.onCreateView(bundle);

        verify(mockView, times(2)).showBranches(branchList);
        verify(mockView, times(2)).showContributors(contributorList);
    }


    @Test
    public void testShowLoading() {
        repoInfoPresenter.onCreateView(null);

        verify(mockView).showLoading();
    }

    @Test
    public void testHideLoading() {
        repoInfoPresenter.onCreateView(null);

        verify(mockView).hideLoading();
    }

    @Test
    public void testShowLoadingOnError() {
        setErrorAnswerWebServer();

        repoInfoPresenter.onCreateView(null);

        verify(mockView).showLoading();
    }

    @Test
    public void testHideLoadingOnError() {
        setErrorAnswerWebServer();

        repoInfoPresenter.onCreateView(null);

        verify(mockView).hideLoading();
    }

    @Test
    public void testShowLoadingOnErrorBranches() {
        setCustomAnswer(false, true);

        repoInfoPresenter.onCreateView(null);

        verify(mockView).showLoading();
    }

    @Test
    public void testHideLoadingOnErrorBranches() {
        setCustomAnswer(false, true);

        repoInfoPresenter.onCreateView(null);

        verify(mockView).hideLoading();
    }

    @Test
    public void testShowLoadingOnErrorContributors() {
        setCustomAnswer(true, false);


        repoInfoPresenter.onCreateView(null);

        verify(mockView).showLoading();
    }

    @Test
    public void testHideLoadingOnErrorContributors() {
        setCustomAnswer(true, false);

        repoInfoPresenter.onCreateView(null);

        verify(mockView).hideLoading();
    }


} public class RepoListPresenterTest extends IntegrationBaseTest {

    @Inject
    protected RepoListMapper repoListMapper;

    @Inject
    protected Model model;

    @Inject
    protected List<Repository> repoList;

    private RepoListView mockView;
    private RepoListPresenter repoListPresenter;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        component.inject(this);

        mockView = mock(RepoListView.class);
        doAnswer(invocation -> TestConst.TEST_OWNER)
                .when(mockView)
                .getUserName();
        repoListPresenter = new RepoListPresenter(mockView);
    }


    @Test
    public void testLoadData() {
        repoListPresenter.onCreateView(null);
        repoListPresenter.onSearchButtonClick();
        repoListPresenter.onStop();

        verify(mockView).showRepoList(repoList);
    }


    @Test
    public void testEmptyName() {
        doAnswer(invocation -> "")
                .when(mockView)
                .getUserName();

        repoListPresenter.onSearchButtonClick();

        verify(mockView, never()).showEmptyList();
        verify(mockView, never()).showRepoList(repoList);

    }

    @Test
    public void testClickRepo() {
        Repository repository = new Repository(TestConst.TEST_REPO, TestConst.TEST_OWNER);

        repoListPresenter.clickRepo(repository);

        verify(mockView).startRepoInfoFragment(repository);
    }

    @Test
    public void testLoadDataWithError() {
        setErrorAnswerWebServer();
        repoListPresenter.onCreateView(null);
        repoListPresenter.onSearchButtonClick();
        repoListPresenter.onStop();

        verify(mockView).showError(TestConst.ERROR_RESPONSE_500);
    }


    @Test
    public void testSaveState() {
        repoListPresenter.onCreateView(null);
        repoListPresenter.onSearchButtonClick();

        Bundle bundle = Bundle.EMPTY;
        repoListPresenter.onSaveInstanceState(bundle);
        repoListPresenter.onStop();

        repoListPresenter.onCreateView(bundle);

        verify(mockView, times(2)).showRepoList(repoList);
    }


    @Test
    public void testLoadingState() {
        repoListPresenter.onCreateView(null);
        repoListPresenter.onSearchButtonClick();
        repoListPresenter.onStop();

        verify(mockView).showLoading();
        verify(mockView).hideLoading();
    }

    @Test
    public void testOnErrorLoadingState() {
        setErrorAnswerWebServer();
        repoListPresenter.onSearchButtonClick();

        verify(mockView).showLoading();
        verify(mockView).hideLoading();
    }
} public class RepoInfoFragmentTest extends IntegrationBaseTest {

    @Inject
    protected List<Contributor> contributorList;

    @Inject
    protected List<Branch> branchList;

    @Inject
    protected Repository repository;

    private RepoInfoFragment repoInfoFragment;
    private MainActivity activity;


    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        component.inject(this);
        repoInfoFragment = spy(RepoInfoFragment.newInstance(repository));
        activity = Robolectric.setupActivity(MainActivity.class);
        repoInfoFragment.onAttach(activity);
    }


    @Test
    public void testLoadData() {
        repoInfoFragment.onCreate(null);
        repoInfoFragment.onCreateView(LayoutInflater.from(activity), (ViewGroup) activity.findViewById(R.id.container), null);
        verify(repoInfoFragment).showBranches(branchList);
        verify(repoInfoFragment).showContributors(contributorList);

    }


    @Test
    public void testLoadDataWithError() {
        setErrorAnswerWebServer();
        repoInfoFragment.onCreate(null);
        repoInfoFragment.onCreateView(LayoutInflater.from(activity), (ViewGroup) activity.findViewById(R.id.container), null);
        verify(repoInfoFragment, times(2)).showError(TestConst.ERROR_RESPONSE_500);
    }
} public class RepoListFragmentTest extends IntegrationBaseTest {

    @Inject
    protected List<Repository> repoList;

    private RepoListFragment repoListFragment;

    private MainActivity activity;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        component.inject(this);

        repoListFragment = spy(new RepoListFragment());
        activity = Robolectric.setupActivity(MainActivity.class);
        repoListFragment.onAttach(activity);
        doAnswer(invocation -> TestConst.TEST_OWNER)
                .when(repoListFragment)
                .getUserName();

    }

    @Test
    public void testOnCreate() {
        repoListFragment.onCreate(null);
        repoListFragment.onCreateView(LayoutInflater.from(activity), (ViewGroup) activity.findViewById(R.id.container), null);
        repoListFragment.onClickSearch(null);
        repoListFragment.onStop();
        verify(repoListFragment).showRepoList(repoList);
    }

    @Test
    public void testOnCreateWithError() {
        setErrorAnswerWebServer();
        repoListFragment.onCreate(null);
        repoListFragment.onCreateView(LayoutInflater.from(activity), (ViewGroup) activity.findViewById(R.id.container), null);
        repoListFragment.onClickSearch(null);
        repoListFragment.onStop();
        verify(repoListFragment).showError(TestConst.ERROR_RESPONSE_500);
    }

} @Singleton
@Component(modules = {ModelModule.class, PresenterModule.class, ViewModule.class})
public interface AppComponent {

    void inject(ModelImpl dataRepository);

    void inject(BasePresenter basePresenter);

    void inject(RepoListPresenter repoListPresenter);

    void inject(RepoInfoPresenter repoInfoPresenter);

    void inject(RepoInfoFragment repoInfoFragment);

} @Module
public class DataTestModule {

    private TestUtils testUtils;

    public DataTestModule() {
        testUtils = new TestUtils();
    }

    @Provides
    @Singleton
    TestUtils provideTestUtils() {
        return testUtils;
    }

    @Provides
    @Singleton
    Repository provideRepository() {
        return new Repository(TestConst.TEST_REPO, TestConst.TEST_OWNER);
    }


    @Provides
    @Singleton
    List<ContributorDTO> provideContributorDTOList() {
        ContributorDTO[] contributorDTOArray = testUtils.getGson().fromJson(testUtils.readString("json/contributors.json"), ContributorDTO[].class);
        return Arrays.asList(contributorDTOArray);
    }


    @Provides
    @Singleton
    List<BranchDTO> provideBranchDTOList() {
        BranchDTO[] branchDTOArray = testUtils.getGson().fromJson(testUtils.readString("json/branches.json"), BranchDTO[].class);
        return Arrays.asList(branchDTOArray);
    }

    @Provides
    @Singleton
    List<RepositoryDTO> provideRepositoryDTOList() {
        RepositoryDTO[] repositoryDTOArray = testUtils.getGson().fromJson(testUtils.readString("json/repos.json"), RepositoryDTO[].class);
        return Arrays.asList(repositoryDTOArray);
    }

    @Provides
    @Singleton
    List<Repository> provideRepositoryList(RepoListMapper repoListMapper, List<RepositoryDTO> list) {
        return repoListMapper.call(list);
    }

    @Provides
    @Singleton
    List<Contributor> provideContributorList(RepoContributorsMapper contributorsMapper, List<ContributorDTO> contributorDTOs) {
        return contributorsMapper.call(contributorDTOs);
    }

    @Provides
    @Singleton
    List<Branch> provideBranchList(RepoBranchesMapper branchesMapper, List<BranchDTO> branchDTOs) {
        return branchesMapper.call(branchDTOs);
    }


} @Module

public class PresenterModule {

    @Provides
    @Singleton
    Model provideDataRepository() {
        return new ModelImpl();
    }

    @Provides
    CompositeSubscription provideCompositeSubscription() {
        return new CompositeSubscription();
    }

} @Module
public class ViewModule {

    @Provides
    RepoInfoPresenter provideRepoInfoPresenter() {
        return new RepoInfoPresenter();
    }

}
import com.andrey7mel.stepbystep.integration.model.ModelTest;
import com.andrey7mel.stepbystep.integration.other.IntegrationBaseTest;
import com.andrey7mel.stepbystep.integration.presenter.RepoInfoPresenterTest;
import com.andrey7mel.stepbystep.integration.presenter.RepoListPresenterTest;
import com.andrey7mel.stepbystep.integration.view.RepoInfoFragmentTest;
import com.andrey7mel.stepbystep.integration.view.RepoListFragmentTest;
import com.andrey7mel.stepbystep.other.di.AppComponent;
import com.andrey7mel.stepbystep.other.di.DataTestModule;
import com.andrey7mel.stepbystep.other.di.PresenterModule;
import com.andrey7mel.stepbystep.other.di.ViewModule;
import javax.inject.Singleton;
import dagger.Component;
package com.andrey7mel.stepbystep.integration.other.di;




@Singleton
@Component(modules = {IntegrationTestModelModule.class, PresenterModule.class, ViewModule.class, DataTestModule.class})
public interface IntegrationTestComponent extends AppComponent {

    void inject(ModelTest modelTest);

    void inject(RepoInfoPresenterTest repoInfoPresenterTest);