/*
* Copyright 2015 Jacek Marchwicki <jacek.marchwicki@gmail.com>
*
* 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.appunite.rx.example.ui.main;
import com.appunite.login.CurrentLoggedInUserDao;
import com.appunite.rx.ResponseOrError;
import com.appunite.rx.example.dao.auth.MyCurrentLoggedInUserDao;
import com.appunite.rx.example.dao.posts.PostsDao;
import com.appunite.rx.example.dao.posts.model.Post;
import com.appunite.rx.example.dao.posts.model.PostsIdsResponse;
import com.appunite.rx.example.dao.posts.model.PostsResponse;
import com.google.common.collect.ImmutableList;
import com.jacekmarchwicki.universaladapter.BaseAdapterItem;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
import javax.annotation.Nonnull;
import rx.Observable;
import rx.observers.TestSubscriber;
import rx.schedulers.TestScheduler;
import rx.subjects.TestSubject;
import static com.google.common.truth.Truth.assert_;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.when;
public class MainPresenterTest {
@Mock
PostsDao postsDao;
@Mock
MyCurrentLoggedInUserDao myCurrentLoggedInUserDao;
@Mock
CurrentLoggedInUserDao.LoggedInUserDao loggedInUserDao;
private MainPresenter mainPresenter;
private final TestScheduler scheduler = new TestScheduler();
private TestSubject<ResponseOrError<PostsResponse>> postsSubject = TestSubject.create(scheduler);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(postsDao.postsObservable()).thenReturn(postsSubject);
when(postsDao.postsIdsObservable()).thenReturn(Observable.<ResponseOrError<PostsIdsResponse>>never());
when(myCurrentLoggedInUserDao.currentLoggedInUserObservable())
.thenReturn(
Observable.just(ResponseOrError.fromData(loggedInUserDao))
.mergeWith(Observable.<ResponseOrError<CurrentLoggedInUserDao.LoggedInUserDao>>never()));
when(loggedInUserDao.authTokenObservable(anyBoolean()))
.thenReturn(Observable.just("auth_token"));
mainPresenter = new MainPresenter(postsDao, myCurrentLoggedInUserDao, scheduler);
}
@Test
public void testAfterStart_presenterIsNotNull() throws Exception {
assert_().that(mainPresenter).isNotNull();
}
@Test
public void testBeforeDownload_progressBarIsShown() throws Exception {
final TestSubscriber<Boolean> progress = new TestSubscriber<>();
mainPresenter.progressObservable().subscribe(progress);
assert_().that(progress.getOnNextEvents())
.isEqualTo(ImmutableList.of(true));
progress.assertNoErrors();
}
@Test
public void testAfterDownload_progressBarIsHidden() throws Exception {
final TestSubscriber<Boolean> progress = new TestSubscriber<>();
mainPresenter.progressObservable().subscribe(progress);
postsSubject.onNext(sampleData());
scheduler.triggerActions();
assert_().that(progress.getOnNextEvents())
.isEqualTo(ImmutableList.of(true, false));
progress.assertNoErrors();
}
@Nonnull
private ResponseOrError<PostsResponse> sampleData() {
return ResponseOrError.fromData(new PostsResponse("some_title", ImmutableList.<Post>of(), null));
}
@Test
public void testBeforeDownload_errorIsNull() throws Exception {
final TestSubscriber<Throwable> error = new TestSubscriber<>();
mainPresenter.errorObservable().subscribe(error);
assert_().that(error.getOnNextEvents())
.contains(null);
error.assertNoErrors();
}
@Test
public void testAfterSuccessDownload_errorIsStillNull() throws Exception {
final TestSubscriber<Throwable> error = new TestSubscriber<>();
mainPresenter.errorObservable().subscribe(error);
postsSubject.onNext(sampleData());
scheduler.triggerActions();
assert_().that(error.getOnNextEvents())
.contains(null);
error.assertNoErrors();
}
@Test
public void testAfterFailedDownload_errorIsSet() throws Exception {
final Exception e = new Exception();
final TestSubscriber<Throwable> error = new TestSubscriber<>();
mainPresenter.errorObservable().subscribe(error);
postsSubject.onNext(ResponseOrError.<PostsResponse>fromError(e));
scheduler.triggerActions();
assert_().that(error.getOnNextEvents())
.containsExactly(null, e)
.inOrder();
error.assertNoErrors();
}
@Test
public void testAfterSuccessDownload_titleIsSet() throws Exception {
final TestSubscriber<String> title = new TestSubscriber<>();
mainPresenter.titleObservable().subscribe(title);
postsSubject.onNext(sampleData());
scheduler.triggerActions();
assert_().that(title.getOnNextEvents())
.contains("some_title");
title.assertNoErrors();
}
@Test
public void testBeforeDownload_titleIsNotSet() throws Exception {
final TestSubscriber<String> title = new TestSubscriber<>();
mainPresenter.titleObservable().subscribe(title);
assert_().that(title.getOnNextEvents())
.isEmpty();
title.assertNoErrors();
}
@Test
public void testBeforeDownload_doNotPropagateItems() throws Exception {
final TestSubscriber<List<BaseAdapterItem>> items = new TestSubscriber<>();
mainPresenter.itemsObservable().subscribe(items);
assert_().that(items.getOnNextEvents())
.isEmpty();
items.assertNoErrors();
}
@Test
public void testAfterDownloadEmptyArray_emptyItemsArrayIsPropagated() throws Exception {
final TestSubscriber<List<BaseAdapterItem>> items = new TestSubscriber<>();
mainPresenter.itemsObservable().subscribe(items);
postsSubject.onNext(sampleData());
scheduler.triggerActions();
assert_().that(items.getOnNextEvents())
.contains(ImmutableList.of());
items.assertNoErrors();
}
@Test
public void testAfterDownload_itemsArePropagated() throws Exception {
final TestSubscriber<List<BaseAdapterItem>> items = new TestSubscriber<>();
mainPresenter.itemsObservable().subscribe(items);
postsSubject.onNext(ResponseOrError.fromData(new PostsResponse("",
ImmutableList.of(new Post("123", "krowa")), null)));
scheduler.triggerActions();
assert_().that(items.getOnNextEvents()).hasSize(1);
assert_().that(items.getOnNextEvents().get(0)).hasSize(1);
assert_().that(items.getOnNextEvents().get(0).get(0))
.isInstanceOf(MainPresenter.AdapterItem.class);
final MainPresenter.AdapterItem firstItem = (MainPresenter.AdapterItem) items
.getOnNextEvents().get(0).get(0);
assert_().that(firstItem.text()).isEqualTo("krowa");
assert_().that(firstItem.id()).isEqualTo("123");
items.assertNoErrors();
}
@Test
public void testAfterClickOnFirstItem_openDetails() throws Exception {
// Subscribe to open details
final TestSubscriber<MainPresenter.AdapterItem> openDetails = new TestSubscriber<>();
mainPresenter.openDetailsObservable().subscribe(openDetails);
// Download item
final TestSubscriber<List<BaseAdapterItem>> items = new TestSubscriber<>();
mainPresenter.itemsObservable().subscribe(items);
postsSubject.onNext(ResponseOrError.fromData(new PostsResponse("",
ImmutableList.of(new Post("123", "krowa")), null)));
scheduler.triggerActions();
final BaseAdapterItem itemToClick = items.getOnNextEvents().get(0).get(0);
// user click
assert_().that(itemToClick).isInstanceOf(MainPresenter.AdapterItem.class);
((MainPresenter.AdapterItem)itemToClick).clickObserver().onNext(null);
// verify if details opened
assert_().that(openDetails.getOnNextEvents())
.contains(itemToClick);
openDetails.assertNoErrors();
}
}