/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.example.github.ui.user;
import com.android.example.github.R;
import com.android.example.github.binding.FragmentBindingAdapters;
import com.android.example.github.testing.SingleFragmentActivity;
import com.android.example.github.ui.common.NavigationController;
import com.android.example.github.util.RecyclerViewMatcher;
import com.android.example.github.util.TestUtil;
import com.android.example.github.util.ViewModelUtil;
import com.android.example.github.vo.Repo;
import com.android.example.github.vo.Resource;
import com.android.example.github.vo.User;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.arch.lifecycle.MutableLiveData;
import android.support.annotation.NonNull;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import java.util.ArrayList;
import java.util.List;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
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.hasDescendant;
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 org.hamcrest.CoreMatchers.not;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(AndroidJUnit4.class)
public class UserFragmentTest {
@Rule
public ActivityTestRule<SingleFragmentActivity> activityRule =
new ActivityTestRule<>(SingleFragmentActivity.class, true, true);
private UserViewModel viewModel;
private NavigationController navigationController;
private FragmentBindingAdapters fragmentBindingAdapters;
private MutableLiveData<Resource<User>> userData = new MutableLiveData<>();
private MutableLiveData<Resource<List<Repo>>> repoListData = new MutableLiveData<>();
@Before
public void init() {
UserFragment fragment = UserFragment.create("foo");
viewModel = mock(UserViewModel.class);
when(viewModel.getUser()).thenReturn(userData);
when(viewModel.getRepositories()).thenReturn(repoListData);
navigationController = mock(NavigationController.class);
fragmentBindingAdapters = mock(FragmentBindingAdapters.class);
fragment.viewModelFactory = ViewModelUtil.createFor(viewModel);
fragment.navigationController = navigationController;
fragment.dataBindingComponent = () -> fragmentBindingAdapters;
activityRule.getActivity().setFragment(fragment);
}
@Test
public void loading() {
userData.postValue(Resource.loading(null));
onView(withId(R.id.progress_bar)).check(matches(isDisplayed()));
onView(withId(R.id.retry)).check(matches(not(isDisplayed())));
}
@Test
public void error() {
userData.postValue(Resource.error("wtf", null));
onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
onView(withId(R.id.error_msg)).check(matches(withText("wtf")));
onView(withId(R.id.retry)).check(matches(isDisplayed()));
onView(withId(R.id.retry)).perform(click());
verify(viewModel).retry();
}
@Test
public void loadingWithUser() {
User user = TestUtil.createUser("foo");
userData.postValue(Resource.loading(user));
onView(withId(R.id.name)).check(matches(withText(user.name)));
onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
}
@Test
public void loadedUser() {
User user = TestUtil.createUser("foo");
userData.postValue(Resource.success(user));
onView(withId(R.id.name)).check(matches(withText(user.name)));
onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
}
@Test
public void loadRepos() {
List<Repo> repos = setRepos(2);
for (int pos = 0; pos < repos.size(); pos ++) {
Repo repo = repos.get(pos);
onView(listMatcher().atPosition(pos)).check(
matches(hasDescendant(withText(repo.name))));
onView(listMatcher().atPosition(pos)).check(
matches(hasDescendant(withText(repo.description))));
onView(listMatcher().atPosition(pos)).check(
matches(hasDescendant(withText("" + repo.stars))));
}
Repo repo3 = setRepos(3).get(2);
onView(listMatcher().atPosition(2)).check(
matches(hasDescendant(withText(repo3.name))));
}
@Test
public void clickRepo() {
List<Repo> repos = setRepos(2);
Repo selected = repos.get(1);
onView(withText(selected.description)).perform(click());
verify(navigationController).navigateToRepo(selected.owner.login, selected.name);
}
@Test
public void nullUser() {
userData.postValue(null);
onView(withId(R.id.name)).check(matches(not(isDisplayed())));
}
@Test
public void nullRepoList() {
repoListData.postValue(null);
onView(listMatcher().atPosition(0)).check(doesNotExist());
}
@Test
public void nulledUser() {
User user = TestUtil.createUser("foo");
userData.postValue(Resource.success(user));
onView(withId(R.id.name)).check(matches(withText(user.name)));
userData.postValue(null);
onView(withId(R.id.name)).check(matches(not(isDisplayed())));
}
@Test
public void nulledRepoList() {
setRepos(5);
onView(listMatcher().atPosition(1)).check(matches(isDisplayed()));
repoListData.postValue(null);
onView(listMatcher().atPosition(0)).check(doesNotExist());
}
@NonNull
private RecyclerViewMatcher listMatcher() {
return new RecyclerViewMatcher(R.id.repo_list);
}
private List<Repo> setRepos(int count) {
List<Repo> repos = new ArrayList<>();
for (int i = 0; i < count; i++) {
repos.add(TestUtil.createRepo("foo", "name " + i, "desc" + i));
}
repoListData.postValue(Resource.success(repos));
return repos;
}
}