From 78141cb609248a92bf9006045ad99ba8f992513c Mon Sep 17 00:00:00 2001 From: Vivek Maskara Date: Thu, 20 Jun 2019 20:56:07 +0530 Subject: [PATCH] With media client APIs migrated to retrofit (#2998) * With media client APIs migrated to retrofit * Add test cases and java docs * Fix test * Fix build * Fix build and other minor issues * Fix tests --- app/build.gradle | 2 +- .../main/java/fr/free/nrw/commons/Media.java | 21 ++-- .../free/nrw/commons/MediaDataExtractor.java | 11 +- .../nrw/commons/OkHttpConnectionFactory.java | 2 +- .../free/nrw/commons/di/NetworkingModule.java | 11 +- .../free/nrw/commons/media/MediaClient.java | 46 ++++++++ .../nrw/commons/media/MediaInterface.java | 28 +++++ .../mwapi/ApacheHttpClientMediaWikiApi.java | 32 +----- .../free/nrw/commons/mwapi/MediaWikiApi.java | 6 -- .../free/nrw/commons/review/ReviewHelper.java | 7 +- .../upload/ImageProcessingService.java | 9 +- .../nrw/commons/upload/UploadService.java | 8 +- .../nrw/commons/MediaDataExtractorTest.kt | 6 +- .../free/nrw/commons/media/MediaClientTest.kt | 100 ++++++++++++++++++ .../mwapi/ApacheHttpClientMediaWikiApiTest.kt | 18 ---- .../nrw/commons/review/ReviewHelperTest.kt | 13 ++- .../upload/ImageProcessingServiceTest.kt | 24 +++-- 17 files changed, 252 insertions(+), 92 deletions(-) create mode 100644 app/src/main/java/fr/free/nrw/commons/media/MediaClient.java create mode 100644 app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt diff --git a/app/build.gradle b/app/build.gradle index 569a176ff..f5e3cb3dc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ dependencies { implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1' implementation 'com.facebook.fresco:fresco:1.13.0' implementation 'com.drewnoakes:metadata-extractor:2.11.0' - implementation 'com.dmitrybrant:wikimedia-android-data-client:0.0.18' implementation 'org.apache.commons:commons-lang3:3.8.1' + implementation 'com.dmitrybrant:wikimedia-android-data-client:0.0.23' // UI implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java index 568071b13..62a11a90a 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.java +++ b/app/src/main/java/fr/free/nrw/commons/Media.java @@ -4,6 +4,9 @@ import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.apache.commons.lang3.StringUtils; import org.wikipedia.dataclient.mwapi.MwQueryPage; import org.wikipedia.gallery.ExtMetadata; @@ -20,8 +23,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.utils.CommonsDateUtil; import fr.free.nrw.commons.utils.MediaDataExtractorUtil; @@ -156,9 +157,9 @@ public class Media implements Parcelable { page.title(), "", 0, - safeParseDate(metadata.dateTimeOriginal().value()), - safeParseDate(metadata.dateTime().value()), - StringUtil.fromHtml(metadata.artist().value()).toString() + safeParseDate(metadata.dateTime()), + safeParseDate(metadata.dateTime()), + StringUtil.fromHtml(metadata.artist()).toString() ); if (!StringUtils.isBlank(imageInfo.getThumbUrl())) { @@ -170,17 +171,17 @@ public class Media implements Parcelable { language = "default"; } - media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription().value())); - media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories().value())); - String latitude = metadata.gpsLatitude().value(); - String longitude = metadata.gpsLongitude().value(); + media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription())); + media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.getCategories())); + String latitude = metadata.getGpsLatitude(); + String longitude = metadata.getGpsLongitude(); if (!StringUtils.isBlank(latitude) && !StringUtils.isBlank(longitude)) { LatLng latLng = new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude), 0); media.setCoordinates(latLng); } - media.setLicenseInformation(metadata.licenseShortName().value(), metadata.licenseUrl().value()); + media.setLicenseInformation(metadata.licenseShortName(), metadata.licenseUrl()); return media; } diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java index 4779e0455..4e63bdf7d 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java @@ -1,9 +1,11 @@ package fr.free.nrw.commons; +import androidx.core.text.HtmlCompat; + import javax.inject.Inject; import javax.inject.Singleton; -import androidx.core.text.HtmlCompat; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; import io.reactivex.Single; @@ -19,12 +21,15 @@ import timber.log.Timber; public class MediaDataExtractor { private final MediaWikiApi mediaWikiApi; private final OkHttpJsonApiClient okHttpJsonApiClient; + private final MediaClient mediaClient; @Inject public MediaDataExtractor(MediaWikiApi mwApi, - OkHttpJsonApiClient okHttpJsonApiClient) { + OkHttpJsonApiClient okHttpJsonApiClient, + MediaClient mediaClient) { this.okHttpJsonApiClient = okHttpJsonApiClient; this.mediaWikiApi = mwApi; + this.mediaClient = mediaClient; } /** @@ -35,7 +40,7 @@ public class MediaDataExtractor { */ public Single fetchMediaDetails(String filename) { Single mediaSingle = getMediaFromFileName(filename); - Single pageExistsSingle = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename); + Single pageExistsSingle = mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + filename); Single discussionSingle = getDiscussion(filename); return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, (media, deletionStatus, discussion) -> { media.setDiscussion(discussion); diff --git a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java index 94be306cf..e77a82618 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -31,7 +31,7 @@ public final class OkHttpConnectionFactory { return new OkHttpClient.Builder() .cookieJar(SharedPreferenceCookieManager.getInstance()) .cache(NET_CACHE) - .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC)) + .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .addInterceptor(new UnsuccessfulResponseInterceptor()) .addInterceptor(new CommonHeaderRequestInterceptor()) .build(); 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 c8664cd9f..103f0d9a8 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 @@ -19,6 +19,7 @@ import dagger.Module; import dagger.Provides; import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.kvstore.JsonKvStore; +import fr.free.nrw.commons.media.MediaInterface; import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; @@ -39,6 +40,8 @@ public class NetworkingModule { public static final long OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; + private static final String NAMED_COMMONS_WIKI_SITE = "commons-wikisite"; + @Provides @Singleton public OkHttpClient provideOkHttpClient(Context context, @@ -120,7 +123,13 @@ public class NetworkingModule { @Provides @Singleton - public ReviewInterface provideReviewInterface(@Named("commons-wikisite") WikiSite commonsWikiSite) { + public ReviewInterface provideReviewInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) { return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, ReviewInterface.class); } + + @Provides + @Singleton + public MediaInterface provideMediaInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) { + return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, MediaInterface.class); + } } 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 new file mode 100644 index 000000000..fcb45e38c --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.java @@ -0,0 +1,46 @@ +package fr.free.nrw.commons.media; + + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.reactivex.Single; + +/** + * Media Client to handle custom calls to Commons MediaWiki APIs + */ +@Singleton +public class MediaClient { + + private final MediaInterface mediaInterface; + + @Inject + public MediaClient(MediaInterface mediaInterface) { + this.mediaInterface = mediaInterface; + } + + /** + * Checks if a page exists on Commons + * The same method can be used to check for file or talk page + * + * @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg + */ + public Single checkPageExistsUsingTitle(String title) { + return mediaInterface.checkPageExistsUsingTitle(title) + .map(mwQueryResponse -> mwQueryResponse + .query().firstPage().pageId() > 0) + .singleOrError(); + } + + /** + * Take the fileSha and returns whether a file with a matching SHA exists or not + * + * @param fileSha SHA of the file to be checked + */ + public Single checkFileExistsUsingSha(String fileSha) { + return mediaInterface.checkFileExistsUsingSha(fileSha) + .map(mwQueryResponse -> mwQueryResponse + .query().allImages().size() > 0) + .singleOrError(); + } +} 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 new file mode 100644 index 000000000..f34ca1dad --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java @@ -0,0 +1,28 @@ +package fr.free.nrw.commons.media; + +import org.wikipedia.dataclient.mwapi.MwQueryResponse; + +import io.reactivex.Observable; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * Interface for interacting with Commons media related APIs + */ +public interface MediaInterface { + /** + * Checks if a page exists or not. + * @param title the title of the page to be checked + * @return + */ + @GET("w/api.php?action=query&format=json&formatversion=2") + Observable checkPageExistsUsingTitle(@Query("titles") String title); + + /** + * 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); +} diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 8f5b4213f..727a8f2a2 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -4,6 +4,9 @@ import android.content.Context; import android.net.Uri; import android.text.TextUtils; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.google.gson.Gson; import org.apache.commons.lang3.StringUtils; @@ -32,8 +35,6 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.Callable; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; @@ -224,23 +225,6 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { return centralAuthToken; } - @Override - public boolean fileExistsWithName(String fileName) throws IOException { - return api.action("query") - .param("prop", "imageinfo") - .param("titles", "File:" + fileName) - .get() - .getNodes("/api/query/pages/page/imageinfo").size() > 0; - } - - @Override - public Single pageExists(String pageName) { - return Single.fromCallable(() -> Double.parseDouble(api.action("query") - .param("titles", pageName) - .get() - .getString("/api/query/pages/page/@_idx")) != -1); - } - @Override public boolean thank(String editToken, long revision) throws IOException { CustomApiResult res = api.action("thank") @@ -749,16 +733,6 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { return gson.fromJson(queryContinueString, QueryContinue.class); } - @Override - public boolean existingFile(String fileSha1) throws IOException { - return api.action("query") - .param("format", "xml") - .param("list", "allimages") - .param("aisha1", fileSha1) - .get() - .getNodes("/api/query/allimages/img").size() > 0; - } - @Override @NonNull public Single uploadFile( diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java index e38c4dc0f..9fafacfff 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java @@ -30,10 +30,6 @@ public interface MediaWikiApi { String getCentralAuthToken() throws IOException; - boolean fileExistsWithName(String fileName) throws IOException; - - Single pageExists(String pageName); - List getSubCategoryList(String categoryName); List getParentCategoryList(String categoryName); @@ -87,8 +83,6 @@ public interface MediaWikiApi { @Nullable String revisionsByFilename(String filename) throws IOException; - boolean existingFile(String fileSha1) throws IOException; - @NonNull LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException; diff --git a/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java b/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java index 03f67bfcf..76256c6a5 100644 --- a/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java +++ b/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java @@ -14,6 +14,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import fr.free.nrw.commons.Media; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; import io.reactivex.Observable; @@ -26,14 +27,16 @@ public class ReviewHelper { private final OkHttpJsonApiClient okHttpJsonApiClient; private final MediaWikiApi mediaWikiApi; + private final MediaClient mediaClient; private final ReviewInterface reviewInterface; @Inject public ReviewHelper(OkHttpJsonApiClient okHttpJsonApiClient, MediaWikiApi mediaWikiApi, - ReviewInterface reviewInterface) { + MediaClient mediaClient, ReviewInterface reviewInterface) { this.okHttpJsonApiClient = okHttpJsonApiClient; this.mediaWikiApi = mediaWikiApi; + this.mediaClient = mediaClient; this.reviewInterface = reviewInterface; } @@ -86,7 +89,7 @@ public class ReviewHelper { */ private Single getRandomMediaFromRecentChange(RecentChange recentChange) { return Single.just(recentChange) - .flatMap(change -> mediaWikiApi.pageExists("Commons:Deletion_requests/" + change.getTitle())) + .flatMap(change -> mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + change.getTitle())) .flatMap(isDeleted -> { if (isDeleted) { return Single.just(new Media("")); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java index a397823dc..3baaf9959 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java @@ -10,6 +10,7 @@ import java.io.IOException; import javax.inject.Inject; import javax.inject.Singleton; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.utils.ImageUtils; @@ -34,18 +35,20 @@ public class ImageProcessingService { private final MediaWikiApi mwApi; private final ReadFBMD readFBMD; private final EXIFReader EXIFReader; + private final MediaClient mediaClient; private final Context context; @Inject public ImageProcessingService(FileUtilsWrapper fileUtilsWrapper, ImageUtilsWrapper imageUtilsWrapper, MediaWikiApi mwApi, ReadFBMD readFBMD, EXIFReader EXIFReader, - Context context) { + MediaClient mediaClient, Context context) { this.fileUtilsWrapper = fileUtilsWrapper; this.imageUtilsWrapper = imageUtilsWrapper; this.mwApi = mwApi; this.readFBMD = readFBMD; this.EXIFReader = EXIFReader; + this.mediaClient = mediaClient; this.context = context; } @@ -128,7 +131,7 @@ public class ImageProcessingService { return Single.just(EMPTY_TITLE); } - return Single.fromCallable(() -> mwApi.fileExistsWithName(uploadItem.getFileName())) + return mediaClient.checkPageExistsUsingTitle("File:" + uploadItem.getFileName()) .map(doesFileExist -> { Timber.d("Result for valid title is %s", doesFileExist); return doesFileExist ? FILE_NAME_EXISTS : IMAGE_OK; @@ -146,7 +149,7 @@ public class ImageProcessingService { return Single.fromCallable(() -> fileUtilsWrapper.getFileInputStream(filePath)) .map(fileUtilsWrapper::getSHA1) - .map(mwApi::existingFile) + .flatMap(mediaClient::checkFileExistsUsingSha) .map(b -> { Timber.d("Result for duplicate image %s", b); return b ? ImageUtils.IMAGE_DUPLICATE : ImageUtils.IMAGE_OK; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 39addbdee..7e10846a9 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -8,9 +8,10 @@ import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; +import android.widget.Toast; + import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import android.widget.Toast; import java.io.File; import java.io.FileInputStream; @@ -33,6 +34,7 @@ import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionDao; import fr.free.nrw.commons.contributions.ContributionsContentProvider; import fr.free.nrw.commons.contributions.MainActivity; +import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.wikidata.WikidataEditService; import io.reactivex.Single; @@ -54,6 +56,8 @@ public class UploadService extends HandlerService { @Inject WikidataEditService wikidataEditService; @Inject SessionManager sessionManager; @Inject ContributionDao contributionDao; + @Inject + MediaClient mediaClient; private NotificationManagerCompat notificationManager; private NotificationCompat.Builder curNotification; @@ -337,7 +341,7 @@ public class UploadService extends HandlerService { sequenceFileName = regexMatcher.replaceAll("$1 " + sequenceNumber + "$2"); } } - if (!mwApi.fileExistsWithName(sequenceFileName) + if (!mediaClient.checkPageExistsUsingTitle(sequenceFileName).blockingGet() && !unfinishedUploads.contains(sequenceFileName)) { break; } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/MediaDataExtractorTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/MediaDataExtractorTest.kt index cf87f9cd6..5f224f7a8 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/MediaDataExtractorTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/MediaDataExtractorTest.kt @@ -1,5 +1,6 @@ package fr.free.nrw.commons +import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.mwapi.MediaResult import fr.free.nrw.commons.mwapi.MediaWikiApi import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient @@ -25,6 +26,9 @@ class MediaDataExtractorTest { @Mock internal var okHttpJsonApiClient: OkHttpJsonApiClient? = null + @Mock + internal var mediaClient: MediaClient? = null + @InjectMocks var mediaDataExtractor: MediaDataExtractor? = null @@ -45,7 +49,7 @@ class MediaDataExtractorTest { `when`(okHttpJsonApiClient?.getMedia(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())) .thenReturn(Single.just(mock(Media::class.java))) - `when`(mwApi?.pageExists(ArgumentMatchers.anyString())) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) .thenReturn(Single.just(true)) val mediaResult = mock(MediaResult::class.java) 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 new file mode 100644 index 000000000..0f5901bc6 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt @@ -0,0 +1,100 @@ +package fr.free.nrw.commons.media + +import io.reactivex.Observable +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.mockito.ArgumentMatchers +import org.mockito.InjectMocks +import org.mockito.Mock +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 + +class MediaClientTest { + + @Mock + internal var mediaInterface: MediaInterface? = null + + @InjectMocks + var mediaClient: MediaClient? = null + + @Before + @Throws(Exception::class) + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun checkPageExistsUsingTitle() { + val mwQueryPage = mock(MwQueryPage::class.java) + `when`(mwQueryPage.pageId()).thenReturn(10) + val mwQueryResult = mock(MwQueryResult::class.java) + `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) + `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) + val mockResponse = mock(MwQueryResponse::class.java) + `when`(mockResponse.query()).thenReturn(mwQueryResult) + + `when`(mediaInterface!!.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) + .thenReturn(Observable.just(mockResponse)) + + val checkPageExistsUsingTitle = mediaClient!!.checkPageExistsUsingTitle("File:Test.jpg").blockingGet() + assertTrue(checkPageExistsUsingTitle) + } + + @Test + fun checkPageNotExistsUsingTitle() { + val mwQueryPage = mock(MwQueryPage::class.java) + `when`(mwQueryPage.pageId()).thenReturn(0) + val mwQueryResult = mock(MwQueryResult::class.java) + `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) + `when`(mwQueryResult.pages()).thenReturn(listOf()) + val mockResponse = mock(MwQueryResponse::class.java) + `when`(mockResponse.query()).thenReturn(mwQueryResult) + + `when`(mediaInterface!!.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) + .thenReturn(Observable.just(mockResponse)) + + val checkPageExistsUsingTitle = mediaClient!!.checkPageExistsUsingTitle("File:Test.jpg").blockingGet() + assertFalse(checkPageExistsUsingTitle) + } + + @Test + fun checkFileExistsUsingSha() { + val mwQueryPage = mock(MwQueryPage::class.java) + val mwQueryResult = mock(MwQueryResult::class.java) + `when`(mwQueryResult.allImages()).thenReturn(listOf(mock(ImageDetails::class.java))) + `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) + `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) + val mockResponse = mock(MwQueryResponse::class.java) + `when`(mockResponse.query()).thenReturn(mwQueryResult) + + `when`(mediaInterface!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) + .thenReturn(Observable.just(mockResponse)) + + val checkFileExistsUsingSha = mediaClient!!.checkFileExistsUsingSha("abcde").blockingGet() + assertTrue(checkFileExistsUsingSha) + } + + @Test + fun checkFileNotExistsUsingSha() { + val mwQueryPage = mock(MwQueryPage::class.java) + val mwQueryResult = mock(MwQueryResult::class.java) + `when`(mwQueryResult.allImages()).thenReturn(listOf()) + `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) + `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) + val mockResponse = mock(MwQueryResponse::class.java) + `when`(mockResponse.query()).thenReturn(mwQueryResult) + + `when`(mediaInterface!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) + .thenReturn(Observable.just(mockResponse)) + + val checkFileExistsUsingSha = mediaClient!!.checkFileExistsUsingSha("abcde").blockingGet() + assertFalse(checkFileExistsUsingSha) + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt index 907b07c74..02f4b40ee 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -221,24 +221,6 @@ class ApacheHttpClientMediaWikiApiTest { assertEquals("baz", result) } - @Test - fun fileExistsWithName_FileNotFound() { - server.enqueue(MockResponse().setBody(" ")) - - val result = testObject.fileExistsWithName("foo") - - assertBasicRequestParameters(server, "GET").let { request -> - parseQueryParams(request).let { params -> - assertEquals("xml", params["format"]) - assertEquals("query", params["action"]) - assertEquals("imageinfo", params["prop"]) - assertEquals("File:foo", params["titles"]) - } - } - - assertFalse(result) - } - @Test fun isUserBlockedFromCommonsForInfinitelyBlockedUser() { server.enqueue(MockResponse().setBody("")) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/review/ReviewHelperTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/review/ReviewHelperTest.kt index ebd5d4baf..2fcce9347 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/review/ReviewHelperTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/review/ReviewHelperTest.kt @@ -1,6 +1,7 @@ package fr.free.nrw.commons.review import fr.free.nrw.commons.Media +import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.mwapi.MediaWikiApi import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient import io.reactivex.Observable @@ -31,6 +32,8 @@ class ReviewHelperTest { internal var okHttpJsonApiClient: OkHttpJsonApiClient? = null @Mock internal var mediaWikiApi: MediaWikiApi? = null + @Mock + internal var mediaClient: MediaClient? = null @InjectMocks var reviewHelper: ReviewHelper? = null @@ -74,7 +77,7 @@ class ReviewHelperTest { */ @Test fun getRandomMedia() { - `when`(mediaWikiApi?.pageExists(ArgumentMatchers.anyString())) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) .thenReturn(Single.just(false)) val randomMedia = reviewHelper?.randomMedia?.blockingGet() @@ -89,7 +92,7 @@ class ReviewHelperTest { */ @Test(expected = RuntimeException::class) fun getRandomMediaWithWithAllMediaNominatedForDeletion() { - `when`(mediaWikiApi?.pageExists(ArgumentMatchers.anyString())) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) .thenReturn(Single.just(true)) val media = reviewHelper?.randomMedia?.blockingGet() assertNull(media) @@ -101,11 +104,11 @@ class ReviewHelperTest { */ @Test fun getRandomMediaWithWithOneMediaNominatedForDeletion() { - `when`(mediaWikiApi?.pageExists("Commons:Deletion_requests/File:Test1.jpeg")) + `when`(mediaClient?.checkPageExistsUsingTitle("Commons:Deletion_requests/File:Test1.jpeg")) .thenReturn(Single.just(true)) - `when`(mediaWikiApi?.pageExists("Commons:Deletion_requests/File:Test2.png")) + `when`(mediaClient?.checkPageExistsUsingTitle("Commons:Deletion_requests/File:Test2.png")) .thenReturn(Single.just(false)) - `when`(mediaWikiApi?.pageExists("Commons:Deletion_requests/File:Test3.jpg")) + `when`(mediaClient?.checkPageExistsUsingTitle("Commons:Deletion_requests/File:Test3.jpg")) .thenReturn(Single.just(true)) val media = reviewHelper?.randomMedia?.blockingGet() diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt index 93cda48c2..a7cfdba88 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt @@ -2,6 +2,7 @@ package fr.free.nrw.commons.upload import android.net.Uri import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.mwapi.MediaWikiApi import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.utils.ImageUtils @@ -28,6 +29,8 @@ class u { internal var readFBMD: ReadFBMD?=null @Mock internal var readEXIF: EXIFReader?=null + @Mock + internal var mediaClient: MediaClient? = null @InjectMocks var imageProcessingService: ImageProcessingService? = null @@ -55,6 +58,7 @@ class u { `when`(uploadItem.title).thenReturn(mockTitle) `when`(uploadItem.place).thenReturn(mockPlace) + `when`(uploadItem.fileName).thenReturn("File:jpg") `when`(fileUtilsWrapper!!.getFileInputStream(ArgumentMatchers.anyString())) .thenReturn(mock(FileInputStream::class.java)) @@ -74,10 +78,10 @@ class u { .thenReturn(mock(FileInputStream::class.java)) `when`(fileUtilsWrapper!!.getSHA1(any(FileInputStream::class.java))) .thenReturn("fileSha") - `when`(mwApi!!.existingFile(ArgumentMatchers.anyString())) - .thenReturn(false) - `when`(mwApi!!.fileExistsWithName(ArgumentMatchers.anyString())) - .thenReturn(false) + `when`(mediaClient!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) + .thenReturn(Single.just(false)) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) + .thenReturn(Single.just(false)) `when`(readFBMD?.processMetadata(ArgumentMatchers.any(),ArgumentMatchers.any())) .thenReturn(Single.just(ImageUtils.IMAGE_OK)) `when`(readEXIF?.processMetadata(ArgumentMatchers.anyString())) @@ -93,8 +97,8 @@ class u { @Test fun validateImageForDuplicateImage() { - `when`(mwApi!!.existingFile(ArgumentMatchers.anyString())) - .thenReturn(true) + `when`(mediaClient!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) + .thenReturn(Single.just(true)) val validateImage = imageProcessingService!!.validateImage(uploadItem, false) assertEquals(ImageUtils.IMAGE_DUPLICATE, validateImage.blockingGet()) } @@ -123,16 +127,16 @@ class u { @Test fun validateImageForFileNameExistsWithCheckTitleOff() { - `when`(mwApi!!.fileExistsWithName(ArgumentMatchers.anyString())) - .thenReturn(true) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) + .thenReturn(Single.just(true)) val validateImage = imageProcessingService!!.validateImage(uploadItem, false) assertEquals(ImageUtils.IMAGE_OK, validateImage.blockingGet()) } @Test fun validateImageForFileNameExistsWithCheckTitleOn() { - `when`(mwApi!!.fileExistsWithName(ArgumentMatchers.nullable(String::class.java))) - .thenReturn(true) + `when`(mediaClient?.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) + .thenReturn(Single.just(true)) val validateImage = imageProcessingService!!.validateImage(uploadItem, true) assertEquals(ImageUtils.FILE_NAME_EXISTS, validateImage.blockingGet()) }