Skip to content

Commit af9d991

Browse files
maskaravivekashishkumar468
authored andcommitted
Fix fetching of bookmarks (#2905)
* Fix fetching of bookmarks * With more robust tests
1 parent a003e97 commit af9d991

File tree

7 files changed

+143
-28
lines changed

7 files changed

+143
-28
lines changed

app/src/main/java/fr/free/nrw/commons/bookmarks/Bookmark.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public class Bookmark {
99
private String mediaName;
1010
private String mediaCreator;
1111

12-
public Bookmark(String mediaName, String mediaCreator) {
13-
this.contentUri = BookmarkPicturesContentProvider.uriForName(mediaName);
12+
public Bookmark(String mediaName, String mediaCreator, Uri contentUri) {
13+
this.contentUri = contentUri;
1414
this.mediaName = mediaName == null ? "" : mediaName;
1515
this.mediaCreator = mediaCreator == null ? "" : mediaCreator;
1616
}

app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java

+20-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package fr.free.nrw.commons.bookmarks.pictures;
22

3+
import org.apache.commons.lang3.StringUtils;
4+
35
import java.util.ArrayList;
46
import java.util.List;
57

@@ -9,6 +11,10 @@
911
import fr.free.nrw.commons.Media;
1012
import fr.free.nrw.commons.bookmarks.Bookmark;
1113
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
14+
import io.reactivex.Observable;
15+
import io.reactivex.ObservableSource;
16+
import io.reactivex.Single;
17+
import io.reactivex.functions.Function;
1218

1319
@Singleton
1420
public class BookmarkPicturesController {
@@ -30,22 +36,21 @@ public BookmarkPicturesController(OkHttpJsonApiClient okHttpJsonApiClient,
3036
* Loads the Media objects from the raw data stored in DB and the API.
3137
* @return a list of bookmarked Media object
3238
*/
33-
List<Media> loadBookmarkedPictures() {
39+
Single<List<Media>> loadBookmarkedPictures() {
3440
List<Bookmark> bookmarks = bookmarkDao.getAllBookmarks();
3541
currentBookmarks = bookmarks;
36-
ArrayList<Media> medias = new ArrayList<>();
37-
for (Bookmark bookmark : bookmarks) {
38-
List<Media> tmpMedias = okHttpJsonApiClient
39-
.getMediaList("search", bookmark.getMediaName())
40-
.blockingGet();
41-
for (Media m : tmpMedias) {
42-
if (m.getCreator().trim().equals(bookmark.getMediaCreator().trim())) {
43-
medias.add(m);
44-
break;
45-
}
46-
}
47-
}
48-
return medias;
42+
return Observable.fromIterable(bookmarks)
43+
.flatMap((Function<Bookmark, ObservableSource<Media>>) this::getMediaFromBookmark)
44+
.filter(media -> media != null && !StringUtils.isBlank(media.getFilename()))
45+
.toList();
46+
}
47+
48+
private Observable<Media> getMediaFromBookmark(Bookmark bookmark) {
49+
Media dummyMedia = new Media("");
50+
return okHttpJsonApiClient.getMedia(bookmark.getMediaName(), false)
51+
.map(media -> media == null ? dummyMedia : media)
52+
.onErrorReturn(throwable -> dummyMedia)
53+
.toObservable();
4954
}
5055

5156
/**
@@ -54,10 +59,7 @@ List<Media> loadBookmarkedPictures() {
5459
*/
5560
boolean needRefreshBookmarkedPictures() {
5661
List<Bookmark> bookmarks = bookmarkDao.getAllBookmarks();
57-
if (bookmarks.size() == currentBookmarks.size()) {
58-
return false;
59-
}
60-
return true;
62+
return bookmarks.size() != currentBookmarks.size();
6163
}
6264

6365
/**

app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesDao.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,11 @@ public boolean findBookmark(Bookmark bookmark) {
149149

150150
@NonNull
151151
Bookmark fromCursor(Cursor cursor) {
152+
String fileName = cursor.getString(cursor.getColumnIndex(Table.COLUMN_MEDIA_NAME));
152153
return new Bookmark(
153-
cursor.getString(cursor.getColumnIndex(Table.COLUMN_MEDIA_NAME)),
154-
cursor.getString(cursor.getColumnIndex(Table.COLUMN_CREATOR))
154+
fileName,
155+
cursor.getString(cursor.getColumnIndex(Table.COLUMN_CREATOR)),
156+
BookmarkPicturesContentProvider.uriForName(fileName)
155157
);
156158
}
157159

app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesFragment.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import android.annotation.SuppressLint;
44
import android.os.Bundle;
5-
import androidx.annotation.NonNull;
6-
import androidx.annotation.Nullable;
75
import android.view.LayoutInflater;
86
import android.view.View;
97
import android.view.ViewGroup;
@@ -19,6 +17,8 @@
1917

2018
import javax.inject.Inject;
2119

20+
import androidx.annotation.NonNull;
21+
import androidx.annotation.Nullable;
2222
import butterknife.BindView;
2323
import butterknife.ButterKnife;
2424
import dagger.android.support.DaggerFragment;
@@ -28,7 +28,6 @@
2828
import fr.free.nrw.commons.category.GridViewAdapter;
2929
import fr.free.nrw.commons.utils.NetworkUtils;
3030
import fr.free.nrw.commons.utils.ViewUtil;
31-
import io.reactivex.Observable;
3231
import io.reactivex.android.schedulers.AndroidSchedulers;
3332
import io.reactivex.disposables.CompositeDisposable;
3433
import io.reactivex.schedulers.Schedulers;
@@ -121,7 +120,7 @@ private void initList() {
121120
progressBar.setVisibility(VISIBLE);
122121
statusTextView.setVisibility(GONE);
123122

124-
compositeDisposable.add(Observable.fromCallable(() -> controller.loadBookmarkedPictures())
123+
compositeDisposable.add(controller.loadBookmarkedPictures()
125124
.subscribeOn(Schedulers.io())
126125
.observeOn(AndroidSchedulers.mainThread())
127126
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)

app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import fr.free.nrw.commons.R;
3131
import fr.free.nrw.commons.auth.SessionManager;
3232
import fr.free.nrw.commons.bookmarks.Bookmark;
33+
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
3334
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
3435
import fr.free.nrw.commons.category.CategoryDetailsActivity;
3536
import fr.free.nrw.commons.category.CategoryImagesActivity;
@@ -262,7 +263,8 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
262263
// Initialize bookmark object
263264
bookmark = new Bookmark(
264265
m.getFilename(),
265-
m.getCreator()
266+
m.getCreator(),
267+
BookmarkPicturesContentProvider.uriForName(m.getFilename())
266268
);
267269
updateBookmarkState(menu.findItem(R.id.menu_bookmark_current_image));
268270

app/src/test/kotlin/fr/free/nrw/commons/bookmarks/pictures/BookmarkPictureDaoTest.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.content.ContentValues
55
import android.database.Cursor
66
import android.database.MatrixCursor
77
import android.database.sqlite.SQLiteDatabase
8+
import android.net.Uri
89
import android.os.RemoteException
910
import com.nhaarman.mockito_kotlin.*
1011
import fr.free.nrw.commons.BuildConfig
@@ -33,7 +34,7 @@ class BookmarkPictureDaoTest {
3334

3435
@Before
3536
fun setUp() {
36-
exampleBookmark = Bookmark("mediaName", "creatorName")
37+
exampleBookmark = Bookmark("mediaName", "creatorName", Uri.EMPTY)
3738
testObject = BookmarkPicturesDao { client }
3839
}
3940

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package fr.free.nrw.commons.bookmarks.pictures;
2+
3+
import android.net.Uri;
4+
5+
import org.junit.Before;
6+
import org.junit.Test;
7+
import org.mockito.InjectMocks;
8+
import org.mockito.Mock;
9+
import org.mockito.MockitoAnnotations;
10+
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import fr.free.nrw.commons.Media;
15+
import fr.free.nrw.commons.bookmarks.Bookmark;
16+
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
17+
import io.reactivex.Single;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.assertFalse;
21+
import static org.junit.Assert.assertTrue;
22+
import static org.mockito.ArgumentMatchers.anyBoolean;
23+
import static org.mockito.ArgumentMatchers.anyString;
24+
import static org.mockito.Mockito.when;
25+
26+
/**
27+
* Tests for bookmark pictures controller
28+
*/
29+
public class BookmarkPicturesControllerTest {
30+
31+
@Mock
32+
OkHttpJsonApiClient okHttpJsonApiClient;
33+
@Mock
34+
BookmarkPicturesDao bookmarkDao;
35+
36+
@InjectMocks
37+
BookmarkPicturesController bookmarkPicturesController;
38+
39+
40+
/**
41+
* Init mocks
42+
*/
43+
@Before
44+
public void setup() {
45+
MockitoAnnotations.initMocks(this);
46+
Media mockMedia = getMockMedia();
47+
when(bookmarkDao.getAllBookmarks())
48+
.thenReturn(getMockBookmarkList());
49+
when(okHttpJsonApiClient.getMedia(anyString(), anyBoolean()))
50+
.thenReturn(Single.just(mockMedia));
51+
}
52+
53+
/**
54+
* Get mock bookmark list
55+
* @return
56+
*/
57+
private List<Bookmark> getMockBookmarkList() {
58+
ArrayList<Bookmark> list = new ArrayList<>();
59+
list.add(new Bookmark("File:Test1.jpg", "Maskaravivek", Uri.EMPTY));
60+
list.add(new Bookmark("File:Test2.jpg", "Maskaravivek", Uri.EMPTY));
61+
return list;
62+
}
63+
64+
/**
65+
* Test case where all bookmark pictures are fetched and media is found against it
66+
*/
67+
@Test
68+
public void loadBookmarkedPictures() {
69+
List<Media> bookmarkedPictures = bookmarkPicturesController.loadBookmarkedPictures().blockingGet();
70+
assertEquals(2, bookmarkedPictures.size());
71+
}
72+
73+
/**
74+
* Test case where all bookmark pictures are fetched and only one media is found
75+
*/
76+
@Test
77+
public void loadBookmarkedPicturesForNullMedia() {
78+
when(okHttpJsonApiClient.getMedia("File:Test1.jpg", false))
79+
.thenReturn(Single.error(new NullPointerException("Error occurred")));
80+
when(okHttpJsonApiClient.getMedia("File:Test2.jpg", false))
81+
.thenReturn(Single.just(getMockMedia()));
82+
List<Media> bookmarkedPictures = bookmarkPicturesController.loadBookmarkedPictures().blockingGet();
83+
assertEquals(1, bookmarkedPictures.size());
84+
}
85+
86+
private Media getMockMedia() {
87+
return new Media("File:Test.jpg");
88+
}
89+
90+
/**
91+
* Test case where current bookmarks don't match the bookmarks in DB
92+
*/
93+
@Test
94+
public void needRefreshBookmarkedPictures() {
95+
boolean needRefreshBookmarkedPictures = bookmarkPicturesController.needRefreshBookmarkedPictures();
96+
assertTrue(needRefreshBookmarkedPictures);
97+
}
98+
99+
/**
100+
* Test case where the DB is up to date with the bookmarks loaded in the list
101+
*/
102+
@Test
103+
public void doNotNeedRefreshBookmarkedPictures() {
104+
List<Media> bookmarkedPictures = bookmarkPicturesController.loadBookmarkedPictures().blockingGet();
105+
assertEquals(2, bookmarkedPictures.size());
106+
boolean needRefreshBookmarkedPictures = bookmarkPicturesController.needRefreshBookmarkedPictures();
107+
assertFalse(needRefreshBookmarkedPictures);
108+
}
109+
}

0 commit comments

Comments
 (0)