From 891d9ec41ce6b799fa6bc001c48da40074b09e9a Mon Sep 17 00:00:00 2001 From: Vivek Maskara Date: Sat, 23 Nov 2019 15:26:18 +0530 Subject: [PATCH] With wikidata changes (#3199) --- app/build.gradle | 2 +- .../free/nrw/commons/CommonsApplication.java | 41 +++++----- .../nrw/commons/OkHttpConnectionFactory.java | 3 +- .../ContributionsListFragment.java | 3 - .../free/nrw/commons/di/NetworkingModule.java | 25 ++---- .../free/nrw/commons/upload/UploadModel.java | 22 +++--- .../nrw/commons/upload/UploadService.java | 1 - .../nrw/commons/wikidata/WikidataClient.java | 76 +++++++++++++------ .../commons/wikidata/WikidataEditService.java | 18 ++--- .../commons/wikidata/WikidataInterface.java | 54 +++++++++++++ .../wikidata/model/AddEditTagResponse.java | 25 ++++++ .../nrw/commons/wikidata/model/EditTag.java | 56 ++++++++++++++ .../nrw/commons/wikidata/model/PageInfo.java | 21 +++++ .../wikidata/model/WbCreateClaimResponse.java | 30 ++++++++ .../wikidata/WikidataEditServiceTest.kt | 67 ++++++++++++++++ 15 files changed, 360 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java create mode 100644 app/src/main/java/fr/free/nrw/commons/wikidata/model/AddEditTagResponse.java create mode 100644 app/src/main/java/fr/free/nrw/commons/wikidata/model/EditTag.java create mode 100644 app/src/main/java/fr/free/nrw/commons/wikidata/model/PageInfo.java create mode 100644 app/src/main/java/fr/free/nrw/commons/wikidata/model/WbCreateClaimResponse.java create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt diff --git a/app/build.gradle b/app/build.gradle index a3618b7d8..374aefc49 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -222,7 +222,7 @@ android { buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\"" buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\"" buildConfigField "String", "COMMONS_URL", "\"https://commons.wikimedia.beta.wmflabs.org\"" - buildConfigField "String", "WIKIDATA_URL", "\"https://wikidata.org\"" + buildConfigField "String", "WIKIDATA_URL", "\"https:/www./wikidata.org\"" buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\"" buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\"" buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Main_Page&welcome=yes\"" diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index 06e2e2401..3c9398bab 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -1,12 +1,5 @@ package fr.free.nrw.commons; -import static org.acra.ReportField.ANDROID_VERSION; -import static org.acra.ReportField.APP_VERSION_CODE; -import static org.acra.ReportField.APP_VERSION_NAME; -import static org.acra.ReportField.PHONE_MODEL; -import static org.acra.ReportField.STACK_TRACE; -import static org.acra.ReportField.USER_COMMENT; - import android.annotation.SuppressLint; import android.app.Application; import android.app.NotificationChannel; @@ -16,12 +9,28 @@ import android.database.sqlite.SQLiteDatabase; import android.os.Build; import android.os.Process; import android.util.Log; + import androidx.annotation.NonNull; + import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.core.ImagePipeline; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; + +import org.acra.ACRA; +import org.acra.annotation.AcraCore; +import org.acra.annotation.AcraDialog; +import org.acra.annotation.AcraMailSender; +import org.acra.data.StringFormat; +import org.wikipedia.AppAdapter; +import org.wikipedia.language.AppLanguageLookUpTable; + +import java.io.File; + +import javax.inject.Inject; +import javax.inject.Named; + import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao; @@ -40,18 +49,15 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.internal.functions.Functions; import io.reactivex.plugins.RxJavaPlugins; import io.reactivex.schedulers.Schedulers; -import java.io.File; -import javax.inject.Inject; -import javax.inject.Named; -import org.acra.ACRA; -import org.acra.annotation.AcraCore; -import org.acra.annotation.AcraDialog; -import org.acra.annotation.AcraMailSender; -import org.acra.data.StringFormat; -import org.wikipedia.AppAdapter; -import org.wikipedia.language.AppLanguageLookUpTable; import timber.log.Timber; +import static org.acra.ReportField.ANDROID_VERSION; +import static org.acra.ReportField.APP_VERSION_CODE; +import static org.acra.ReportField.APP_VERSION_NAME; +import static org.acra.ReportField.PHONE_MODEL; +import static org.acra.ReportField.STACK_TRACE; +import static org.acra.ReportField.USER_COMMENT; + @AcraCore( buildConfigClass = BuildConfig.class, resReportSendSuccessToast = R.string.crash_dialog_ok_toast, @@ -114,6 +120,7 @@ public class CommonsApplication extends Application { @Override public void onCreate() { super.onCreate(); + INSTANCE = this; ACRA.init(this); 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 59ece06cb..6fe317c0a 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -1,12 +1,13 @@ package fr.free.nrw.commons; +import androidx.annotation.NonNull; + import org.wikipedia.dataclient.SharedPreferenceCookieManager; import org.wikipedia.dataclient.okhttp.HttpStatusException; import java.io.File; import java.io.IOException; -import androidx.annotation.NonNull; import okhttp3.Cache; import okhttp3.Interceptor; import okhttp3.OkHttpClient; diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 455e365d4..de564196f 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -29,7 +29,6 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.contributions.ContributionsListAdapter.Callback; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.wikidata.WikidataClient; import static android.view.View.GONE; import static android.view.View.VISIBLE; @@ -58,8 +57,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment { @Inject @Named("default_preferences") JsonKvStore kvStore; @Inject ContributionController controller; - @Inject - WikidataClient wikidataClient; private Animation fab_close; private Animation fab_open; 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 be2d7b5b7..c6e6033f5 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 @@ -31,6 +31,7 @@ import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient; import fr.free.nrw.commons.mwapi.UserInterface; import fr.free.nrw.commons.review.ReviewInterface; import fr.free.nrw.commons.upload.UploadInterface; +import fr.free.nrw.commons.wikidata.WikidataInterface; import okhttp3.Cache; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; @@ -51,7 +52,6 @@ public class NetworkingModule { private static final String NAMED_WIKI_DATA_WIKI_SITE = "wikidata-wikisite"; public static final String NAMED_COMMONS_CSRF = "commons-csrf"; - public static final String NAMED_WIKI_DATA_CSRF = "wikidata-csrf"; @Provides @Singleton @@ -97,14 +97,6 @@ public class NetworkingModule { return new CsrfTokenClient(commonsWikiSite, commonsWikiSite); } - @Named(NAMED_WIKI_DATA_CSRF) - @Provides - @Singleton - public CsrfTokenClient provideWikidataCsrfTokenClient(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite, - @Named(NAMED_WIKI_DATA_WIKI_SITE) WikiSite wikidataWikiSite) { - return new CsrfTokenClient(wikidataWikiSite, commonsWikiSite); - } - @Provides @Singleton public LoginClient provideLoginClient() { @@ -200,15 +192,6 @@ public class NetworkingModule { return new PageEditClient(csrfTokenClient, pageEditInterface, service); } - @Named("wikidata-page-edit") - @Provides - @Singleton - public PageEditClient provideWikidataPageEditClient(@Named(NAMED_WIKI_DATA_CSRF) CsrfTokenClient csrfTokenClient, - @Named("wikidata-page-edit-service") PageEditInterface pageEditInterface, - @Named("wikidata-service") Service service) { - return new PageEditClient(csrfTokenClient, pageEditInterface, service); - } - @Provides @Singleton public MediaInterface provideMediaInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) { @@ -226,4 +209,10 @@ public class NetworkingModule { public UserInterface provideUserInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) { return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, UserInterface.class); } + + @Provides + @Singleton + public WikidataInterface provideWikidataInterface(@Named(NAMED_WIKI_DATA_WIKI_SITE) WikiSite wikiDataWikiSite) { + return ServiceFactory.get(wikiDataWikiSite, BuildConfig.WIKIDATA_URL, WikidataInterface.class); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java index 1ca5c2be0..e9b0b0629 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java @@ -3,7 +3,20 @@ package fr.free.nrw.commons.upload; import android.annotation.SuppressLint; import android.content.Context; import android.net.Uri; + import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.auth.SessionManager; @@ -18,15 +31,6 @@ import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.subjects.BehaviorSubject; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; import timber.log.Timber; @Singleton 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 266bfa2bb..a7fbb0d22 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 @@ -87,7 +87,6 @@ public class UploadService extends HandlerService { } public void onProgress(long transferred, long total) { - Timber.d("Uploaded %d of %d", transferred, total); if (!notificationTitleChanged) { curNotification.setContentTitle(notificationProgressTitle); notificationTitleChanged = true; diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java index 74c05564c..542eb58ed 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataClient.java @@ -1,40 +1,70 @@ package fr.free.nrw.commons.wikidata; -import org.wikipedia.csrf.CsrfTokenClient; -import org.wikipedia.dataclient.Service; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Singleton; +import fr.free.nrw.commons.wikidata.model.AddEditTagResponse; import io.reactivex.Observable; - -import static fr.free.nrw.commons.di.NetworkingModule.NAMED_WIKI_DATA_CSRF; +import io.reactivex.ObservableSource; +import okhttp3.MediaType; +import okhttp3.RequestBody; @Singleton public class WikidataClient { - private final Service service; - private final CsrfTokenClient csrfTokenClient; + + private final WikidataInterface wikidataInterface; @Inject - public WikidataClient(@Named("wikidata-service") Service service, - @Named(NAMED_WIKI_DATA_CSRF) CsrfTokenClient csrfTokenClient) { - this.service = service; - this.csrfTokenClient = csrfTokenClient; + public WikidataClient(WikidataInterface wikidataInterface) { + this.wikidataInterface = wikidataInterface; } - public Observable createClaim(String entityId, String property, String snaktype, String value) { - try { - return service.postCreateClaim(entityId, snaktype, property, value, "en", csrfTokenClient.getTokenBlocking()) - .map(mwPostResponse -> { - if (mwPostResponse.getSuccessVal() == 1) { - return 1L; - } - return -1L; - }); - } catch (Throwable throwable) { - return Observable.just(-1L); - } + /** + * Create wikidata claim to add P18 value + * @param entityId wikidata entity ID + * @param value value of the P18 edit + * @return revisionID of the edit + */ + Observable createClaim(String entityId, String value) { + return getCsrfToken() + .flatMap(csrfToken -> wikidataInterface.postCreateClaim(toRequestBody(entityId), + toRequestBody("value"), + toRequestBody("P18"), + toRequestBody(value), + toRequestBody("en"), + toRequestBody(csrfToken))) + .map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid()); + } + + /** + * Converts string value to RequestBody for multipart request + */ + private RequestBody toRequestBody(String value) { + return RequestBody.create(MediaType.parse("text/plain"), value); + } + + /** + * Get csrf token for wikidata edit + */ + @NotNull + private Observable getCsrfToken() { + return wikidataInterface.getCsrfToken().map(mwQueryResponse -> mwQueryResponse.query().csrfToken()); + } + + /** + * Add edit tag for a given revision ID. The app currently uses this to tag P18 edits + * @param revisionId revision ID of the page edited + * @param tag to be added + * @param reason to be mentioned + */ + ObservableSource addEditTag(Long revisionId, String tag, String reason) { + return getCsrfToken() + .flatMap(csrfToken -> wikidataInterface.addEditTag(String.valueOf(revisionId), + tag, + reason, + csrfToken)); } } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java index 1c6b17317..e486d1150 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java @@ -10,7 +10,6 @@ import javax.inject.Named; import javax.inject.Singleton; import fr.free.nrw.commons.R; -import fr.free.nrw.commons.actions.PageEditClient; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -32,19 +31,16 @@ public class WikidataEditService { private final WikidataEditListener wikidataEditListener; private final JsonKvStore directKvStore; private final WikidataClient wikidataClient; - private final PageEditClient wikiDataPageEditClient; @Inject - public WikidataEditService(Context context, - WikidataEditListener wikidataEditListener, - @Named("default_preferences") JsonKvStore directKvStore, - WikidataClient wikidataClient, - @Named("wikidata-page-edit") PageEditClient wikiDataPageEditClient) { + WikidataEditService(Context context, + WikidataEditListener wikidataEditListener, + @Named("default_preferences") JsonKvStore directKvStore, + WikidataClient wikidataClient) { this.context = context; this.wikidataEditListener = wikidataEditListener; this.directKvStore = directKvStore; this.wikidataClient = wikidataClient; - this.wikiDataPageEditClient = wikiDataPageEditClient; } /** @@ -85,11 +81,11 @@ public class WikidataEditService { String propertyValue = getFileName(fileName); - Timber.d(propertyValue); - wikidataClient.createClaim(wikidataEntityId, "P18", "value", propertyValue) + Timber.d("Entity id is %s and property value is %s", wikidataEntityId, propertyValue); + wikidataClient.createClaim(wikidataEntityId, propertyValue) .flatMap(revisionId -> { if (revisionId != -1) { - return wikiDataPageEditClient.addEditTag(revisionId, COMMONS_APP_TAG, COMMONS_APP_EDIT_REASON); + return wikidataClient.addEditTag(revisionId, COMMONS_APP_TAG, COMMONS_APP_EDIT_REASON); } throw new RuntimeException("Unable to edit wikidata item"); }) diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java new file mode 100644 index 000000000..25d5f43ea --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataInterface.java @@ -0,0 +1,54 @@ +package fr.free.nrw.commons.wikidata; + +import androidx.annotation.NonNull; + +import org.wikipedia.dataclient.mwapi.MwQueryResponse; + +import fr.free.nrw.commons.wikidata.model.AddEditTagResponse; +import fr.free.nrw.commons.wikidata.model.WbCreateClaimResponse; +import io.reactivex.Observable; +import okhttp3.RequestBody; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Multipart; +import retrofit2.http.POST; +import retrofit2.http.Part; + +import static org.wikipedia.dataclient.Service.MW_API_PREFIX; + +public interface WikidataInterface { + + /** + * Wikidata create claim API. Posts a new claim for the given entity ID + */ + @Headers("Cache-Control: no-cache") + @POST("w/api.php?format=json&errorformat=plaintext&action=wbcreateclaim&errorlang=uselang") + @Multipart + Observable postCreateClaim(@NonNull @Part("entity") RequestBody entity, + @NonNull @Part("snaktype") RequestBody snakType, + @NonNull @Part("property") RequestBody property, + @NonNull @Part("value") RequestBody value, + @NonNull @Part("uselang") RequestBody useLang, + @NonNull @Part("token") RequestBody token); + + /** + * Add edit tag and reason for any revision + */ + @Headers("Cache-Control: no-cache") + @POST(MW_API_PREFIX + "action=tag") + @FormUrlEncoded + Observable addEditTag(@NonNull @Field("revid") String revId, + @NonNull @Field("add") String tagName, + @NonNull @Field("reason") String reason, + @NonNull @Field("token") String token); + + /** + * Get edit token for wikidata wiki site + */ + @Headers("Cache-Control: no-cache") + @GET(MW_API_PREFIX + "action=query&meta=tokens&type=csrf") + @NonNull + Observable getCsrfToken(); +} diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/model/AddEditTagResponse.java b/app/src/main/java/fr/free/nrw/commons/wikidata/model/AddEditTagResponse.java new file mode 100644 index 000000000..74a538b4b --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/model/AddEditTagResponse.java @@ -0,0 +1,25 @@ +package fr.free.nrw.commons.wikidata.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +/** + * Response class for add edit tag + */ +public class AddEditTagResponse { + + @SerializedName("tag") + @Expose + private List tag = null; + + public List getTag() { + return tag; + } + + public void setTag(List tag) { + this.tag = tag; + } + +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/model/EditTag.java b/app/src/main/java/fr/free/nrw/commons/wikidata/model/EditTag.java new file mode 100644 index 000000000..aa5ca3071 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/model/EditTag.java @@ -0,0 +1,56 @@ +package fr.free.nrw.commons.wikidata.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +/** + * Tag class used when adding wikidata edit tag + */ +public class EditTag { + + @SerializedName("revid") + @Expose + private Integer revid; + @SerializedName("status") + @Expose + private String status; + @SerializedName("actionlogid") + @Expose + private Integer actionlogid; + @SerializedName("added") + @Expose + private List added; + @SerializedName("removed") + @Expose + private List removed; + + public EditTag(Integer revid, String status, Integer actionlogid, List added, List removed) { + this.revid = revid; + this.status = status; + this.actionlogid = actionlogid; + this.added = added; + this.removed = removed; + } + + public Integer getRevid() { + return revid; + } + + public String getStatus() { + return status; + } + + public Integer getActionlogid() { + return actionlogid; + } + + public List getAdded() { + return added; + } + + public List getRemoved() { + return removed; + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/model/PageInfo.java b/app/src/main/java/fr/free/nrw/commons/wikidata/model/PageInfo.java new file mode 100644 index 000000000..75b3ea82f --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/model/PageInfo.java @@ -0,0 +1,21 @@ +package fr.free.nrw.commons.wikidata.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * PageInfo model class with last revision id of the edited Wikidata entity + */ +public class PageInfo { + @SerializedName("lastrevid") + @Expose + private Long lastrevid; + + public PageInfo(Long lastrevid) { + this.lastrevid = lastrevid; + } + + public Long getLastrevid() { + return lastrevid; + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/model/WbCreateClaimResponse.java b/app/src/main/java/fr/free/nrw/commons/wikidata/model/WbCreateClaimResponse.java new file mode 100644 index 000000000..cc4a39c0b --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/model/WbCreateClaimResponse.java @@ -0,0 +1,30 @@ +package fr.free.nrw.commons.wikidata.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * Wikidata create claim response model class + */ +public class WbCreateClaimResponse { + + @SerializedName("pageinfo") + @Expose + private PageInfo pageinfo; + @SerializedName("success") + @Expose + private Integer success; + + public WbCreateClaimResponse(PageInfo pageinfo, Integer success) { + this.pageinfo = pageinfo; + this.success = success; + } + + public PageInfo getPageinfo() { + return pageinfo; + } + + public Integer getSuccess() { + return success; + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt new file mode 100644 index 000000000..4d5a41159 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/wikidata/WikidataEditServiceTest.kt @@ -0,0 +1,67 @@ +package fr.free.nrw.commons.wikidata + +import android.content.Context +import com.nhaarman.mockito_kotlin.verifyZeroInteractions +import fr.free.nrw.commons.kvstore.JsonKvStore +import fr.free.nrw.commons.wikidata.model.AddEditTagResponse +import io.reactivex.Observable +import org.junit.Before +import org.junit.Test +import org.mockito.ArgumentMatchers +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.MockitoAnnotations + +class WikidataEditServiceTest { + @Mock + internal var context: Context? = null + @Mock + internal var wikidataEditListener: WikidataEditListener? = null + @Mock + internal var directKvStore: JsonKvStore? = null + @Mock + internal var wikidataClient: WikidataClient? = null + + @InjectMocks + var wikidataEditService: WikidataEditService? = null + + @Before + @Throws(Exception::class) + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun noClaimsWhenEntityIdIsNull() { + wikidataEditService!!.createClaimWithLogging(null, "Test.jpg") + verifyZeroInteractions(wikidataClient!!) + } + + @Test + fun noClaimsWhenFileNameIsNull() { + wikidataEditService!!.createClaimWithLogging("Q1", null) + verifyZeroInteractions(wikidataClient!!) + } + + @Test + fun noClaimsWhenLocationIsNotCorrect() { + `when`(directKvStore!!.getBoolean("Picture_Has_Correct_Location", true)) + .thenReturn(false) + wikidataEditService!!.createClaimWithLogging("Q1", "Test.jpg") + verifyZeroInteractions(wikidataClient!!) + } + + @Test + fun createClaimWithLogging() { + `when`(directKvStore!!.getBoolean("Picture_Has_Correct_Location", true)) + .thenReturn(true) + `when`(wikidataClient!!.createClaim(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())) + .thenReturn(Observable.just(1L)) + `when`(wikidataClient!!.addEditTag(anyLong(), ArgumentMatchers.anyString(), ArgumentMatchers.anyString())) + .thenReturn(Observable.just(mock(AddEditTagResponse::class.java))) + wikidataEditService!!.createClaimWithLogging("Q1", "Test.jpg") + verify(wikidataClient!!, times(1)) + .createClaim(ArgumentMatchers.anyString(), ArgumentMatchers.anyString()) + } +} \ No newline at end of file