diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImageController.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImageController.java deleted file mode 100644 index 5ab5ea6b3..000000000 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImageController.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.free.nrw.commons.category; - -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import fr.free.nrw.commons.Media; -import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; -import io.reactivex.Single; - -@Singleton -public class CategoryImageController { - - private OkHttpJsonApiClient okHttpJsonApiClient; - - @Inject - public CategoryImageController(OkHttpJsonApiClient okHttpJsonApiClient) { - this.okHttpJsonApiClient = okHttpJsonApiClient; - } - - /** - * Takes a category name as input and calls the API to get a list of images for that category - * @param categoryName - * @return - */ - public Single> getCategoryImages(String categoryName) { - return okHttpJsonApiClient.getMediaList("category", categoryName); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java index 2a846413d..2e4f6e0a1 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java @@ -27,6 +27,7 @@ import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.explore.categories.ExploreActivity; import fr.free.nrw.commons.kvstore.JsonKvStore; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -56,7 +57,7 @@ public class CategoryImagesListFragment extends DaggerFragment { private boolean isLoading = true; private String categoryName = null; - @Inject CategoryImageController controller; + @Inject MediaClient mediaClient; @Inject @Named("default_preferences") JsonKvStore categoryKvStore; @@ -116,7 +117,7 @@ public class CategoryImagesListFragment extends DaggerFragment { isLoading = true; progressBar.setVisibility(VISIBLE); - compositeDisposable.add(controller.getCategoryImages(categoryName) + compositeDisposable.add(mediaClient.getMediaListFromCategory(categoryName) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS) @@ -222,7 +223,7 @@ public class CategoryImagesListFragment extends DaggerFragment { } progressBar.setVisibility(VISIBLE); - compositeDisposable.add(controller.getCategoryImages(categoryName) + compositeDisposable.add(mediaClient.getMediaListFromCategory(categoryName) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS) diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java index 5494ae305..000b19570 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java @@ -85,7 +85,6 @@ public class NetworkingModule { WIKIDATA_SPARQL_QUERY_URL, BuildConfig.WIKIMEDIA_CAMPAIGNS_URL, BuildConfig.WIKIMEDIA_API_HOST, - defaultKvStore, gson); } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java index eb32cfb64..895b2ff13 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java @@ -24,7 +24,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.pedrogomez.renderers.RVRendererAdapter; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; @@ -32,18 +31,11 @@ import fr.free.nrw.commons.explore.SearchActivity; import fr.free.nrw.commons.explore.recentsearches.RecentSearch; import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao; import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; -import javax.inject.Inject; -import javax.inject.Named; import timber.log.Timber; import static android.view.View.GONE; @@ -69,7 +61,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { @Inject RecentSearchesDao recentSearchesDao; @Inject - OkHttpJsonApiClient okHttpJsonApiClient; + MediaClient mediaClient; @Inject @Named("default_preferences") JsonKvStore defaultKvStore; @@ -148,7 +140,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { bottomProgressBar.setVisibility(GONE); queryList.clear(); imagesAdapter.clear(); - compositeDisposable.add(okHttpJsonApiClient.getMediaList("search", query) + compositeDisposable.add(mediaClient.getMediaListFromSearch(query) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS) @@ -165,7 +157,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { this.query = query; bottomProgressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(GONE); - compositeDisposable.add(okHttpJsonApiClient.getMediaList("search", query) + compositeDisposable.add(mediaClient.getMediaListFromSearch(query) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS) @@ -228,7 +220,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { private void initErrorView() { progressBar.setVisibility(GONE); imagesNotFoundView.setVisibility(VISIBLE); - imagesNotFoundView.setText(getString(R.string.images_not_found, query)); + imagesNotFoundView.setText(getString(R.string.images_not_found)); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java index fcb45e38c..38e778db7 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java @@ -1,9 +1,19 @@ package fr.free.nrw.commons.media; +import org.wikipedia.dataclient.mwapi.MwQueryResponse; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import javax.inject.Inject; import javax.inject.Singleton; +import fr.free.nrw.commons.Media; +import io.reactivex.Observable; import io.reactivex.Single; /** @@ -14,9 +24,13 @@ public class MediaClient { private final MediaInterface mediaInterface; + //OkHttpJsonApiClient used JsonKvStore for this. I don't know why. + private Map> continuationStore; + @Inject public MediaClient(MediaInterface mediaInterface) { this.mediaInterface = mediaInterface; + this.continuationStore = new HashMap<>(); } /** @@ -43,4 +57,51 @@ public class MediaClient { .query().allImages().size() > 0) .singleOrError(); } + + /** + * This method takes the category as input and returns a list of Media objects filtered using image generator query + * It uses the generator query API to get the images searched using a query, 10 at a time. + * + * @param category the search category. Must start with "Category:" + * @return + */ + public Single> getMediaListFromCategory(String category) { + return responseToMediaList( + continuationStore.containsKey("category_" + category) ? + mediaInterface.getMediaListFromCategory(category, 10, continuationStore.get("category_" + category)) : //if true + mediaInterface.getMediaListFromCategory(category, 10, Collections.emptyMap()), + "category_" + category); //if false + + } + + /** + * This method takes a keyword as input and returns a list of Media objects filtered using image generator query + * It uses the generator query API to get the images searched using a query, 10 at a time. + * + * @param keyword the search keyword + * @return + */ + public Single> getMediaListFromSearch(String keyword) { + return responseToMediaList( + continuationStore.containsKey("search_" + keyword) ? + mediaInterface.getMediaListFromSearch(keyword, 10, continuationStore.get("search_" + keyword)) : //if true + mediaInterface.getMediaListFromSearch(keyword, 10, Collections.emptyMap()), //if false + "search_" + keyword); + + } + + private Single> responseToMediaList(Observable response, String key) { + return response.flatMap(mwQueryResponse -> { + if (null == mwQueryResponse + || null == mwQueryResponse.query() + || null == mwQueryResponse.query().pages()) { + return Observable.empty(); + } + continuationStore.put(key, mwQueryResponse.continuation()); + return Observable.fromIterable(mwQueryResponse.query().pages()); + }) + .map(Media::from) + .collect(ArrayList::new, List::add); + } + } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java index f34ca1dad..94604e6f4 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java @@ -1,10 +1,14 @@ package fr.free.nrw.commons.media; +import org.jetbrains.annotations.NotNull; import org.wikipedia.dataclient.mwapi.MwQueryResponse; +import java.util.Map; + import io.reactivex.Observable; import retrofit2.http.GET; import retrofit2.http.Query; +import retrofit2.http.QueryMap; /** * Interface for interacting with Commons media related APIs @@ -12,6 +16,7 @@ import retrofit2.http.Query; public interface MediaInterface { /** * Checks if a page exists or not. + * * @param title the title of the page to be checked * @return */ @@ -20,9 +25,42 @@ public interface MediaInterface { /** * Check if file exists + * * @param aisha1 the SHA of the media file to be checked * @return */ @GET("w/api.php?action=query&format=json&formatversion=2&list=allimages") Observable checkFileExistsUsingSha(@Query("aisha1") String aisha1); + + + /** + * This method retrieves a list of Media objects filtered using image generator query + * + * @param category the category name. Must start with "Category:" + * @param itemLimit how many images are returned + * @param continuation the continuation string from the previous query or empty map + * @return + */ + @GET("w/api.php?action=query&format=json&formatversion=2" + //Basic parameters + "&generator=categorymembers&gcmtype=file&gcmsort=timestamp&gcmdir=desc" + //Category parameters + "&prop=imageinfo&iiprop=url|extmetadata&iiurlwidth=640" + //Media property parameters + "&iiextmetadatafilter=DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal" + + "|Artist|LicenseShortName|LicenseUrl") + Observable getMediaListFromCategory(@Query("gcmtitle") String category, @Query("gcmlimit") int itemLimit, @QueryMap Map continuation); + + /** + * This method retrieves a list of Media objects filtered using image generator query + * + * @param keyword the searched keyword + * @param itemLimit how many images are returned + * @param continuation the continuation string from the previous query + * @return + */ + @GET("w/api.php?action=query&format=json&formatversion=2" + //Basic parameters + "&generator=search&gsrwhat=text&gsrnamespace=6" + //Search parameters + "&prop=imageinfo&iiprop=url|extmetadata&iiurlwidth=640" + //Media property parameters + "&iiextmetadatafilter=DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal" + + "|Artist|LicenseShortName|LicenseUrl") + Observable getMediaListFromSearch(@Query("gsrsearch") String keyword, @Query("gsrlimit") int itemLimit, @QueryMap Map continuation); + } diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java index 061351c1f..7ed0916b0 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.java @@ -46,15 +46,11 @@ import timber.log.Timber; public class OkHttpJsonApiClient { private static final String THUMB_SIZE = "640"; - public static final Type mapType = new TypeToken>() { - }.getType(); - private final OkHttpClient okHttpClient; private final HttpUrl wikiMediaToolforgeUrl; private final String sparqlQueryUrl; private final String campaignsUrl; private final String commonsBaseUrl; - private final JsonKvStore defaultKvStore; private Gson gson; @@ -64,14 +60,12 @@ public class OkHttpJsonApiClient { String sparqlQueryUrl, String campaignsUrl, String commonsBaseUrl, - JsonKvStore defaultKvStore, Gson gson) { this.okHttpClient = okHttpClient; this.wikiMediaToolforgeUrl = wikiMediaToolforgeUrl; this.sparqlQueryUrl = sparqlQueryUrl; this.campaignsUrl = campaignsUrl; this.commonsBaseUrl = commonsBaseUrl; - this.defaultKvStore = defaultKvStore; this.gson = gson; } @@ -284,6 +278,8 @@ public class OkHttpJsonApiClient { }); } + + /** * Whenever imageInfo is fetched, these common properties can be specified for the API call * https://www.mediawiki.org/wiki/API:Imageinfo @@ -304,124 +300,4 @@ public class OkHttpJsonApiClient { return builder; } - - /** - * This method takes the keyword and queryType as input and returns a list of Media objects filtered using image generator query - * It uses the generator query API to get the images searched using a query, 10 at a time. - * @param queryType queryType can be "search" OR "category" - * @param keyword the search keyword. Can be either category name or search query - * @return - */ - @Nullable - public Single> getMediaList(String queryType, String keyword) { - HttpUrl.Builder urlBuilder = HttpUrl - .parse(commonsBaseUrl) - .newBuilder() - .addQueryParameter("action", "query") - .addQueryParameter("format", "json") - .addQueryParameter("formatversion", "2"); - - - if (queryType.equals("search")) { - appendSearchParam(keyword, urlBuilder); - } else { - appendCategoryParams(keyword, urlBuilder); - } - - appendQueryContinueValues(keyword, urlBuilder); - - Request request = new Request.Builder() - .url(appendMediaProperties(urlBuilder).build()) - .build(); - - return Single.fromCallable(() -> { - Response response = okHttpClient.newCall(request).execute(); - List mediaList = new ArrayList<>(); - if (response.body() != null && response.isSuccessful()) { - String json = response.body().string(); - MwQueryResponse mwQueryResponse = gson.fromJson(json, MwQueryResponse.class); - if (null == mwQueryResponse - || null == mwQueryResponse.query() - || null == mwQueryResponse.query().pages()) { - return mediaList; - } - putContinueValues(keyword, mwQueryResponse.continuation()); - - List pages = mwQueryResponse.query().pages(); - for (MwQueryPage page : pages) { - Media media = Media.from(page); - if (media != null) { - mediaList.add(media); - } - } - } - return mediaList; - }); - } - - /** - * Append params for search query. - * - * @param query the search query to be sent to the API - * @param urlBuilder builder for HttpUrl - */ - private void appendSearchParam(String query, HttpUrl.Builder urlBuilder) { - urlBuilder.addQueryParameter("generator", "search") - .addQueryParameter("gsrwhat", "text") - .addQueryParameter("gsrnamespace", "6") - .addQueryParameter("gsrlimit", "25") - .addQueryParameter("gsrsearch", query); - } - - /** - * It takes a urlBuilder and appends all the continue values as query parameters - * - * @param query - * @param urlBuilder - */ - private void appendQueryContinueValues(String query, HttpUrl.Builder urlBuilder) { - Map continueValues = getContinueValues(query); - if (continueValues != null && continueValues.size() > 0) { - for (Map.Entry entry : continueValues.entrySet()) { - urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); - } - } - } - - /** - * Append parameters for category image generator - * - * @param categoryName name of the category - * @param urlBuilder HttpUrl builder - */ - private void appendCategoryParams(String categoryName, HttpUrl.Builder urlBuilder) { - urlBuilder.addQueryParameter("generator", "categorymembers") - .addQueryParameter("gcmtype", "file") - .addQueryParameter("gcmtitle", categoryName) - .addQueryParameter("gcmsort", "timestamp")//property to sort by;timestamp - .addQueryParameter("gcmdir", "desc")//in which direction to sort;descending - .addQueryParameter("gcmlimit", "10"); - } - - /** - * Stores the continue values for action=query - * These values are sent to the server in the subsequent call to fetch results after this point - * - * @param keyword - * @param values - */ - private void putContinueValues(String keyword, Map values) { - defaultKvStore.putJson("query_continue_" + keyword, values); - } - - /** - * Retrieves a map of continue values from shared preferences. - * These values are appended to the next API call - * - * @param keyword - * @return - */ - private Map getContinueValues(String keyword) { - return defaultKvStore.getJson("query_continue_" + keyword, mapType); - } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt index 0f5901bc6..e7d7fd9c7 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt @@ -1,20 +1,24 @@ package fr.free.nrw.commons.media +import fr.free.nrw.commons.Media import io.reactivex.Observable -import junit.framework.Assert.assertFalse -import junit.framework.Assert.assertTrue +import junit.framework.Assert.* import org.junit.Before import org.junit.Test -import org.mockito.ArgumentMatchers -import org.mockito.InjectMocks -import org.mockito.Mock +import org.mockito.* import org.mockito.Mockito.`when` import org.mockito.Mockito.mock -import org.mockito.MockitoAnnotations import org.wikipedia.dataclient.mwapi.ImageDetails import org.wikipedia.dataclient.mwapi.MwQueryPage import org.wikipedia.dataclient.mwapi.MwQueryResponse import org.wikipedia.dataclient.mwapi.MwQueryResult +import org.wikipedia.gallery.ImageInfo +import org.mockito.ArgumentCaptor +import java.util.* +import org.mockito.Captor + + + class MediaClientTest { @@ -97,4 +101,36 @@ class MediaClientTest { val checkFileExistsUsingSha = mediaClient!!.checkFileExistsUsingSha("abcde").blockingGet() assertFalse(checkFileExistsUsingSha) } + + @Captor + private val continuationCaptor: ArgumentCaptor>? = null + + @Test + fun getMediaListFromCategoryTwice() { + val mockContinuation= mapOf(Pair("gcmcontinue", "test")) + val imageInfo = ImageInfo() + + val mwQueryPage = mock(MwQueryPage::class.java) + `when`(mwQueryPage.title()).thenReturn("Test") + `when`(mwQueryPage.imageInfo()).thenReturn(imageInfo) + + val mwQueryResult = mock(MwQueryResult::class.java) + `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) + + val mockResponse = mock(MwQueryResponse::class.java) + `when`(mockResponse.query()).thenReturn(mwQueryResult) + `when`(mockResponse.continuation()).thenReturn(mockContinuation) + + `when`(mediaInterface!!.getMediaListFromCategory(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), + continuationCaptor!!.capture())) + .thenReturn(Observable.just(mockResponse)) + val media1 = mediaClient!!.getMediaListFromCategory("abcde").blockingGet().get(0) + val media2 = mediaClient!!.getMediaListFromCategory("abcde").blockingGet().get(0) + + assertEquals(continuationCaptor.allValues[0], emptyMap()) + assertEquals(continuationCaptor.allValues[1], mockContinuation) + + assertEquals(media1.filename, "Test") + assertEquals(media2.filename, "Test") + } } \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/OkHttpJsonApiClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/OkHttpJsonApiClientTest.kt index 822277028..8bfb6cb66 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/OkHttpJsonApiClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/OkHttpJsonApiClientTest.kt @@ -4,9 +4,7 @@ import com.google.gson.Gson import fr.free.nrw.commons.Media import fr.free.nrw.commons.TestCommonsApplication import fr.free.nrw.commons.kvstore.JsonKvStore -import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient.mapType import fr.free.nrw.commons.utils.CommonsDateUtil -import junit.framework.Assert.assertEquals import okhttp3.HttpUrl import okhttp3.OkHttpClient import okhttp3.mockwebserver.MockResponse @@ -18,7 +16,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import java.util.* @@ -55,7 +52,7 @@ class OkHttpJsonApiClientTest { val sparqlUrl = "http://" + sparqlServer.hostName + ":" + sparqlServer.port + "/" val campaignsUrl = "http://" + campaignsServer.hostName + ":" + campaignsServer.port + "/" val serverUrl = "http://" + server.hostName + ":" + server.port + "/" - testObject = OkHttpJsonApiClient(okHttpClient, HttpUrl.get(toolsForgeUrl), sparqlUrl, campaignsUrl, serverUrl, sharedPreferences, Gson()) + testObject = OkHttpJsonApiClient(okHttpClient, HttpUrl.get(toolsForgeUrl), sparqlUrl, campaignsUrl, serverUrl, Gson()) } /** @@ -69,96 +66,6 @@ class OkHttpJsonApiClientTest { campaignsServer.shutdown() } - /** - * Test response for category images - */ - @Test - fun getCategoryImages() { - server.enqueue(getFirstPageOfImages()) - testFirstPageQuery() - } - - /** - * test paginated response for category images - */ - @Test - fun getCategoryImagesWithContinue() { - server.enqueue(getFirstPageOfImages()) - server.enqueue(getSecondPageOfImages()) - testFirstPageQuery() - - `when`(sharedPreferences.getJson>("query_continue_Watercraft moored off shore", mapType)) - .thenReturn(hashMapOf(Pair("gcmcontinue", "testvalue"), Pair("continue", "gcmcontinue||"))) - - - val categoryImagesContinued = testObject.getMediaList("category", "Watercraft moored off shore")!!.blockingGet() - - assertBasicRequestParameters(server, "GET").let { request -> - parseQueryParams(request).let { body -> - Assert.assertEquals("json", body["format"]) - Assert.assertEquals("2", body["formatversion"]) - Assert.assertEquals("query", body["action"]) - Assert.assertEquals("categorymembers", body["generator"]) - Assert.assertEquals("file", body["gcmtype"]) - Assert.assertEquals("Watercraft moored off shore", body["gcmtitle"]) - Assert.assertEquals("timestamp", body["gcmsort"]) - Assert.assertEquals("desc", body["gcmdir"]) - Assert.assertEquals("testvalue", body["gcmcontinue"]) - Assert.assertEquals("gcmcontinue||", body["continue"]) - Assert.assertEquals("imageinfo", body["prop"]) - Assert.assertEquals("url|extmetadata", body["iiprop"]) - Assert.assertEquals("DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal|Artist|LicenseShortName|LicenseUrl", body["iiextmetadatafilter"]) - } - } - - assertEquals(categoryImagesContinued.size, 2) - } - - /** - * Test response for search images - */ - @Test - fun getSearchImages() { - server.enqueue(getFirstPageOfImages()) - testFirstPageSearchQuery() - } - - /** - * Test response for paginated search - */ - @Test - fun getSearchImagesWithContinue() { - server.enqueue(getFirstPageOfSearchImages()) - server.enqueue(getSecondPageOfSearchImages()) - testFirstPageSearchQuery() - - `when`(sharedPreferences.getJson>("query_continue_Watercraft moored off shore", mapType)) - .thenReturn(hashMapOf(Pair("gsroffset", "25"), Pair("continue", "gsroffset||"))) - - - val categoryImagesContinued = testObject.getMediaList("search", "Watercraft moored off shore")!!.blockingGet() - - assertBasicRequestParameters(server, "GET").let { request -> - parseQueryParams(request).let { body -> - Assert.assertEquals("json", body["format"]) - Assert.assertEquals("2", body["formatversion"]) - Assert.assertEquals("query", body["action"]) - Assert.assertEquals("search", body["generator"]) - Assert.assertEquals("text", body["gsrwhat"]) - Assert.assertEquals("6", body["gsrnamespace"]) - Assert.assertEquals("25", body["gsrlimit"]) - Assert.assertEquals("Watercraft moored off shore", body["gsrsearch"]) - Assert.assertEquals("25", body["gsroffset"]) - Assert.assertEquals("gsroffset||", body["continue"]) - Assert.assertEquals("imageinfo", body["prop"]) - Assert.assertEquals("url|extmetadata", body["iiprop"]) - Assert.assertEquals("DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal|Artist|LicenseShortName|LicenseUrl", body["iiextmetadatafilter"]) - } - } - - assertEquals(categoryImagesContinued.size, 2) - } - /** * Test response for getting media without generator */ @@ -236,64 +143,6 @@ class OkHttpJsonApiClientTest { assert(media is Media) } - private fun testFirstPageSearchQuery() { - val categoryImages = testObject.getMediaList("search", "Watercraft moored off shore")!!.blockingGet() - - assertBasicRequestParameters(server, "GET").let { request -> - parseQueryParams(request).let { body -> - Assert.assertEquals("json", body["format"]) - Assert.assertEquals("2", body["formatversion"]) - Assert.assertEquals("query", body["action"]) - Assert.assertEquals("search", body["generator"]) - Assert.assertEquals("text", body["gsrwhat"]) - Assert.assertEquals("6", body["gsrnamespace"]) - Assert.assertEquals("25", body["gsrlimit"]) - Assert.assertEquals("Watercraft moored off shore", body["gsrsearch"]) - Assert.assertEquals("imageinfo", body["prop"]) - Assert.assertEquals("url|extmetadata", body["iiprop"]) - Assert.assertEquals("DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal|Artist|LicenseShortName|LicenseUrl", body["iiextmetadatafilter"]) - } - } - assertEquals(categoryImages.size, 2) - } - - private fun testFirstPageQuery() { - val categoryImages = testObject.getMediaList("category", "Watercraft moored off shore")?.blockingGet() - - assertBasicRequestParameters(server, "GET").let { request -> - parseQueryParams(request).let { body -> - Assert.assertEquals("json", body["format"]) - Assert.assertEquals("2", body["formatversion"]) - Assert.assertEquals("query", body["action"]) - Assert.assertEquals("categorymembers", body["generator"]) - Assert.assertEquals("file", body["gcmtype"]) - Assert.assertEquals("Watercraft moored off shore", body["gcmtitle"]) - Assert.assertEquals("timestamp", body["gcmsort"]) - Assert.assertEquals("desc", body["gcmdir"]) - Assert.assertEquals("imageinfo", body["prop"]) - Assert.assertEquals("url|extmetadata", body["iiprop"]) - Assert.assertEquals("DateTime|Categories|GPSLatitude|GPSLongitude|ImageDescription|DateTimeOriginal|Artist|LicenseShortName|LicenseUrl", body["iiextmetadatafilter"]) - } - } - assertEquals(categoryImages?.size, 2) - } - - private fun getFirstPageOfImages(): MockResponse { - return getMediaList("gcmcontinue", "testvalue", "gcmcontinue||", 2) - } - - private fun getSecondPageOfImages(): MockResponse { - return getMediaList("gcmcontinue", "testvalue2", "gcmcontinue||", 2) - } - - private fun getFirstPageOfSearchImages(): MockResponse { - return getMediaList("gsroffset", "25", "gsroffset||", 2) - } - - private fun getSecondPageOfSearchImages(): MockResponse { - return getMediaList("gsroffset", "25", "gsroffset||", 2) - } - /** * Generate a MockResponse object which contains a list of media pages */