package com.quran.labs.androidquran.presenter.bookmark;
import android.content.Context;
import android.content.res.Resources;
import com.quran.labs.androidquran.dao.Bookmark;
import com.quran.labs.androidquran.dao.BookmarkData;
import com.quran.labs.androidquran.dao.RecentPage;
import com.quran.labs.androidquran.dao.Tag;
import com.quran.labs.androidquran.database.BookmarksDBAdapter;
import com.quran.labs.androidquran.model.bookmark.BookmarkModel;
import com.quran.labs.androidquran.model.bookmark.BookmarkResult;
import com.quran.labs.androidquran.model.bookmark.RecentPageModel;
import com.quran.labs.androidquran.util.QuranSettings;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import io.reactivex.Single;
import io.reactivex.android.plugins.RxAndroidPlugins;
import io.reactivex.observers.TestObserver;
import io.reactivex.schedulers.Schedulers;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
public class BookmarkPresenterTest {
private static final List<Tag> TAG_LIST;
private static final List<RecentPage> RECENTS_LIST;
private static final List<Bookmark> AYAH_BOOKMARKS_LIST;
private static final List<Bookmark> MIXED_BOOKMARKS_LIST;
private static final String[] RESOURCE_ARRAY;
private static final int AYAH_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG;
private static final int MIXED_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG;
static {
// a list of two tags
TAG_LIST = new ArrayList<>(2);
TAG_LIST.add(new Tag(1, "First Tag"));
TAG_LIST.add(new Tag(2, "Second Tag"));
// recent page
RECENTS_LIST = new ArrayList<>(1);
RECENTS_LIST.add(new RecentPage(42, System.currentTimeMillis()));
// two ayah bookmarks
AYAH_BOOKMARKS_LIST = new ArrayList<>(2);
AYAH_BOOKMARKS_LIST.add(
new Bookmark(42, 46, 1, 502, System.currentTimeMillis(), Collections.singletonList(2L)));
AYAH_BOOKMARKS_LIST.add(new Bookmark(2, 2, 4, 2, System.currentTimeMillis() - 60000));
// two ayah bookmarks and one page bookmark
MIXED_BOOKMARKS_LIST = new ArrayList<>(AYAH_BOOKMARKS_LIST);
MIXED_BOOKMARKS_LIST.add(0,
new Bookmark(23, null, null, 400, System.currentTimeMillis() + 1, Arrays.asList(1L, 2L)));
// we return this fake array when getStringArray is called
RESOURCE_ARRAY = new String[114];
for (int i = 0; i < 114; i++) {
RESOURCE_ARRAY[i] = String.valueOf(i);
}
// figure out how many rows the bookmarks would occupy if grouped by tags - this is really
// the max between number of tags and 1 for each bookmark.
int total = 0;
for (Bookmark bookmark : AYAH_BOOKMARKS_LIST) {
int tags = bookmark.tags.size();
total += Math.max(tags, 1);
}
AYAH_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG = total;
total = 0;
for (Bookmark bookmark : MIXED_BOOKMARKS_LIST) {
int tags = bookmark.tags.size();
total += Math.max(tags, 1);
}
MIXED_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG = total;
}
@Mock private Context appContext;
@Mock private Resources resources;
@Mock private QuranSettings settings;
@Mock private BookmarksDBAdapter bookmarksAdapter;
@Mock private RecentPageModel recentPageModel;
@BeforeClass
public static void setup() {
RxAndroidPlugins.setInitMainThreadSchedulerHandler(schedulerCallable -> Schedulers.io());
}
@Before
public void setupTest() {
MockitoAnnotations.initMocks(BookmarkPresenterTest.this);
QuranSettings.setInstance(settings);
when(appContext.getString(anyInt())).thenReturn("Test");
when(appContext.getResources()).thenReturn(resources);
when(resources.getStringArray(anyInt())).thenReturn(RESOURCE_ARRAY);
when(appContext.getApplicationContext()).thenReturn(appContext);
}
@Test
public void testBookmarkObservableAyahBookmarksByDate() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(new ArrayList<>()),
Single.just(AYAH_BOOKMARKS_LIST),
Single.just(new ArrayList<>()),
BookmarkData::new);
}
};
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, false);
assertThat(result.tagMap).isEmpty();
// 1 for the header, plus one row per item
assertThat(result.rows).hasSize(AYAH_BOOKMARKS_LIST.size() + 1);
}
@Test
public void testBookmarkObservableMixedBookmarksByDate() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(new ArrayList<>()),
Single.just(MIXED_BOOKMARKS_LIST),
Single.just(new ArrayList<>()),
BookmarkData::new);
}
};
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, false);
assertThat(result.tagMap).isEmpty();
// 1 for "page bookmarks" and 1 for "ayah bookmarks"
assertThat(result.rows).hasSize(MIXED_BOOKMARKS_LIST.size() + 2);
}
@Test
public void testBookmarkObservableMixedBookmarksByDateWithRecentPage() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(TAG_LIST),
Single.just(MIXED_BOOKMARKS_LIST),
Single.just(RECENTS_LIST),
BookmarkData::new);
}
};
when(settings.getLastPage()).thenReturn(42);
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, false);
assertThat(result.tagMap).hasSize(2);
// 2 for "current page", 1 for "page bookmarks" and 1 for "ayah bookmarks"
assertThat(result.rows).hasSize(MIXED_BOOKMARKS_LIST.size() + 4);
}
@Test
public void testBookmarkObservableAyahBookmarksGroupedByTag() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(TAG_LIST),
Single.just(AYAH_BOOKMARKS_LIST),
Single.just(new ArrayList<>()),
BookmarkData::new);
}
};
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, true);
assertThat(result.tagMap).hasSize(2);
// number of tags (or 1) for each bookmark, plus number of tags (headers), plus unsorted
assertThat(result.rows).hasSize(
AYAH_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG + TAG_LIST.size() + 1);
}
@Test
public void testBookmarkObservableMixedBookmarksGroupedByTag() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(TAG_LIST),
Single.just(MIXED_BOOKMARKS_LIST),
Single.just(new ArrayList<>()),
BookmarkData::new);
}
};
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, true);
assertThat(result.tagMap).hasSize(2);
// number of tags (or 1) for each bookmark, plus number of tags (headers), plus unsorted
assertThat(result.rows).hasSize(
MIXED_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG + TAG_LIST.size() + 1);
}
@Test
public void testBookmarkObservableMixedBookmarksGroupedByTagWithRecentPage() {
BookmarkModel model = new BookmarkModel(bookmarksAdapter, recentPageModel) {
@Override
public Single<BookmarkData> getBookmarkDataObservable(int sortOrder) {
return Single.zip(
Single.just(TAG_LIST),
Single.just(MIXED_BOOKMARKS_LIST),
Single.just(RECENTS_LIST),
BookmarkData::new);
}
};
BookmarkPresenter presenter = makeBookmarkPresenter(model);
BookmarkResult result = getBookmarkResultByDateAndValidate(presenter, true);
assertThat(result.tagMap).hasSize(2);
// number of tags (or 1) for each bookmark, plus number of tags (headers), plus unsorted, plus
// current page header, plus current page
assertThat(result.rows).hasSize(
MIXED_BOOKMARKS_ROW_COUNT_WHEN_GROUPED_BY_TAG + TAG_LIST.size() + 1 + 2);
}
private BookmarkPresenter makeBookmarkPresenter(BookmarkModel model) {
return new BookmarkPresenter(appContext, model, settings, null) {
@Override
void subscribeToChanges() {
// nothing
}
};
}
private BookmarkResult getBookmarkResultByDateAndValidate(BookmarkPresenter presenter,
boolean groupByTags) {
TestObserver<BookmarkResult> testObserver =
presenter.getBookmarksListObservable(BookmarksDBAdapter.SORT_DATE_ADDED, groupByTags)
.test();
testObserver.awaitTerminalEvent();
testObserver.assertNoErrors();
testObserver.assertValueCount(1);
return testObserver.values().get(0);
}
}