package uk.ivanc.archimvvm;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.Collections;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.adapter.rxjava.HttpException;
import rx.Observable;
import rx.schedulers.Schedulers;
import uk.ivanc.archimvvm.model.GithubService;
import uk.ivanc.archimvvm.model.Repository;
import uk.ivanc.archimvvm.util.MockModelFabric;
import uk.ivanc.archimvvm.viewmodel.MainViewModel;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainViewModelTest {
GithubService githubService;
ArchiApplication application;
MainViewModel mainViewModel;
MainViewModel.DataListener dataListener;
@Before
public void setUp() {
githubService = mock(GithubService.class);
dataListener = mock(MainViewModel.DataListener.class);
application = (ArchiApplication) RuntimeEnvironment.application;
// Mock the retrofit service so we don't call the API directly
application.setGithubService(githubService);
// Change the default subscribe schedulers so all observables
// will now run on the same thread
application.setDefaultSubscribeScheduler(Schedulers.immediate());
mainViewModel = new MainViewModel(application, dataListener);
}
@Test
public void shouldSearchUsernameWithRepos() {
String username = "usernameWithRepos";
TextView textView = new TextView(application);
textView.setText(username);
List<Repository> mockRepos = MockModelFabric.newListOfRepositories(10);
doReturn(rx.Observable.just(mockRepos)).when(githubService).publicRepositories(username);
mainViewModel.onSearchAction(textView, EditorInfo.IME_ACTION_SEARCH, null);
verify(dataListener).onRepositoriesChanged(mockRepos);
assertEquals(mainViewModel.infoMessageVisibility.get(), View.INVISIBLE);
assertEquals(mainViewModel.progressVisibility.get(), View.INVISIBLE);
assertEquals(mainViewModel.recyclerViewVisibility.get(), View.VISIBLE);
}
@Test
public void shouldSearchInvalidUsername() {
String username = "invalidUsername";
TextView textView = new TextView(application);
textView.setText(username);
HttpException mockHttpException =
new HttpException(Response.error(404, mock(ResponseBody.class)));
when(githubService.publicRepositories(username))
.thenReturn(Observable.<List<Repository>>error(mockHttpException));
mainViewModel.onSearchAction(textView, EditorInfo.IME_ACTION_SEARCH, null);
verify(dataListener, never()).onRepositoriesChanged(anyListOf(Repository.class));
assertEquals(mainViewModel.infoMessage.get(),
application.getString(R.string.error_username_not_found));
assertEquals(mainViewModel.infoMessageVisibility.get(), View.VISIBLE);
assertEquals(mainViewModel.progressVisibility.get(), View.INVISIBLE);
assertEquals(mainViewModel.recyclerViewVisibility.get(), View.INVISIBLE);
}
@Test
public void shouldSearchUsernameWithNoRepos() {
String username = "usernameWithoutRepos";
TextView textView = new TextView(application);
textView.setText(username);
when(githubService.publicRepositories(username))
.thenReturn(Observable.just(Collections.<Repository>emptyList()));
mainViewModel.onSearchAction(textView, EditorInfo.IME_ACTION_SEARCH, null);
verify(dataListener).onRepositoriesChanged(Collections.<Repository>emptyList());
assertEquals(mainViewModel.infoMessage.get(),
application.getString(R.string.text_empty_repos));
assertEquals(mainViewModel.infoMessageVisibility.get(), View.VISIBLE);
assertEquals(mainViewModel.progressVisibility.get(), View.INVISIBLE);
assertEquals(mainViewModel.recyclerViewVisibility.get(), View.INVISIBLE);
}
}