With data-client added as library module (#3656)

* With data-client added as library module

* Fix build
This commit is contained in:
Vivek Maskara 2020-04-15 03:00:13 -07:00 committed by GitHub
parent 9ee04f3df4
commit 32ee0b4f9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
258 changed files with 34820 additions and 2 deletions

View file

@ -0,0 +1,71 @@
package org.wikipedia;
import androidx.annotation.NonNull;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.SharedPreferenceCookieManager;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.okhttp.TestStubInterceptor;
import org.wikipedia.dataclient.okhttp.UnsuccessfulResponseInterceptor;
import org.wikipedia.login.LoginResult;
import okhttp3.OkHttpClient;
public class TestAppAdapter extends AppAdapter {
@Override
public String getMediaWikiBaseUrl() {
return Service.WIKIPEDIA_URL;
}
@Override
public String getRestbaseUriFormat() {
return "%1$s://%2$s/api/rest_v1/";
}
@Override
public OkHttpClient getOkHttpClient(@NonNull WikiSite wikiSite) {
return new OkHttpClient.Builder()
.addInterceptor(new UnsuccessfulResponseInterceptor())
.addInterceptor(new TestStubInterceptor())
.build();
}
@Override
public int getDesiredLeadImageDp() {
return 0;
}
@Override
public boolean isLoggedIn() {
return false;
}
@Override
public String getUserName() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public void updateAccount(@NonNull LoginResult result) {
}
@Override
public SharedPreferenceCookieManager getCookies() {
return null;
}
@Override
public void setCookies(@NonNull SharedPreferenceCookieManager cookies) {
}
@Override
public boolean logErrorsInsteadOfCrashing() {
return false;
}
}

View file

@ -0,0 +1,10 @@
package org.wikipedia;
import java.util.concurrent.TimeUnit;
public final class TestConstants {
public static final int TIMEOUT_DURATION = 5;
public static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS;
private TestConstants() { }
}

View file

@ -0,0 +1,35 @@
package org.wikipedia;
import java.util.concurrent.CountDownLatch;
public class TestLatch {
private final CountDownLatch latch;
public TestLatch() {
this(1);
}
public TestLatch(int count) {
latch = new CountDownLatch(count);
}
public long getCount() {
return latch.getCount();
}
public void countDown() {
latch.countDown();
}
public void await() {
boolean done = false;
try {
done = latch.await(TestConstants.TIMEOUT_DURATION, TestConstants.TIMEOUT_UNIT);
} catch (InterruptedException ignore) { }
if (!done) {
throw new RuntimeException("Timeout elapsed.");
}
}
}

View file

@ -0,0 +1,54 @@
package org.wikipedia.captcha;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class CaptchaClientTest extends MockRetrofitTest {
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("captcha.json");
TestObserver<CaptchaResult> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getCaptchaId().equals("1572672319"));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<CaptchaResult> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<CaptchaResult> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<CaptchaResult> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<CaptchaResult> getObservable() {
return getApiService().getNewCaptcha()
.map(response -> new CaptchaResult(response.captchaId()));
}
}

View file

@ -0,0 +1,53 @@
package org.wikipedia.createaccount;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.mwapi.CreateAccountResponse;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class CreateAccountClientTest extends MockRetrofitTest {
private Observable<CreateAccountResponse> getObservable() {
return getApiService().postCreateAccount("user", "pass", "pass", "token", Service.WIKIPEDIA_URL, null, null, null);
}
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("create_account_success.json");
TestObserver<CreateAccountResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.status().equals("PASS")
&& result.user().equals("Farb0nucci"));
}
@Test public void testRequestFailure() throws Throwable {
enqueueFromFile("create_account_failure.json");
TestObserver<CreateAccountResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.status().equals("FAIL"));
}
@Test public void testRequestResponse404() {
enqueue404();
TestObserver<CreateAccountResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<CreateAccountResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
}

View file

@ -0,0 +1,48 @@
package org.wikipedia.createaccount;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class CreateAccountInfoClientTest extends MockRetrofitTest {
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("create_account_info.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(response -> {
String token = response.query().createAccountToken();
String captchaId = response.query().captchaId();
return token.equals("5d78e6a823be0901eeae9f6486f752da59123760+\\")
&& captchaId.equals("272460457");
});
}
@Test public void testRequestResponse404() {
enqueue404();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<MwQueryResponse> getObservable() {
return getApiService().getAuthManagerInfo();
}
}

View file

@ -0,0 +1,87 @@
package org.wikipedia.csrf;
import androidx.annotation.NonNull;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.csrf.CsrfTokenClient.Callback;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.dataclient.okhttp.HttpStatusException;
import org.wikipedia.test.MockWebServerTest;
import retrofit2.Call;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class CsrfTokenClientTest extends MockWebServerTest {
private static final WikiSite TEST_WIKI = new WikiSite("test.wikipedia.org");
@NonNull private final CsrfTokenClient subject = new CsrfTokenClient(TEST_WIKI, TEST_WIKI);
@Test public void testRequestSuccess() throws Throwable {
String expected = "b6f7bd58c013ab30735cb19ecc0aa08258122cba+\\";
enqueueFromFile("csrf_token.json");
Callback cb = mock(Callback.class);
request(cb);
server().takeRequest();
assertCallbackSuccess(cb, expected);
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
Callback cb = mock(Callback.class);
request(cb);
server().takeRequest();
assertCallbackFailure(cb, MwException.class);
}
@Test public void testRequestResponseFailure() throws Throwable {
enqueue404();
Callback cb = mock(Callback.class);
request(cb);
server().takeRequest();
assertCallbackFailure(cb, HttpStatusException.class);
}
@Test public void testRequestResponseMalformed() throws Throwable {
enqueueMalformed();
Callback cb = mock(Callback.class);
request(cb);
server().takeRequest();
assertCallbackFailure(cb, MalformedJsonException.class);
}
private void assertCallbackSuccess(@NonNull Callback cb,
@NonNull String expected) {
verify(cb).success(eq(expected));
//noinspection unchecked
verify(cb, never()).failure(any(Throwable.class));
}
private void assertCallbackFailure(@NonNull Callback cb,
@NonNull Class<? extends Throwable> throwable) {
//noinspection unchecked
verify(cb, never()).success(any(String.class));
verify(cb).failure(isA(throwable));
}
private Call<MwQueryResponse> request(@NonNull Callback cb) {
return subject.request(service(Service.class), cb);
}
}

View file

@ -0,0 +1,228 @@
package org.wikipedia.dataclient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.json.GsonMarshaller;
import org.wikipedia.json.GsonUnmarshaller;
import org.wikipedia.page.PageTitle;
import org.wikipedia.test.TestParcelUtil;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
@RunWith(RobolectricTestRunner.class) public class WikiSiteTest {
@Test public void testSupportedAuthority() {
assertThat(WikiSite.supportedAuthority("fr.wikipedia.org"), is(true));
assertThat(WikiSite.supportedAuthority("fr.m.wikipedia.org"), is(true));
assertThat(WikiSite.supportedAuthority("roa-rup.wikipedia.org"), is(true));
assertThat(WikiSite.supportedAuthority("google.com"), is(false));
}
@Test public void testForLanguageCodeScheme() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.scheme(), is("https"));
}
@Test public void testForLanguageCodeAuthority() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.authority(), is("test.wikipedia.org"));
}
@Test public void testForLanguageCodeLanguage() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.languageCode(), is("test"));
}
@Test public void testForLanguageCodeNoLanguage() {
WikiSite subject = WikiSite.forLanguageCode("");
assertThat(subject.languageCode(), is(""));
}
@Test public void testForLanguageCodeNoLanguageAuthority() {
WikiSite subject = WikiSite.forLanguageCode("");
assertThat(subject.authority(), is("wikipedia.org"));
}
@Test public void testForLanguageCodeLanguageAuthority() {
WikiSite subject = WikiSite.forLanguageCode("zh-hans");
assertThat(subject.authority(), is("zh.wikipedia.org"));
assertThat(subject.languageCode(), is("zh-hans"));
}
@Test public void testCtorScheme() {
WikiSite subject = new WikiSite("http://wikipedia.org");
assertThat(subject.scheme(), is("http"));
}
@Test public void testCtorDefaultScheme() {
WikiSite subject = new WikiSite("wikipedia.org");
assertThat(subject.scheme(), is("https"));
}
@Test public void testCtorAuthority() {
WikiSite subject = new WikiSite("test.wikipedia.org");
assertThat(subject.authority(), is("test.wikipedia.org"));
}
@Test public void testCtorAuthorityLanguage() {
WikiSite subject = new WikiSite("test.wikipedia.org");
assertThat(subject.languageCode(), is("test"));
}
@Test public void testCtorAuthorityNoLanguage() {
WikiSite subject = new WikiSite("wikipedia.org");
assertThat(subject.languageCode(), is(""));
}
@Test public void testCtorMobileAuthorityLanguage() {
WikiSite subject = new WikiSite("test.m.wikipedia.org");
assertThat(subject.languageCode(), is("test"));
}
@Test public void testCtorMobileAuthorityNoLanguage() {
WikiSite subject = new WikiSite("m.wikipedia.org");
assertThat(subject.languageCode(), is(""));
}
@Test public void testCtorUriLangVariant() {
WikiSite subject = new WikiSite("zh.wikipedia.org/zh-hant/Foo");
assertThat(subject.authority(), is("zh.wikipedia.org"));
assertThat(subject.mobileAuthority(), is("zh.m.wikipedia.org"));
assertThat(subject.subdomain(), is("zh"));
assertThat(subject.languageCode(), is("zh-hant"));
assertThat(subject.scheme(), is("https"));
assertThat(subject.dbName(), is("zhwiki"));
assertThat(subject.url(), is("https://zh.wikipedia.org"));
}
@Test public void testCtorMobileUriLangVariant() {
WikiSite subject = new WikiSite("zh.m.wikipedia.org/zh-hant/Foo");
assertThat(subject.authority(), is("zh.m.wikipedia.org"));
assertThat(subject.mobileAuthority(), is("zh.m.wikipedia.org"));
assertThat(subject.subdomain(), is("zh"));
assertThat(subject.languageCode(), is("zh-hant"));
assertThat(subject.scheme(), is("https"));
assertThat(subject.url(), is("https://zh.m.wikipedia.org"));
}
@Test public void testCtorUriNoLangVariant() {
WikiSite subject = new WikiSite("http://zh.wikipedia.org/wiki/Foo");
assertThat(subject.authority(), is("zh.wikipedia.org"));
assertThat(subject.mobileAuthority(), is("zh.m.wikipedia.org"));
assertThat(subject.subdomain(), is("zh"));
assertThat(subject.languageCode(), is("zh"));
assertThat(subject.scheme(), is("http"));
assertThat(subject.url(), is("http://zh.wikipedia.org"));
}
@Test public void testCtorParcel() throws Throwable {
WikiSite subject = WikiSite.forLanguageCode("test");
TestParcelUtil.test(subject);
}
@Test public void testAuthority() {
WikiSite subject = new WikiSite("test.wikipedia.org", "test");
assertThat(subject.authority(), is("test.wikipedia.org"));
}
@Test public void testMobileAuthorityLanguage() {
WikiSite subject = WikiSite.forLanguageCode("fiu-vro");
assertThat(subject.mobileAuthority(), is("fiu-vro.m.wikipedia.org"));
}
@Test public void testMobileAuthorityNoLanguage() {
WikiSite subject = new WikiSite("wikipedia.org");
assertThat(subject.mobileAuthority(), is("m.wikipedia.org"));
}
@Test public void testMobileAuthorityLanguageAuthority() {
WikiSite subject = new WikiSite("no.wikipedia.org", "nb");
assertThat(subject.mobileAuthority(), is("no.m.wikipedia.org"));
}
@Test public void testMobileAuthorityMobileAuthority() {
WikiSite subject = new WikiSite("ru.m.wikipedia.org");
assertThat(subject.mobileAuthority(), is("ru.m.wikipedia.org"));
}
@Test public void testMobileAuthorityMobileAuthorityNoLanguage() {
WikiSite subject = new WikiSite("m.wikipedia.org");
assertThat(subject.mobileAuthority(), is("m.wikipedia.org"));
}
@Test public void testDbNameLanguage() {
WikiSite subject = new WikiSite("en.wikipedia.org", "en");
assertThat(subject.dbName(), is("enwiki"));
}
@Test public void testDbNameSpecialLanguage() {
WikiSite subject = new WikiSite("no.wikipedia.org", "nb");
assertThat(subject.dbName(), is("nowiki"));
}
@Test public void testDbNameWithOneUnderscore() {
WikiSite subject = new WikiSite("zh-yue.wikipedia.org");
assertThat(subject.dbName(), is("zh_yuewiki"));
}
@Test public void testDbNameWithTwoUnderscore() {
WikiSite subject = new WikiSite("zh-min-nan.wikipedia.org");
assertThat(subject.dbName(), is("zh_min_nanwiki"));
}
@Test public void testPath() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.path("Segment"), is("/w/Segment"));
}
@Test public void testPathEmpty() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.path(""), is("/w/"));
}
@Test public void testUrl() {
WikiSite subject = new WikiSite("test.192.168.1.11:8080", "test");
assertThat(subject.url(), is("https://test.192.168.1.11:8080"));
}
@Test public void testUrlPath() {
WikiSite subject = WikiSite.forLanguageCode("test");
assertThat(subject.url("Segment"), is("https://test.wikipedia.org/w/Segment"));
}
@Test public void testLanguageCode() {
WikiSite subject = WikiSite.forLanguageCode("lang");
assertThat(subject.languageCode(), is("lang"));
}
@Test public void testUnmarshal() {
WikiSite wiki = WikiSite.forLanguageCode("test");
assertThat(GsonUnmarshaller.unmarshal(WikiSite.class, GsonMarshaller.marshal(wiki)), is(wiki));
}
@Test public void testUnmarshalScheme() {
WikiSite wiki = new WikiSite("wikipedia.org", "");
assertThat(GsonUnmarshaller.unmarshal(WikiSite.class, GsonMarshaller.marshal(wiki)), is(wiki));
}
@Test public void testTitleForInternalLink() {
WikiSite wiki = WikiSite.forLanguageCode("en");
assertThat(new PageTitle("wiki", wiki), is(wiki.titleForInternalLink("wiki")));
assertThat(new PageTitle("wiki", wiki), is(wiki.titleForInternalLink("/wiki/wiki")));
assertThat(new PageTitle("wiki/wiki", wiki), is(wiki.titleForInternalLink("/wiki/wiki/wiki")));
}
@Test public void testEquals() {
assertThat(WikiSite.forLanguageCode("en"), is(WikiSite.forLanguageCode("en")));
assertThat(WikiSite.forLanguageCode("ta"), not(WikiSite.forLanguageCode("en")));
assertThat(WikiSite.forLanguageCode("ta").equals("ta.wikipedia.org"), is(false));
}
@Test public void testNormalization() {
assertThat("bm.wikipedia.org", is(WikiSite.forLanguageCode("bm").authority()));
}
}

View file

@ -0,0 +1,75 @@
package org.wikipedia.dataclient.mwapi.page;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.page.BasePageLeadTest;
import org.wikipedia.dataclient.page.PageClient;
import io.reactivex.observers.TestObserver;
import okhttp3.CacheControl;
import retrofit2.Response;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
public class MwMobileViewPageLeadTest extends BasePageLeadTest {
private PageClient subject;
@Before public void setUp() throws Throwable {
super.setUp();
subject = new MwPageClient();
}
@Test public void testEnglishMainPage() {
MwMobileViewPageLead pageLead = unmarshal(MwMobileViewPageLead.class, wrapInMobileview(getEnglishMainPageJson()));
MwMobileViewPageLead.Mobileview props = pageLead.getMobileview();
verifyEnglishMainPage(props);
}
@Test public void testUnprotectedDisambiguationPage() {
MwMobileViewPageLead pageLead = unmarshal(MwMobileViewPageLead.class,
wrapInMobileview(getUnprotectedDisambiguationPageJson()));
MwMobileViewPageLead.Mobileview props = pageLead.getMobileview();
verifyUnprotectedDisambiguationPage(props);
}
/**
* Custom deserializer; um, yeah /o\.
* An earlier version had issues with protection settings that don't include "edit" protection.
*/
@Test public void testProtectedButNoEditProtectionPage() {
MwMobileViewPageLead pageLead = unmarshal(MwMobileViewPageLead.class,
wrapInMobileview(getProtectedButNoEditProtectionPageJson()));
MwMobileViewPageLead.Mobileview props = pageLead.getMobileview();
verifyProtectedNoEditProtectionPage(props);
}
@Test @SuppressWarnings("checkstyle:magicnumber") public void testThumbUrls() throws Throwable {
enqueueFromFile("page_lead_mw.json");
TestObserver<Response<MwMobileViewPageLead>> observer = new TestObserver<>();
getApiService().getLeadSection(CacheControl.FORCE_NETWORK.toString(), null, null, "foo", 640, "en").subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.body().getLeadImageUrl(640).contains("640px")
&& result.body().getThumbUrl().contains(preferredThumbSizeString())
&& result.body().getDescription().contains("Mexican boxer"));
}
@Test public void testError() {
try {
unmarshal(MwMobileViewPageLead.class, getErrorJson());
} catch (MwException e) {
verifyError(e);
}
}
@NonNull @Override protected PageClient subject() {
return subject;
}
private String wrapInMobileview(String json) {
return "{\"mobileview\":" + json + "}";
}
}

View file

@ -0,0 +1,34 @@
package org.wikipedia.dataclient.mwapi.page;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.wikipedia.dataclient.page.BasePageClientTest;
import org.wikipedia.dataclient.page.PageClient;
import org.wikipedia.dataclient.page.PageLead;
import io.reactivex.observers.TestObserver;
import retrofit2.Response;
public class MwPageClientTest extends BasePageClientTest {
private PageClient subject;
@Before public void setUp() throws Throwable {
super.setUp();
subject = new MwPageClient();
}
@Test public void testLeadThumbnailWidth() {
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject.lead(wikiSite(), null, null, null, "test", 10).subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().url().toString().contains("10"));
}
@NonNull @Override protected PageClient subject() {
return subject;
}
}

View file

@ -0,0 +1,56 @@
package org.wikipedia.dataclient.okhttp.util;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.WikiSite;
import okhttp3.HttpUrl;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@RunWith(RobolectricTestRunner.class) public class HttpUrlUtilTest {
@Test public void testIsRestBaseProd() {
HttpUrl url = HttpUrl.parse("https://test.wikipedia.org/api/rest_v1/");
assertThat(HttpUrlUtil.isRestBase(url), is(true));
}
@Test public void testIsRestBaseLabs() {
HttpUrl url = HttpUrl.parse("http://appservice.wmflabs.org/test.wikipedia.org/v1/");
assertThat(HttpUrlUtil.isRestBase(url), is(true));
}
@Test public void testIsRestBaseDev() {
HttpUrl url = HttpUrl.parse("http://host:6927/192.168.1.11:8080/v1/");
assertThat(HttpUrlUtil.isRestBase(url), is(true));
}
@Test public void testIsRestBaseMediaWikiTest() {
HttpUrl url = HttpUrl.parse(WikiSite.forLanguageCode("test").url());
assertThat(HttpUrlUtil.isRestBase(url), is(false));
}
@Test public void testIsRestBaseMediaWikiDev() {
HttpUrl url = HttpUrl.parse("http://192.168.1.11:8080/");
assertThat(HttpUrlUtil.isRestBase(url), is(false));
}
@Test public void testIsMobileViewTest() {
HttpUrl url = HttpUrl.parse(WikiSite.forLanguageCode("test").url())
.newBuilder()
.addQueryParameter("action", "mobileview")
.build();
assertThat(HttpUrlUtil.isMobileView(url), is(true));
}
@Test public void testIsMobileViewDev() {
HttpUrl url = HttpUrl.parse("http://localhost:8080/?action=mobileview");
assertThat(HttpUrlUtil.isMobileView(url), is(true));
}
@Test public void testIsMobileViewRestBase() {
HttpUrl url = HttpUrl.parse("https://en.wikipedia.org/api/rest_v1/");
assertThat(HttpUrlUtil.isMobileView(url), is(false));
}
}

View file

@ -0,0 +1,88 @@
package org.wikipedia.dataclient.page;
import androidx.annotation.NonNull;
import org.junit.Test;
import org.wikipedia.dataclient.Service;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.observers.TestObserver;
import okhttp3.CacheControl;
import retrofit2.Response;
import static org.wikipedia.dataclient.Service.PREFERRED_THUMB_SIZE;
public abstract class BasePageClientTest extends MockRetrofitTest {
@Test public void testLeadCacheControl() {
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject().lead(wikiSite(), CacheControl.FORCE_NETWORK, null, null, "foo", 0).subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header("Cache-Control").contains("no-cache"));
}
@Test public void testLeadHttpRefererUrl() {
String refererUrl = "https://en.wikipedia.org/wiki/United_States";
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject().lead(wikiSite(), null, null, refererUrl, "foo", 0).subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header("Referer").contains(refererUrl));
}
@Test public void testLeadCacheOptionCache() {
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject().lead(wikiSite(), null, null, null, "foo", 0).subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header(Service.OFFLINE_SAVE_HEADER) == null);
}
@Test public void testLeadCacheOptionSave() {
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject().lead(wikiSite(), null, Service.OFFLINE_SAVE_HEADER_SAVE, null, "foo", 0).subscribe(observer);
observer.assertComplete().assertValue(result -> result.raw().request().header(Service.OFFLINE_SAVE_HEADER).contains(Service.OFFLINE_SAVE_HEADER_SAVE));
}
@Test public void testLeadTitle() {
TestObserver<Response<PageLead>> observer = new TestObserver<>();
subject().lead(wikiSite(), null, null, null, "Title", 0).subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> {
System.out.println(result.raw().request().url());
System.out.println(result.raw().request().url().toString());
return result.raw().request().url().toString().contains("Title");
});
}
@Test public void testSectionsCacheControl() {
TestObserver<Response<PageRemaining>> observer = new TestObserver<>();
subject().sections(wikiSite(), CacheControl.FORCE_NETWORK, null, "foo").subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header("Cache-Control").contains("no-cache"));
}
@Test public void testSectionsCacheOptionCache() {
TestObserver<Response<PageRemaining>> observer = new TestObserver<>();
subject().sections(wikiSite(), null, null, "foo").subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header(Service.OFFLINE_SAVE_HEADER) == null);
}
@Test public void testSectionsCacheOptionSave() {
TestObserver<Response<PageRemaining>> observer = new TestObserver<>();
subject().sections(wikiSite(), null, Service.OFFLINE_SAVE_HEADER_SAVE, "foo").subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().header(Service.OFFLINE_SAVE_HEADER).contains(Service.OFFLINE_SAVE_HEADER_SAVE));
}
@Test public void testSectionsTitle() {
TestObserver<Response<PageRemaining>> observer = new TestObserver<>();
subject().sections(wikiSite(), null, null, "Title").subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.raw().request().url().toString().contains("Title"));
}
@NonNull protected abstract PageClient subject();
protected String preferredThumbSizeString() {
return Integer.toString(PREFERRED_THUMB_SIZE) + "px";
}
}

View file

@ -0,0 +1,101 @@
package org.wikipedia.dataclient.page;
import androidx.annotation.NonNull;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.mwapi.MwServiceError;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* Common test code for the two PageLead variants.
*/
public abstract class BasePageLeadTest extends BasePageClientTest {
protected static final int ID = 15580374;
protected static final long REVISION = 664887982L;
protected static final int LANGUAGE_COUNT = 45;
protected static final String LAST_MODIFIED_DATE = "2015-05-31T17:32:11Z";
protected static final String MAIN_PAGE = "Main Page";
@NonNull
public static String getEnglishMainPageJson() {
return "{"
+ "\"lastmodified\":\"" + LAST_MODIFIED_DATE + "\","
+ "\"revision\":" + REVISION + ","
+ "\"languagecount\":" + LANGUAGE_COUNT + ","
+ "\"displaytitle\":\"" + MAIN_PAGE + "\","
+ "\"id\":" + ID + ","
+ "\"description\":\"main page of a Wikimedia project\","
+ "\"mainpage\":true,"
+ "\"sections\":["
+ "{\"id\":0,\"text\":\"My lead section text\"}"
+ "],"
+ "\"protection\":{\"edit\":[\"made_up_role1\"],\"move\":[\"made_up_role2\"]},"
+ "\"editable\":false"
+ "}";
}
protected void verifyEnglishMainPage(PageLeadProperties props) {
assertThat(props.getId(), is(ID));
assertThat(props.getRevision(), is(REVISION));
assertThat(props.getLastModified(), is(LAST_MODIFIED_DATE));
assertThat(props.getDisplayTitle(), is(MAIN_PAGE));
assertThat(props.getLanguageCount(), is(LANGUAGE_COUNT));
assertThat(props.getLeadImageUrl(0), equalTo(null));
assertThat(props.getLeadImageFileName(), equalTo(null));
assertThat(props.getSections().size(), is(1));
assertThat(props.getSections().get(0).getId(), is(0));
assertThat(props.getSections().get(0).getContent(), is("My lead section text"));
assertThat(props.getSections().get(0).getLevel(), is(1));
assertThat(props.getSections().get(0).getAnchor(), equalTo(""));
assertThat(props.getSections().get(0).getHeading(), equalTo(""));
assertThat(props.getFirstAllowedEditorRole(), is("made_up_role1"));
assertThat(props.isEditable(), is(false));
assertThat(props.isMainPage(), is(true));
assertThat(props.isDisambiguation(), is(false));
}
@NonNull
protected String getUnprotectedDisambiguationPageJson() {
return "{"
+ "\"disambiguation\":true,"
+ "\"protection\":{},"
+ "\"editable\":true"
+ "}";
}
protected void verifyUnprotectedDisambiguationPage(PageLeadProperties core) {
assertThat(core.getFirstAllowedEditorRole(), equalTo(null));
assertThat(core.isEditable(), is(true));
assertThat(core.isMainPage(), is(false));
assertThat(core.isDisambiguation(), is(true));
}
@NonNull
protected String getProtectedButNoEditProtectionPageJson() {
return "{"
+ "\"protection\":{\"move\":[\"sysop\"]}"
+ "}";
}
protected void verifyProtectedNoEditProtectionPage(PageLeadProperties core) {
assertThat(core.getFirstAllowedEditorRole(), equalTo(null));
}
@NonNull
protected String getErrorJson() {
return "{\"error\":{"
+ "\"code\":\"nopage\","
+ "\"info\":\"The page parameter must be set\","
+ "\"docref\":\"See https://en.wikipedia.org/w/api.php for API usage\""
+ "}}";
}
protected void verifyError(MwException e) {
MwServiceError error = e.getError();
assertThat(error.getTitle(), is("nopage"));
assertThat(error.getDetails(), is("The page parameter must be set"));
}
}

View file

@ -0,0 +1,57 @@
package org.wikipedia.dataclient.restbase.page;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.wikipedia.dataclient.page.BasePageLeadTest;
import org.wikipedia.dataclient.page.PageClient;
import io.reactivex.observers.TestObserver;
import okhttp3.CacheControl;
import retrofit2.Response;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
public class RbPageLeadTest extends BasePageLeadTest {
private PageClient subject;
@Before @Override public void setUp() throws Throwable {
super.setUp();
subject = new RbPageClient();
}
@Test public void testEnglishMainPage() {
RbPageLead props = unmarshal(RbPageLead.class, getEnglishMainPageJson());
verifyEnglishMainPage(props);
}
@Test public void testUnprotectedDisambiguationPage() {
RbPageLead props = unmarshal(RbPageLead.class, getUnprotectedDisambiguationPageJson());
verifyUnprotectedDisambiguationPage(props);
}
/**
* Custom deserializer; um, yeah /o\.
* An earlier version had issues with protection settings that don't include "edit" protection.
*/
@Test public void testProtectedButNoEditProtectionPage() {
RbPageLead props = unmarshal(RbPageLead.class, getProtectedButNoEditProtectionPageJson());
verifyProtectedNoEditProtectionPage(props);
}
@Test @SuppressWarnings("checkstyle:magicnumber") public void testThumbUrls() throws Throwable {
enqueueFromFile("page_lead_rb.json");
TestObserver<Response<RbPageLead>> observer = new TestObserver<>();
getRestService().getLeadSection(CacheControl.FORCE_NETWORK.toString(), null, null, "foo").subscribe(observer);
observer.assertComplete()
.assertValue(result -> result.body().getLeadImageUrl(640).contains("640px")
&& result.body().getThumbUrl().contains(preferredThumbSizeString())
&& result.body().getDescription().contains("Mexican boxer")
&& result.body().getDescriptionSource().contains("central"));
}
@NonNull @Override protected PageClient subject() {
return subject;
}
}

View file

@ -0,0 +1,40 @@
package org.wikipedia.dataclient.restbase.page;
import org.junit.Before;
import org.junit.Test;
import org.wikipedia.feed.mostread.MostReadArticlesTest;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
@SuppressWarnings("checkstyle:magicnumber")
public class RbPageSummaryTest {
private List<RbPageSummary> subjects;
@Before public void setUp() throws Throwable {
subjects = MostReadArticlesTest.unmarshal("most_read.json").articles();
}
@Test public void testUnmarshalThumbnails() {
RbPageSummary subject = subjects.get(3);
assertThat(subject.getNormalizedTitle(), is("Marilyn Monroe"));
assertThat(subject.getTitle(), is("Marilyn_Monroe"));
assertThat(subject.getDescription(), is("American actress, model, and singer"));
String thumbnail = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Marilyn_Monroe_in_1952.jpg/229px-Marilyn_Monroe_in_1952.jpg";
assertThat(subject.getThumbnailUrl(), is(thumbnail));
}
@Test public void testUnmarshalNoThumbnails() {
RbPageSummary subject = subjects.get(0);
assertThat(subject.getNormalizedTitle(), is("Bicycle Race"));
assertThat(subject.getTitle(), is("Bicycle_Race"));
assertThat(subject.getDescription(), is("rock song by Queen"));
assertThat(subject.getThumbnailUrl(), nullValue());
}
}

View file

@ -0,0 +1,147 @@
package org.wikipedia.edit;
import androidx.annotation.NonNull;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.captcha.CaptchaResult;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.okhttp.HttpStatusException;
import org.wikipedia.page.PageTitle;
import org.wikipedia.test.MockWebServerTest;
import retrofit2.Call;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class EditClientTest extends MockWebServerTest {
private EditClient subject = new EditClient();
@Test @SuppressWarnings("checkstyle:magicnumber")
public void testRequestSuccessHasResults() throws Throwable {
EditSuccessResult expected = new EditSuccessResult(761350490);
enqueueFromFile("edit_result_success.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackSuccess(call, cb, expected);
}
@Test public void testRequestResponseAbuseFilter() throws Throwable {
EditAbuseFilterResult expected = new EditAbuseFilterResult("abusefilter-disallowed",
"Hit AbuseFilter: Editing user page by anonymous user",
"<b>Warning:</b> This action has been automatically identified as harmful.\nUnconstructive edits will be quickly reverted,\nand egregious or repeated unconstructive editing will result in your account or IP address being blocked.\nIf you believe this action to be constructive, you may submit it again to confirm it.\nA brief description of the abuse rule which your action matched is: Editing user page by anonymous user");
enqueueFromFile("edit_abuse_filter_result.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackSuccess(call, cb, expected);
}
@Test public void testRequestResponseSpamBlacklist() throws Throwable {
EditSpamBlacklistResult expected = new EditSpamBlacklistResult("s-e-x");
enqueueFromFile("edit_result_spam_blacklist.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackSuccess(call, cb, expected);
}
@Test @SuppressWarnings("checkstyle:magicnumber")
public void testRequestResponseCaptcha() throws Throwable {
CaptchaResult expected = new CaptchaResult("547159230");
enqueueFromFile("edit_result_captcha.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackSuccess(call, cb, expected);
}
@Test public void testRequestResponseAssertUserFailed() throws Throwable {
enqueueFromFile("api_error_assert_user_failed.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, true);
server().takeRequest();
assertCallbackFailure(call, cb, MwException.class);
}
@Test public void testRequestResponseGenericApiError() throws Throwable {
enqueueFromFile("api_error.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackFailure(call, cb, MwException.class);
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackFailure(call, cb, MwException.class);
}
@Test public void testRequestResponse404() throws Throwable {
enqueue404();
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackFailure(call, cb, HttpStatusException.class);
}
@Test public void testRequestResponseMalformed() throws Throwable {
enqueueMalformed();
EditClient.Callback cb = mock(EditClient.Callback.class);
Call<Edit> call = request(cb, false);
server().takeRequest();
assertCallbackFailure(call, cb, MalformedJsonException.class);
}
private void assertCallbackSuccess(@NonNull Call<Edit> call,
@NonNull EditClient.Callback cb,
@NonNull EditResult expected) {
verify(cb).success(eq(call), eq(expected));
//noinspection unchecked
verify(cb, never()).failure(any(Call.class), any(Throwable.class));
}
private void assertCallbackFailure(@NonNull Call<Edit> call,
@NonNull EditClient.Callback cb,
@NonNull Class<? extends Throwable> throwable) {
//noinspection unchecked
verify(cb, never()).success(any(Call.class), any(EditResult.class));
verify(cb).failure(eq(call), isA(throwable));
}
private Call<Edit> request(@NonNull EditClient.Callback cb, boolean loggedIn) {
PageTitle title = new PageTitle(null, "TEST", WikiSite.forLanguageCode("test"));
return subject.request(service(Service.class), title, 0, "new text", "token",
"summary", null, loggedIn, "captchaId", "captchaSubmission", cb);
}
}

View file

@ -0,0 +1,81 @@
package org.wikipedia.edit;
import androidx.annotation.NonNull;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.edit.EditClient.Callback;
import org.wikipedia.page.PageTitle;
import org.wikipedia.test.MockWebServerTest;
import retrofit2.Call;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class EditUnitTest extends MockWebServerTest {
@NonNull private EditClient client = new EditClient();
@Test public void testAbuseFilterResult() throws Throwable {
enqueueFromFile("edit_abuse_filter_result.json");
Callback cb = mock(Callback.class);
Call<Edit> call = request(cb);
server().takeRequest();
assertAbuseFilterEditResult(call, cb);
}
@Test public void testBadToken() throws Throwable {
enqueueFromFile("edit_error_bad_token.json");
Callback cb = mock(Callback.class);
Call<Edit> call = request(cb);
server().takeRequest();
assertExpectedEditError(call, cb, "Invalid token");
}
@Test public void testRequestUserNotLoggedIn() throws Throwable {
enqueueFromFile("edit_user_not_logged_in.json");
Callback cb = mock(Callback.class);
Call<Edit> call = request(cb);
server().takeRequest();
assertExpectedEditError(call, cb, "Assertion that the user is logged in failed");
}
@NonNull private Call<Edit> request(@NonNull Callback cb) {
return client.request(service(Service.class), new PageTitle("FAKE TITLE",
WikiSite.forLanguageCode("test")), 0, "FAKE EDIT TEXT", "+/", "FAKE SUMMARY", null, false,
null, null, cb);
}
private void assertAbuseFilterEditResult(@NonNull Call<Edit> call,
@NonNull Callback cb) {
verify(cb).success(eq(call), isA(EditAbuseFilterResult.class));
//noinspection unchecked
verify(cb, never()).failure(any(Call.class), any(Throwable.class));
}
private void assertExpectedEditError(@NonNull Call<Edit> call,
@NonNull Callback cb,
@NonNull String expectedCode) {
ArgumentCaptor<Throwable> captor = ArgumentCaptor.forClass(Throwable.class);
//noinspection unchecked
verify(cb, never()).success(any(Call.class), any(EditSuccessResult.class));
verify(cb).failure(eq(call), captor.capture());
Throwable t = captor.getValue();
assertThat(t.getMessage(), is(expectedCode));
}
}

View file

@ -0,0 +1,47 @@
package org.wikipedia.edit.preview;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class EditPreviewClientTest extends MockRetrofitTest {
@Test public void testRequestSuccessHasResults() throws Throwable {
String expected = "<div class=\"mf-section-0\" id=\"mf-section-0\"><p>\\o/\\n\\ntest12\\n\\n3</p>\n\n\n\n\n</div>";
enqueueFromFile("edit_preview.json");
TestObserver<EditPreview> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(response -> response.result().equals(expected));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<EditPreview> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MwException.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<EditPreview> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<EditPreview> getObservable() {
return getApiService().postEditPreview("User:Mhollo/sandbox", "wikitext of change");
}
}

View file

@ -0,0 +1,47 @@
package org.wikipedia.edit.wikitext;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class WikitextClientTest extends MockRetrofitTest {
@Test public void testRequestSuccessHasResults() throws Throwable {
enqueueFromFile("wikitext.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(response -> response.query().firstPage().revisions().get(0).content().equals("\\o/\n\ntest12\n\n3")
&& response.query().firstPage().revisions().get(0).timeStamp().equals("2018-03-18T18:10:54Z"));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MwException.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<MwQueryResponse> getObservable() {
return getApiService().getWikiTextForSection("User:Mhollo/sandbox", 0);
}
}

View file

@ -0,0 +1,63 @@
package org.wikipedia.feed.announcement;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
@RunWith(RobolectricTestRunner.class)
public class GeoIPCookieUnmarshallerTest {
private static final double LATITUDE = 37.33;
private static final double LONGITUDE = -121.89;
@Test public void testGeoIPWithLocation() {
GeoIPCookie cookie = GeoIPCookieUnmarshaller.unmarshal("US:California:San Francisco:" + LATITUDE + ":" + LONGITUDE + ":v4");
assertThat(cookie.country(), is("US"));
assertThat(cookie.region(), is("California"));
assertThat(cookie.city(), is("San Francisco"));
assertThat(cookie.location(), is(notNullValue()));
assertThat(cookie.location().getLatitude(), is(LATITUDE));
assertThat(cookie.location().getLongitude(), is(LONGITUDE));
}
@Test public void testGeoIPWithoutLocation() {
GeoIPCookie cookie = GeoIPCookieUnmarshaller.unmarshal("FR::Paris:::v4");
assertThat(cookie.country(), is("FR"));
assertThat(cookie.region(), is(""));
assertThat(cookie.city(), is("Paris"));
assertThat(cookie.location(), is(nullValue()));
}
@Test public void testGeoIPEmpty() {
GeoIPCookie cookie = GeoIPCookieUnmarshaller.unmarshal(":::::v4");
assertThat(cookie.country(), is(""));
assertThat(cookie.region(), is(""));
assertThat(cookie.city(), is(""));
assertThat(cookie.location(), is(nullValue()));
}
@Test(expected = IllegalArgumentException.class)
public void testGeoIPWrongVersion() {
GeoIPCookieUnmarshaller.unmarshal("RU::Moscow:1:2:v5");
}
@Test(expected = IllegalArgumentException.class)
public void testGeoIPWrongParamCount() {
GeoIPCookieUnmarshaller.unmarshal("CA:Toronto:v4");
}
@Test(expected = IllegalArgumentException.class)
public void testGeoIPMalformed() {
GeoIPCookieUnmarshaller.unmarshal("foo");
}
@Test(expected = IllegalArgumentException.class)
public void testGeoIPWithBadLocation() {
GeoIPCookieUnmarshaller.unmarshal("US:California:San Francisco:foo:bar:v4");
}
}

View file

@ -0,0 +1,42 @@
package org.wikipedia.feed.mostread;
import androidx.annotation.NonNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.json.GsonUnmarshaller;
import org.wikipedia.test.TestFileUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
@RunWith(RobolectricTestRunner.class)
@SuppressWarnings("checkstyle:magicnumber")
public class MostReadArticlesTest {
@NonNull public static MostReadArticles unmarshal(@NonNull String filename) throws Throwable {
String json = TestFileUtil.readRawFile(filename);
return GsonUnmarshaller.unmarshal(MostReadArticles.class, json);
}
@Test public void testUnmarshalManyArticles() throws Throwable {
MostReadArticles subject = unmarshal("most_read.json");
assertThat(subject.date(), is(date("2016-06-01Z")));
assertThat(subject.articles(), notNullValue());
assertThat(subject.articles().size(), is(40));
}
@NonNull private Date date(@NonNull String str) throws Throwable {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'Z'", Locale.ROOT);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.parse(str);
}
}

View file

@ -0,0 +1,108 @@
package org.wikipedia.gallery;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.test.MockRetrofitTest;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class GalleryClientTest extends MockRetrofitTest {
private static final String RAW_JSON_FILE = "gallery.json";
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testRequestAllSuccess() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(gallery -> {
List<GalleryItem> result = gallery.getAllItems();
return result != null
&& result.get(0).getType().equals("image")
&& result.get(2).getType().equals("audio")
&& result.get(4).getType().equals("video");
});
}
@Test
public void testRequestImageSuccess() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(gallery -> {
List<GalleryItem> result = gallery.getItems("image");
return result.size() == 2
&& result.get(0).getType().equals("image")
&& result.get(0).getTitles().getCanonical().equals("File:Flag_of_the_United_States.svg")
&& result.get(0).getThumbnail().getSource().equals("http://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/320px-Flag_of_the_United_States.svg.png")
&& result.get(0).getThumbnailUrl().equals("http://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/320px-Flag_of_the_United_States.svg.png")
&& result.get(0).getPreferredSizedImageUrl().equals("http://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1280px-Flag_of_the_United_States.svg.png");
});
}
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testRequestVideoSuccess() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(gallery -> {
List<GalleryItem> result = gallery.getItems("video");
return result.get(0).getSources().size() == 6
&& result.get(0).getType().equals("video")
&& result.get(0).getTitles().getCanonical().equals("File:Curiosity's_Seven_Minutes_of_Terror.ogv")
&& result.get(0).getFilePage().equals("https://commons.wikimedia.org/wiki/File:Curiosity%27s_Seven_Minutes_of_Terror.ogv")
&& result.get(0).getOriginalVideoSource().getOriginalUrl().equals("https://upload.wikimedia.org/wikipedia/commons/transcoded/9/96/Curiosity%27s_Seven_Minutes_of_Terror.ogv/Curiosity%27s_Seven_Minutes_of_Terror.ogv.720p.webm");
});
}
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testRequestAudioSuccess() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(gallery -> {
List<GalleryItem> result = gallery.getItems("audio");
return result.size() == 2
&& result.get(0).getType().equals("audio")
&& result.get(1).getTitles().getCanonical().equals("File:March,_Colonel_John_R._Bourgeois,_Director_·_John_Philip_Sousa_·_United_States_Marine_Band.ogg")
&& result.get(1).getDuration() == 226.51766666667
&& result.get(0).getAudioType().equals("generic");
});
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<Gallery> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<Gallery> getObservable() {
return getRestService().getMedia("foo");
}
}

View file

@ -0,0 +1,71 @@
package org.wikipedia.gallery;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwQueryPage;
import org.wikipedia.page.PageTitle;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.observers.TestObserver;
public class ImageLicenseFetchClientTest extends MockRetrofitTest {
private static final WikiSite WIKISITE_TEST = WikiSite.forLanguageCode("test");
private static final PageTitle PAGE_TITLE_MARK_SELBY =
new PageTitle("File:Mark_Selby_at_Snooker_German_Masters_(DerHexer)_2015-02-04_02.jpg",
WIKISITE_TEST);
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("image_license.json");
TestObserver<ImageLicense> observer = new TestObserver<>();
getApiService().getImageExtMetadata(PAGE_TITLE_MARK_SELBY.getPrefixedText())
.map(response -> {
// noinspection ConstantConditions
MwQueryPage page = response.query().pages().get(0);
return page.imageInfo() != null && page.imageInfo().getMetadata() != null
? new ImageLicense(page.imageInfo().getMetadata())
: new ImageLicense();
})
.subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getLicenseName().equals("cc-by-sa-4.0")
&& result.getLicenseShortName().equals("CC BY-SA 4.0")
&& result.getLicenseUrl().equals("http://creativecommons.org/licenses/by-sa/4.0"));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<ImageLicense> observer = new TestObserver<>();
getApiService().getImageExtMetadata(PAGE_TITLE_MARK_SELBY.getPrefixedText())
.map(response -> new ImageLicense())
.subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<ImageLicense> observer = new TestObserver<>();
getApiService().getImageExtMetadata(PAGE_TITLE_MARK_SELBY.getPrefixedText())
.map(response -> new ImageLicense())
.subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<ImageLicense> observer = new TestObserver<>();
getApiService().getImageExtMetadata(PAGE_TITLE_MARK_SELBY.getPrefixedText())
.map(response -> new ImageLicense())
.subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
}

View file

@ -0,0 +1,74 @@
package org.wikipedia.json;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
import org.wikipedia.page.Namespace;
import java.util.Arrays;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.wikipedia.json.GsonMarshaller.marshal;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
@RunWith(ParameterizedRobolectricTestRunner.class) public class NamespaceTypeAdapterTest {
@Parameters(name = "{0}") public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {{DeferredParam.NULL}, {DeferredParam.SPECIAL},
{DeferredParam.MAIN}, {DeferredParam.TALK}});
}
@Nullable private final Namespace namespace;
public NamespaceTypeAdapterTest(@NonNull DeferredParam param) {
this.namespace = param.val();
}
@Test public void testWriteRead() {
Namespace result = unmarshal(Namespace.class, marshal(namespace));
assertThat(result, is(namespace));
}
@Test public void testReadOldData() {
// Prior to 3210ce44, we marshaled Namespace as the name string of the enum, instead of
// the code number, and when we switched to using the code number, we didn't introduce
// backwards-compatible checks for the old-style strings that may still be present in
// some local serialized data.
// TODO: remove after April 2017?
String marshaledStr = namespace == null ? "null" : "\"" + namespace.name() + "\"";
Namespace ns = unmarshal(Namespace.class, marshaledStr);
assertThat(ns, is(namespace));
}
// SparseArray is a Roboelectric mocked class which is unavailable at static time; defer
// evaluation until TestRunner is executed
private enum DeferredParam {
NULL() {
@Nullable @Override
Namespace val() {
return null;
}
},
SPECIAL() {
@NonNull @Override Namespace val() {
return Namespace.SPECIAL;
}
},
MAIN() {
@NonNull @Override Namespace val() {
return Namespace.MAIN;
}
},
TALK() {
@NonNull @Override Namespace val() {
return Namespace.TALK;
}
};
@Nullable abstract Namespace val();
}
}

View file

@ -0,0 +1,184 @@
package org.wikipedia.json;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.Service;
import org.wikipedia.json.annotations.Required;
import org.wikipedia.model.BaseModel;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.wikipedia.json.GsonMarshaller.marshal;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
@RunWith(RobolectricTestRunner.class)
public class RequiredFieldsCheckOnReadTypeAdapterFactoryTest {
private final Gson gson = GsonUtil.getDefaultGsonBuilder().serializeNulls().create();
@Test
public void testRequireNonNull() {
RequiredModel expected = new RequiredModel();
expected.field = 1;
RequiredModel result = unmarshal(gson, RequiredModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testRequireNull() {
RequiredModel model = new RequiredModel();
RequiredModel result = unmarshal(gson, RequiredModel.class, marshal(gson, model));
assertThat(result, nullValue());
}
@Test
public void testRequireMissing() {
RequiredModel result = unmarshal(gson, RequiredModel.class, "{}");
assertThat(result, nullValue());
}
@Test
public void testOptionalNonNull() {
OptionalModel expected = new OptionalModel();
expected.field = 1;
OptionalModel result = unmarshal(gson, OptionalModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testOptionalNull() {
OptionalModel expected = new OptionalModel();
OptionalModel result = unmarshal(gson, OptionalModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testOptionalMissing() {
OptionalModel expected = new OptionalModel();
OptionalModel result = unmarshal(gson, OptionalModel.class, "{}");
assertThat(result, is(expected));
}
@Test
public void testRequiredTypeAdapterNonNull() {
RequiredTypeAdapterModel expected = new RequiredTypeAdapterModel();
expected.uri = Uri.parse(Service.WIKIPEDIA_URL);
RequiredTypeAdapterModel result = unmarshal(gson, RequiredTypeAdapterModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testRequiredTypeAdapterNull() {
RequiredTypeAdapterModel expected = new RequiredTypeAdapterModel();
RequiredTypeAdapterModel result = unmarshal(gson, RequiredTypeAdapterModel.class, marshal(gson, expected));
assertThat(result, nullValue());
}
@Test
public void testRequiredTypeAdapterMissing() {
RequiredTypeAdapterModel result = unmarshal(gson, RequiredTypeAdapterModel.class, "{}");
assertThat(result, nullValue());
}
@Test
public void testOptionalTypeAdapterNonNull() {
OptionalTypeAdapterModel expected = new OptionalTypeAdapterModel();
expected.uri = Uri.parse(Service.WIKIPEDIA_URL);
OptionalTypeAdapterModel result = unmarshal(gson, OptionalTypeAdapterModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testOptionalTypeAdapterNull() {
OptionalTypeAdapterModel expected = new OptionalTypeAdapterModel();
OptionalTypeAdapterModel result = unmarshal(gson, OptionalTypeAdapterModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testOptionalTypeAdapterMissing() {
OptionalTypeAdapterModel expected = new OptionalTypeAdapterModel();
OptionalTypeAdapterModel result = unmarshal(gson, OptionalTypeAdapterModel.class, "{}");
assertThat(result, is(expected));
}
@Test
public void testRequiredSerializedNameNonNull() {
SerializedNameModel expected = new SerializedNameModel();
expected.bar = "hello world";
SerializedNameModel result = unmarshal(gson, SerializedNameModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testRequiredSerializedNameNull() {
SerializedNameModel expected = new SerializedNameModel();
SerializedNameModel result = unmarshal(gson, SerializedNameModel.class, marshal(gson, expected));
assertThat(result, nullValue());
}
@Test
public void testRequiredSerializedNameMissing() {
SerializedNameModel result = unmarshal(gson, SerializedNameModel.class, "{}");
assertThat(result, nullValue());
}
@Test
public void testComposedValid() {
RequiredModel required = new RequiredModel();
required.field = 1;
OptionalModel optional = new OptionalModel();
ComposedModel expected = new ComposedModel();
expected.required = required;
expected.optional = optional;
ComposedModel result = unmarshal(gson, ComposedModel.class, marshal(gson, expected));
assertThat(result, is(expected));
}
@Test
public void testComposedInvalid() {
RequiredModel required = new RequiredModel();
OptionalModel optional = new OptionalModel();
ComposedModel aggregated = new ComposedModel();
aggregated.required = required;
aggregated.optional = optional;
ComposedModel result = unmarshal(gson, ComposedModel.class, marshal(gson, aggregated));
assertThat(result, nullValue());
}
private static class RequiredModel extends BaseModel {
@SuppressWarnings("NullableProblems") @Required @NonNull private Integer field;
}
private static class OptionalModel extends BaseModel {
@Nullable private Integer field;
}
private static class ComposedModel extends BaseModel {
@SuppressWarnings("NullableProblems") @Required @NonNull private RequiredModel required;
@Nullable private OptionalModel optional;
}
private static class RequiredTypeAdapterModel extends BaseModel {
@SuppressWarnings("NullableProblems") @Required @NonNull private Uri uri;
}
private static class OptionalTypeAdapterModel extends BaseModel {
@Nullable private Uri uri;
}
private static class SerializedNameModel extends BaseModel {
@SuppressWarnings("NullableProblems") @SerializedName("foo") @Required @NonNull private String bar;
}
}

View file

@ -0,0 +1,64 @@
package org.wikipedia.json;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
import org.wikipedia.dataclient.Service;
import java.util.Arrays;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.wikipedia.json.GsonMarshaller.marshal;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
@RunWith(ParameterizedRobolectricTestRunner.class) public class UriTypeAdapterTest {
@Parameters(name = "{0}") public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {{DeferredParam.NULL}, {DeferredParam.STRING},
{DeferredParam.OPAQUE}, {DeferredParam.HIERARCHICAL}});
}
@Nullable private final Uri uri;
public UriTypeAdapterTest(@NonNull DeferredParam param) {
this.uri = param.val();
}
@Test public void testWriteRead() {
Uri result = unmarshal(Uri.class, marshal(uri));
assertThat(result, is(uri));
}
// Namespace uses a roboelectric mocked class internally, SparseArray, which is unavailable at
// static time; defer evaluation until TestRunner is executed
private enum DeferredParam {
NULL() {
@Nullable @Override Uri val() {
return null;
}
},
STRING() {
@Nullable @Override Uri val() {
return Uri.parse(Service.WIKIPEDIA_URL);
}
},
OPAQUE() {
@Nullable @Override Uri val() {
return Uri.fromParts("http", "mediawiki.org", null);
}
},
HIERARCHICAL() {
@Nullable @Override Uri val() {
return Uri.EMPTY;
}
};
@Nullable abstract Uri val();
}
}

View file

@ -0,0 +1,48 @@
package org.wikipedia.json;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.WikiSite;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.wikipedia.json.GsonMarshaller.marshal;
import static org.wikipedia.json.GsonUnmarshaller.unmarshal;
@RunWith(RobolectricTestRunner.class) public class WikiSiteTypeAdapterTest {
@Test public void testWriteRead() {
WikiSite wiki = WikiSite.forLanguageCode("test");
assertThat(unmarshal(WikiSite.class, marshal(wiki)), is(wiki));
}
@Test public void testReadNull() {
assertThat(unmarshal(WikiSite.class, null), nullValue());
}
@Test public void testReadLegacyString() {
String json = "\"https://test.wikipedia.org\"";
WikiSite expected = WikiSite.forLanguageCode("test");
assertThat(unmarshal(WikiSite.class, json), is(expected));
}
@Test public void testReadLegacyUri() {
String json = "{\"domain\": \"test.wikipedia.org\", \"languageCode\": \"test\"}";
WikiSite expected = WikiSite.forLanguageCode("test");
assertThat(unmarshal(WikiSite.class, json), is(expected));
}
@Test public void testReadLegacyUriLang() {
String json = "{\"domain\": \"test.wikipedia.org\"}";
WikiSite expected = WikiSite.forLanguageCode("test");
assertThat(unmarshal(WikiSite.class, json), is(expected));
}
@Test public void testReadLegacyLang() {
String json = "{\"domain\": \"https://test.wikipedia.org\"}";
WikiSite expected = WikiSite.forLanguageCode("test");
assertThat(unmarshal(WikiSite.class, json), is(expected));
}
}

View file

@ -0,0 +1,60 @@
package org.wikipedia.language;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class LangLinksClientTest extends MockRetrofitTest {
@Test
public void testRequestSuccessHasResults() throws Throwable {
enqueueFromFile("lang_links.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result ->
result.query().langLinks().get(0).getDisplayText().equals("Sciëntologie"));
}
@Test
public void testRequestSuccessNoResults() throws Throwable {
enqueueFromFile("lang_links_empty.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.query().langLinks().isEmpty());
}
@Test
public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test
public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<MwQueryResponse> getObservable() {
return getApiService().getLangLinks("foo");
}
}

View file

@ -0,0 +1,44 @@
package org.wikipedia.login;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class UserExtendedInfoClientTest extends MockRetrofitTest {
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("user_extended_info.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
final int id = 24531888;
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.query().userInfo().id() == id
&& result.query().getUserResponse("USER").name().equals("USER"));
}
@Test public void testRequestResponse404() {
enqueue404();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<MwQueryResponse> getObservable() {
return getApiService().getUserInfo("USER");
}
}

View file

@ -0,0 +1,23 @@
package org.wikipedia.media;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.wikipedia.dataclient.Service.PREFERRED_THUMB_SIZE;
import static org.wikipedia.util.ImageUrlUtil.getUrlForSize;
public class ImageUrlTest {
// Should rewrite URLs for larger images to the desired width, but leave smaller images and
// image URLs with no width alone.
@Test public void testImageUrlRewriting() {
String url1024 = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Istanbul_Airport_Turkish-Airlines_2013-11-18.JPG/1024px-Istanbul_Airport_Turkish-Airlines_2013-11-18.JPG";
String url320 = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Istanbul_Airport_Turkish-Airlines_2013-11-18.JPG/320px-Istanbul_Airport_Turkish-Airlines_2013-11-18.JPG";
String url244 = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/People%27s_Party_%28Spain%29_Logo.svg/244px-People%27s_Party_%28Spain%29_Logo.svg.png";
String urlNoWidth = "https://upload.wikimedia.org/wikipedia/commons/6/6a/Mariano_Rajoy_2015e_%28cropped%29.jpg";
assertThat(getUrlForSize(url1024, PREFERRED_THUMB_SIZE), is(url320));
assertThat(getUrlForSize(url244, PREFERRED_THUMB_SIZE), is(url244));
assertThat(getUrlForSize(urlNoWidth, PREFERRED_THUMB_SIZE), is(urlNoWidth));
}
}

View file

@ -0,0 +1,108 @@
package org.wikipedia.nearby;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.dataclient.mwapi.NearbyPage;
import org.wikipedia.test.MockRetrofitTest;
import java.util.Collections;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
import io.reactivex.observers.TestObserver;
@SuppressWarnings("checkstyle:magicnumber")
public class NearbyClientTest extends MockRetrofitTest {
@Test public void testRequestSuccessHasResults() throws Throwable {
enqueueFromFile("nearby.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(nearbyPages -> nearbyPages.get(0).getTitle().getDisplayText().equals("Bean Hollow State Beach")
&& nearbyPages.get(0).getLocation().getLatitude() == 37.22583333
&& nearbyPages.get(0).getLocation().getLongitude() == -122.40888889);
}
@Test public void testRequestNoResults() throws Throwable {
enqueueFromFile("nearby_empty.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getApiService().nearbySearch("0|0", 1)
.map((Function<MwQueryResponse, List<NearbyPage>>) response
-> response.query() != null ? response.query().nearbyPages(WikiSite.forLanguageCode("en")) : Collections.emptyList())
.subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(List::isEmpty);
}
@Test public void testLocationMissingCoordsIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_coords.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(List::isEmpty);
}
@Test public void testLocationMissingLatOnlyIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_lat.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(List::isEmpty);
}
@Test public void testLocationMissingLonOnlyIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_lon.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(List::isEmpty);
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MwException.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<List<NearbyPage>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<List<NearbyPage>> getObservable() {
return getApiService().nearbySearch("0|0", 1)
.map(response -> response.query().nearbyPages(WikiSite.forLanguageCode("en")));
}
}

View file

@ -0,0 +1,120 @@
package org.wikipedia.nearby;
import android.location.Location;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.NearbyPage;
import org.wikipedia.page.PageTitle;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
/**
* Unit tests for Nearby related classes. Probably should refactor this into a model class.
*/
@SuppressWarnings("checkstyle:magicnumber") @RunWith(RobolectricTestRunner.class)
public class NearbyUnitTest {
private static WikiSite TEST_WIKI_SITE = new WikiSite(Service.WIKIPEDIA_URL);
/** dist(origin, point a) */
private static final int A = 111_319;
private Location nextLocation;
private List<NearbyPage> nearbyPages;
@Before
public void setUp() {
nextLocation = new Location("current");
nextLocation.setLatitude(0.0d);
nextLocation.setLongitude(0.0d);
nearbyPages = new LinkedList<>();
nearbyPages.add(constructNearbyPage("c", 0.0, 3.0));
nearbyPages.add(constructNearbyPage("b", 0.0, 2.0));
nearbyPages.add(constructNearbyPage("a", 0.0, 1.0));
}
@Test public void testSort() {
calcDistances(nearbyPages);
Collections.sort(nearbyPages, new NearbyDistanceComparator());
assertThat("a", is(nearbyPages.get(0).getTitle().getDisplayText()));
assertThat("b", is(nearbyPages.get(1).getTitle().getDisplayText()));
assertThat("c", is(nearbyPages.get(2).getTitle().getDisplayText()));
}
@Test public void testSortWithNullLocations() {
final Location location = null;
nearbyPages.add(new NearbyPage(new PageTitle("d", TEST_WIKI_SITE), location));
nearbyPages.add(new NearbyPage(new PageTitle("e", TEST_WIKI_SITE), location));
calcDistances(nearbyPages);
Collections.sort(nearbyPages, new NearbyDistanceComparator());
assertThat("a", is(nearbyPages.get(0).getTitle().getDisplayText()));
assertThat("b", is(nearbyPages.get(1).getTitle().getDisplayText()));
assertThat("c", is(nearbyPages.get(2).getTitle().getDisplayText()));
// the two null location values come last but in the same order as from the original list:
assertThat("d", is(nearbyPages.get(3).getTitle().getDisplayText()));
assertThat("e", is(nearbyPages.get(4).getTitle().getDisplayText()));
}
@Test public void testCompare() {
final Location location = null;
NearbyPage nullLocPage = new NearbyPage(new PageTitle("nowhere", TEST_WIKI_SITE), location);
calcDistances(nearbyPages);
nullLocPage.setDistance(getDistance(nullLocPage.getLocation()));
assertThat(Integer.MAX_VALUE, is(nullLocPage.getDistance()));
NearbyDistanceComparator comp = new NearbyDistanceComparator();
assertThat(A, is(comp.compare(nearbyPages.get(1), nearbyPages.get(2))));
assertThat(-1 * A, is(comp.compare(nearbyPages.get(2), nearbyPages.get(1))));
assertThat(Integer.MAX_VALUE - A, is(comp.compare(nullLocPage, nearbyPages.get(2))));
assertThat((Integer.MIN_VALUE + 1) + A, is(comp.compare(nearbyPages.get(2), nullLocPage))); // - (max - a)
assertThat(0, is(comp.compare(nullLocPage, nullLocPage)));
}
private class NearbyDistanceComparator implements Comparator<NearbyPage> {
@Override
public int compare(NearbyPage a, NearbyPage b) {
return a.getDistance() - b.getDistance();
}
}
//
// UGLY: copy of production code
//
/**
* Calculates the distances from the origin to the given pages.
* This method should be called before sorting.
*/
private void calcDistances(List<NearbyPage> pages) {
for (NearbyPage page : pages) {
page.setDistance(getDistance(page.getLocation()));
}
}
private int getDistance(Location otherLocation) {
if (otherLocation == null) {
return Integer.MAX_VALUE;
} else {
return (int) nextLocation.distanceTo(otherLocation);
}
}
private NearbyPage constructNearbyPage(@NonNull String title, double lat, double lon) {
Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);
return new NearbyPage(new PageTitle(title, TEST_WIKI_SITE), location);
}
}

View file

@ -0,0 +1,57 @@
package org.wikipedia.notifications;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.json.GsonUnmarshaller;
import org.wikipedia.test.MockRetrofitTest;
import org.wikipedia.test.TestFileUtil;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class NotificationClientTest extends MockRetrofitTest {
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("notifications.json");
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(response -> {
List<Notification> notifications = response.query().notifications().list();
return notifications.get(0).type().equals("edit-thank")
&& notifications.get(0).title().full().equals("PageTitle")
&& notifications.get(0).agent().name().equals("User1");
});
}
@Test public void testRequestMalformed() {
enqueueMalformed();
TestObserver<MwQueryResponse> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
@Test public void testNotificationReverted() throws Throwable {
String json = TestFileUtil.readRawFile("notification_revert.json");
Notification n = GsonUnmarshaller.unmarshal(Notification.class, json);
assertThat(n.type(), is(Notification.TYPE_REVERTED));
assertThat(n.wiki(), is("wikidatawiki"));
assertThat(n.agent().name(), is("User1"));
assertThat(n.isFromWikidata(), is(true));
}
private Observable<MwQueryResponse> getObservable() {
return getApiService().getAllNotifications("*", "!read", null);
}
}

View file

@ -0,0 +1,99 @@
package org.wikipedia.page;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.WikiSite;
import java.util.Locale;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.wikipedia.page.Namespace.FILE;
import static org.wikipedia.page.Namespace.MAIN;
import static org.wikipedia.page.Namespace.MEDIA;
import static org.wikipedia.page.Namespace.SPECIAL;
import static org.wikipedia.page.Namespace.TALK;
@RunWith(RobolectricTestRunner.class) public class NamespaceTest {
private static Locale PREV_DEFAULT_LOCALE;
@BeforeClass public static void setUp() {
PREV_DEFAULT_LOCALE = Locale.getDefault();
Locale.setDefault(Locale.ENGLISH);
}
@AfterClass public static void tearDown() {
Locale.setDefault(PREV_DEFAULT_LOCALE);
}
@Test public void testOf() {
assertThat(Namespace.of(SPECIAL.code()), is(SPECIAL));
}
@Test public void testFromLegacyStringMain() {
//noinspection deprecation
assertThat(Namespace.fromLegacyString(WikiSite.forLanguageCode("test"), null), is(MAIN));
}
@Test public void testFromLegacyStringFile() {
//noinspection deprecation
assertThat(Namespace.fromLegacyString(WikiSite.forLanguageCode("he"), "קובץ"), is(FILE));
}
@Test public void testFromLegacyStringSpecial() {
//noinspection deprecation
assertThat(Namespace.fromLegacyString(WikiSite.forLanguageCode("lez"), "Служебная"), is(SPECIAL));
}
@Test public void testFromLegacyStringTalk() {
//noinspection deprecation
assertThat(Namespace.fromLegacyString(WikiSite.forLanguageCode("en"), "stringTalk"), is(TALK));
}
@Test public void testCode() {
assertThat(MAIN.code(), is(0));
assertThat(TALK.code(), is(1));
}
@Test public void testSpecial() {
assertThat(SPECIAL.special(), is(true));
assertThat(MAIN.special(), is(false));
}
@Test public void testMain() {
assertThat(MAIN.main(), is(true));
assertThat(TALK.main(), is(false));
}
@Test public void testFile() {
assertThat(FILE.file(), is(true));
assertThat(MAIN.file(), is(false));
}
@Test public void testTalkNegative() {
assertThat(MEDIA.talk(), is(false));
assertThat(SPECIAL.talk(), is(false));
}
@Test public void testTalkZero() {
assertThat(MAIN.talk(), is(false));
}
@Test public void testTalkOdd() {
assertThat(TALK.talk(), is(true));
}
@Test public void testToLegacyStringMain() {
//noinspection deprecation
assertThat(MAIN.toLegacyString(), nullValue());
}
@Test public void testToLegacyStringNonMain() {
//noinspection deprecation
assertThat(TALK.toLegacyString(), is("Talk"));
}
}

View file

@ -0,0 +1,35 @@
package org.wikipedia.page;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.WikiSite;
import java.util.ArrayList;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/** Unit tests for Page. */
@RunWith(RobolectricTestRunner.class)
public class PageTest {
private static final WikiSite WIKI = WikiSite.forLanguageCode("en");
@Test
public void testMediaWikiMarshalling() {
PageTitle title = new PageTitle("Main page", WIKI, "//foo/thumb.jpg");
PageProperties props = new PageProperties(title, true);
Page page = new Page(title, new ArrayList<>(), props, false);
assertThat(page.isFromRestBase(), is(false));
}
@Test
public void testRestBaseMarshalling() {
PageTitle title = new PageTitle("Main page", WIKI, "//foo/thumb.jpg");
PageProperties props = new PageProperties(title, true);
Page page = new Page(title, new ArrayList<>(), props, true);
assertThat(page.isFromRestBase(), is(true));
}
}

View file

@ -0,0 +1,139 @@
package org.wikipedia.page;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.dataclient.WikiSite;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(RobolectricTestRunner.class) public class PageTitleTest {
@Test public void testEquals() {
assertThat(new PageTitle(null, "India", WikiSite.forLanguageCode("en")).equals(new PageTitle(null, "India", WikiSite.forLanguageCode("en"))), is(true));
assertThat(new PageTitle("Talk", "India", WikiSite.forLanguageCode("en")).equals(new PageTitle("Talk", "India", WikiSite.forLanguageCode("en"))), is(true));
assertThat(new PageTitle(null, "India", WikiSite.forLanguageCode("ta")).equals(new PageTitle(null, "India", WikiSite.forLanguageCode("en"))), is(false));
assertThat(new PageTitle("Talk", "India", WikiSite.forLanguageCode("ta")).equals(new PageTitle("Talk", "India", WikiSite.forLanguageCode("en"))), is(false));
assertThat(new PageTitle("Talk", "India", WikiSite.forLanguageCode("ta")).equals("Something else"), is(false));
}
@Test public void testPrefixedText() {
WikiSite enwiki = WikiSite.forLanguageCode("en");
assertThat(new PageTitle(null, "Test title", enwiki).getPrefixedText(), is("Test__title"));
assertThat(new PageTitle(null, "Test title", enwiki).getPrefixedText(), is("Test_title"));
assertThat(new PageTitle("Talk", "Test title", enwiki).getPrefixedText(), is("Talk:Test_title"));
assertThat(new PageTitle(null, "Test title", enwiki).getText(), is("Test_title"));
}
@Test public void testFromInternalLink() {
WikiSite enwiki = WikiSite.forLanguageCode("en");
assertThat(enwiki.titleForInternalLink("/wiki/India").getPrefixedText(), is("India"));
assertThat(enwiki.titleForInternalLink("/wiki/India").getNamespace(), nullValue());
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India").getNamespace(), is("Talk"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India").getText(), is("India"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India").getFragment(), nullValue());
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#").getNamespace(), is("Talk"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#").getText(), is("India"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#").getFragment(), is(""));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#History").getNamespace(), is("Talk"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#History").getText(), is("India"));
assertThat(enwiki.titleForInternalLink("/wiki/Talk:India#History").getFragment(), is("History"));
}
@Test public void testCanonicalURL() {
WikiSite enwiki = WikiSite.forLanguageCode("en");
assertThat(enwiki.titleForInternalLink("/wiki/India").getCanonicalUri(), is("https://en.wikipedia.org/wiki/India"));
assertThat(enwiki.titleForInternalLink("/wiki/India Gate").getCanonicalUri(), is("https://en.wikipedia.org/wiki/India_Gate"));
assertThat(enwiki.titleForInternalLink("/wiki/India's Gate").getCanonicalUri(), is("https://en.wikipedia.org/wiki/India%27s_Gate"));
}
@Test public void testWikiSite() {
WikiSite enwiki = WikiSite.forLanguageCode("en");
assertThat(new PageTitle(null, "Test", enwiki).getWikiSite(), is(enwiki));
assertThat(WikiSite.forLanguageCode("en"), is(enwiki));
}
@Test public void testParsing() {
WikiSite enwiki = WikiSite.forLanguageCode("en");
assertThat(new PageTitle("Hello", enwiki).getDisplayText(), is("Hello"));
assertThat(new PageTitle("Talk:Hello", enwiki).getDisplayText(), is("Talk:Hello"));
assertThat(new PageTitle("Talk:Hello", enwiki).getText(), is("Hello"));
assertThat(new PageTitle("Talk:Hello", enwiki).getNamespace(), is("Talk"));
assertThat(new PageTitle("Wikipedia_talk:Hello world", enwiki).getDisplayText(), is("Wikipedia talk:Hello world"));
}
@Test public void testSpecial() {
assertThat(new PageTitle("Special:Version", WikiSite.forLanguageCode("en")).isSpecial(), is(true));
assertThat(new PageTitle("特別:Version", WikiSite.forLanguageCode("ja")).isSpecial(), is(true));
assertThat(new PageTitle("Special:Version", WikiSite.forLanguageCode("ja")).isSpecial(), is(true));
assertThat(new PageTitle("特別:Version", WikiSite.forLanguageCode("en")).isSpecial(), is(false));
}
@Test public void testFile() {
assertThat(new PageTitle("File:SomethingSomething", WikiSite.forLanguageCode("en")).isFilePage(), is(true));
assertThat(new PageTitle("ファイル:Version", WikiSite.forLanguageCode("ja")).isFilePage(), is(true));
assertThat(new PageTitle("File:SomethingSomething", WikiSite.forLanguageCode("ja")).isFilePage(), is(true));
assertThat(new PageTitle("ファイル:Version", WikiSite.forLanguageCode("en")).isFilePage(), is(false));
}
@Test public void testIsMainPageNoTitleNoProps() {
final String text = null;
WikiSite wiki = WikiSite.forLanguageCode("test");
final String thumbUrl = null;
final String desc = null;
final PageProperties props = null;
PageTitle subject = new PageTitle(text, wiki, thumbUrl, desc, props);
assertThat(subject.isMainPage(), is(false));
}
@Test public void testIsMainPageTitleNoProps() {
String text = "text";
WikiSite wiki = WikiSite.forLanguageCode("test");
final String thumbUrl = null;
final String desc = null;
final PageProperties props = null;
PageTitle subject = new PageTitle(text, wiki, thumbUrl, desc, props);
assertThat(subject.isMainPage(), is(false));
}
@Test public void testIsMainPageProps() {
String text = "text";
WikiSite wiki = WikiSite.forLanguageCode("test");
final String thumbUrl = null;
final String desc = null;
PageProperties props = mock(PageProperties.class);
when(props.isMainPage()).thenReturn(true);
PageTitle subject = new PageTitle(text, wiki, thumbUrl, desc, props);
assertThat(subject.isMainPage(), is(true));
}
/** https://bugzilla.wikimedia.org/66151 */
@Test public void testHashChar() {
PageTitle pageTitle = new PageTitle("#", WikiSite.forLanguageCode("en"));
assertThat(pageTitle.getNamespace(), nullValue());
assertThat(pageTitle.getText(), is(""));
assertThat(pageTitle.getFragment(), is(""));
}
@Test public void testColonChar() {
PageTitle pageTitle = new PageTitle(":", WikiSite.forLanguageCode("en"));
assertThat(pageTitle.getNamespace(), is(""));
assertThat(pageTitle.getText(), is(""));
assertThat(pageTitle.getFragment(), nullValue());
}
}

View file

@ -0,0 +1,30 @@
package org.wikipedia.page;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@RunWith(RobolectricTestRunner.class) public class SectionTest {
@Test public void testSectionLead() {
// Section 0 is the lead
Section section = new Section(0, 0, "Heading", "Heading", "Content");
assertThat(section.isLead(), is(true));
// Section 1 is not
section = new Section(1, 1, "Heading", "Heading", "Content");
assertThat(section.isLead(), is(false));
// Section 1 is not, even if it's somehow at level 0
section = new Section(1, 0, "Heading", "Heading", "Content");
assertThat(section.isLead(), is(false));
}
@Test public void testJSONSerialization() {
Section parentSection = new Section(1, 1, null, null, "Hi there!");
assertThat(parentSection, is(Section.fromJson(parentSection.toJSON())));
}
}

View file

@ -0,0 +1,46 @@
package org.wikipedia.random;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.restbase.page.RbPageSummary;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class RandomSummaryClientTest extends MockRetrofitTest {
@Test
public void testRequestEligible() throws Throwable {
enqueueFromFile("rb_page_summary_valid.json");
TestObserver<RbPageSummary> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(summary -> summary != null
&& summary.getDisplayTitle().equals("Fermat's Last Theorem")
&& summary.getDescription().equals("theorem in number theory"));
}
@Test public void testRequestMalformed() {
enqueueMalformed();
TestObserver<RbPageSummary> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
@Test public void testRequestFailure() {
enqueue404();
TestObserver<RbPageSummary> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
private Observable<RbPageSummary> getObservable() {
return getRestService().getRandomSummary();
}
}

View file

@ -0,0 +1,80 @@
package org.wikipedia.search;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class FullTextSearchClientTest extends MockRetrofitTest {
private static final WikiSite TESTWIKI = new WikiSite("test.wikimedia.org");
private static final int BATCH_SIZE = 20;
private Observable<SearchResults> getObservable() {
return getApiService().fullTextSearch("foo", BATCH_SIZE, null, null)
.map(response -> {
if (response.success()) {
// noinspection ConstantConditions
return new SearchResults(response.query().pages(), TESTWIKI,
response.continuation(), null);
}
return new SearchResults();
});
}
@Test public void testRequestSuccessNoContinuation() throws Throwable {
enqueueFromFile("full_text_search_results.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getResults().get(0).getPageTitle().getDisplayText().equals("IND Queens Boulevard Line"));
}
@Test public void testRequestSuccessWithContinuation() throws Throwable {
enqueueFromFile("full_text_search_results.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getContinuation().get("continue").equals("gsroffset||")
&& result.getContinuation().get("gsroffset").equals("20"));
}
@Test public void testRequestSuccessNoResults() throws Throwable {
enqueueFromFile("full_text_search_results_empty.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getResults().isEmpty());
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
}

View file

@ -0,0 +1,69 @@
package org.wikipedia.search;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.test.MockRetrofitTest;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class PrefixSearchClientTest extends MockRetrofitTest {
private static final WikiSite TESTWIKI = new WikiSite("test.wikimedia.org");
private static final int BATCH_SIZE = 20;
private Observable<SearchResults> getObservable() {
return getApiService().prefixSearch("foo", BATCH_SIZE, "foo")
.map(response -> {
if (response != null && response.success() && response.query().pages() != null) {
// noinspection ConstantConditions
return new SearchResults(response.query().pages(), TESTWIKI, response.continuation(),
response.suggestion());
}
return new SearchResults();
});
}
@Test public void testRequestSuccess() throws Throwable {
enqueueFromFile("prefix_search_results.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getResults().get(0).getPageTitle().getDisplayText().equals("Narthecium"));
}
@Test public void testRequestSuccessNoResults() throws Throwable {
enqueueFromFile("prefix_search_results_empty.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.getResults().isEmpty());
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<SearchResults> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
}

View file

@ -0,0 +1,81 @@
package org.wikipedia.search;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.wikipedia.dataclient.restbase.RbRelatedPages;
import org.wikipedia.dataclient.restbase.page.RbPageSummary;
import org.wikipedia.test.MockRetrofitTest;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
public class RelatedPagesSearchClientTest extends MockRetrofitTest {
private static final String RAW_JSON_FILE = "related_pages_search_results.json";
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testRequestSuccessWithNoLimit() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<List<RbPageSummary>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.size() == 5
&& result.get(4).getThumbnailUrl().equals("https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Vizsla_r%C3%A1h%C3%BAz_a_vadra.jpg/320px-Vizsla_r%C3%A1h%C3%BAz_a_vadra.jpg")
&& result.get(4).getDisplayTitle().equals("Dog intelligence")
&& result.get(4).getDescription() == null);
}
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testRequestSuccessWithLimit() throws Throwable {
enqueueFromFile(RAW_JSON_FILE);
TestObserver<List<RbPageSummary>> observer = new TestObserver<>();
getRestService().getRelatedPages("foo")
.map(response -> response.getPages(3))
.subscribe(observer);
observer.assertComplete().assertNoErrors()
.assertValue(result -> result.size() == 3
&& result.get(0).getThumbnailUrl().equals("https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/European_grey_wolf_in_Prague_zoo.jpg/291px-European_grey_wolf_in_Prague_zoo.jpg")
&& result.get(0).getDisplayTitle().equals("Wolf")
&& result.get(0).getDescription().equals("species of mammal"));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
TestObserver<List<RbPageSummary>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseFailure() {
enqueue404();
TestObserver<List<RbPageSummary>> observer = new TestObserver<>();
getRestService().getRelatedPages("foo")
.map(RbRelatedPages::getPages)
.subscribe(observer);
observer.assertError(Exception.class);
}
@Test public void testRequestResponseMalformed() {
enqueueMalformed();
TestObserver<List<RbPageSummary>> observer = new TestObserver<>();
getObservable().subscribe(observer);
observer.assertError(MalformedJsonException.class);
}
private Observable<List<RbPageSummary>> getObservable() {
return getRestService().getRelatedPages("foo").map(RbRelatedPages::getPages);
}
}

View file

@ -0,0 +1,90 @@
package org.wikipedia.search;
import org.junit.Before;
import org.junit.Test;
import org.wikipedia.dataclient.mwapi.MwQueryResult;
import org.wikipedia.json.GsonUtil;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class SearchResultsRedirectProcessingTest {
private MwQueryResult result;
@Before public void setUp() {
result = GsonUtil.getDefaultGson().fromJson(queryJson, MwQueryResult.class);
}
@Test public void testRedirectHandling() {
assertThat(result.pages().size(), is(2));
assertThat(result.pages().get(0).title(), is("Narthecium#Foo"));
assertThat(result.pages().get(0).redirectFrom(), is("Abama"));
assertThat(result.pages().get(1).title(), is("Amitriptyline"));
assertThat(result.pages().get(1).redirectFrom(), is("Abamax"));
}
@Test public void testConvertTitleHandling() {
assertThat(result.pages().size(), is(2));
assertThat(result.pages().get(0).title(), is("Narthecium#Foo"));
assertThat(result.pages().get(0).convertedFrom(), is("NotNarthecium"));
}
private String queryJson = "{\n"
+ " \"converted\": [\n"
+ " {\n"
+ " \"from\": \"NotNarthecium\",\n"
+ " \"to\": \"Narthecium\"\n"
+ " }\n"
+ " ],\n"
+ " \"redirects\": [\n"
+ " {\n"
+ " \"index\": 1,\n"
+ " \"from\": \"Abama\",\n"
+ " \"to\": \"Narthecium\",\n"
+ " \"tofragment\": \"Foo\"\n"
+ " },\n"
+ " {\n"
+ " \"index\": 2,\n"
+ " \"from\": \"Abamax\",\n"
+ " \"to\": \"Amitriptyline\"\n"
+ " }\n"
+ " ],\n"
+ " \"pages\":[\n"
+ " {\n"
+ " \"pageid\": 2060913,\n"
+ " \"ns\": 0,\n"
+ " \"title\": \"Narthecium\",\n"
+ " \"index\": 1,\n"
+ " \"terms\": {\n"
+ " \"description\": [\n"
+ " \"genus of plants\"\n"
+ " ]\n"
+ " },\n"
+ " \"thumbnail\": {\n"
+ " \"source\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Narthecium_ossifragum_01.jpg/240px-Narthecium_ossifragum_01.jpg\",\n"
+ " \"width\": 240,\n"
+ " \"height\": 320\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"pageid\": 583678,\n"
+ " \"ns\": 0,\n"
+ " \"title\": \"Amitriptyline\",\n"
+ " \"index\": 2,\n"
+ " \"terms\": {\n"
+ " \"description\": [\n"
+ " \"chemical compound\",\n"
+ " \"chemical compound\"\n"
+ " ]\n"
+ " },\n"
+ " \"thumbnail\": {\n"
+ " \"source\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Amitriptyline2DACS.svg/318px-Amitriptyline2DACS.svg.png\",\n"
+ " \"width\": 318,\n"
+ " \"height\": 320\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ " }";
}

View file

@ -0,0 +1,12 @@
package org.wikipedia.test;
import androidx.annotation.NonNull;
import java.util.concurrent.Executor;
public class ImmediateExecutor implements Executor {
@Override
public void execute(@NonNull Runnable runnable) {
runnable.run();
}
}

View file

@ -0,0 +1,34 @@
package org.wikipedia.test;
import androidx.annotation.NonNull;
import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.TimeUnit;
public final class ImmediateExecutorService extends AbstractExecutorService {
@Override public void shutdown() {
throw new UnsupportedOperationException();
}
@NonNull @Override public List<Runnable> shutdownNow() {
throw new UnsupportedOperationException();
}
@Override public boolean isShutdown() {
throw new UnsupportedOperationException();
}
@Override public boolean isTerminated() {
throw new UnsupportedOperationException();
}
@Override public boolean awaitTermination(long l, @NonNull TimeUnit timeUnit)
throws InterruptedException {
throw new UnsupportedOperationException();
}
@Override public void execute(@NonNull Runnable runnable) {
runnable.run();
}
}

View file

@ -0,0 +1,60 @@
package org.wikipedia.test;
import android.net.Uri;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.Before;
import org.wikipedia.dataclient.RestService;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.json.NamespaceTypeAdapter;
import org.wikipedia.json.PostProcessingTypeAdapter;
import org.wikipedia.json.UriTypeAdapter;
import org.wikipedia.json.WikiSiteTypeAdapter;
import org.wikipedia.page.Namespace;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public abstract class MockRetrofitTest extends MockWebServerTest {
private Service apiService;
private RestService restService;
private WikiSite wikiSite = WikiSite.forLanguageCode("en");
protected WikiSite wikiSite() {
return wikiSite;
}
@Override
@Before
public void setUp() throws Throwable {
super.setUp();
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(getGson()))
.baseUrl(server().getUrl())
.build();
apiService = retrofit.create(Service.class);
restService = retrofit.create(RestService.class);
}
protected Service getApiService() {
return apiService;
}
protected RestService getRestService() {
return restService;
}
private Gson getGson() {
return new GsonBuilder()
.registerTypeHierarchyAdapter(Uri.class, new UriTypeAdapter().nullSafe())
.registerTypeHierarchyAdapter(Namespace.class, new NamespaceTypeAdapter().nullSafe())
.registerTypeAdapter(WikiSite.class, new WikiSiteTypeAdapter().nullSafe())
.registerTypeAdapterFactory(new PostProcessingTypeAdapter())
.create();
}
}

View file

@ -0,0 +1,76 @@
package org.wikipedia.test;
import androidx.annotation.NonNull;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.wikipedia.AppAdapter;
import org.wikipedia.TestAppAdapter;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.json.GsonUtil;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import okhttp3.mockwebserver.MockResponse;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@RunWith(RobolectricTestRunner.class)
public abstract class MockWebServerTest {
private OkHttpClient okHttpClient;
private final TestWebServer server = new TestWebServer();
@Before public void setUp() throws Throwable {
AppAdapter.set(new TestAppAdapter());
OkHttpClient.Builder builder = AppAdapter.get().getOkHttpClient(new WikiSite(Service.WIKIPEDIA_URL)).newBuilder();
okHttpClient = builder.dispatcher(new Dispatcher(new ImmediateExecutorService())).build();
server.setUp();
}
@After public void tearDown() throws Throwable {
server.tearDown();
}
@NonNull protected TestWebServer server() {
return server;
}
protected void enqueueFromFile(@NonNull String filename) throws Throwable {
String json = TestFileUtil.readRawFile(filename);
server.enqueue(json);
}
protected void enqueue404() {
final int code = 404;
server.enqueue(new MockResponse().setResponseCode(code).setBody("Not Found"));
}
protected void enqueueMalformed() {
server.enqueue("(╯°□°)╯︵ ┻━┻");
}
protected void enqueueEmptyJson() {
server.enqueue(new MockResponse().setBody("{}"));
}
@NonNull protected OkHttpClient okHttpClient() {
return okHttpClient;
}
@NonNull protected <T> T service(Class<T> clazz) {
return service(clazz, server().getUrl());
}
@NonNull protected <T> T service(Class<T> clazz, @NonNull String url) {
return new Retrofit.Builder()
.baseUrl(url)
.callbackExecutor(new ImmediateExecutor())
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(GsonUtil.getDefaultGson()))
.build()
.create(clazz);
}
}

View file

@ -0,0 +1,40 @@
package org.wikipedia.test;
import android.annotation.TargetApi;
import androidx.annotation.NonNull;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
public final class TestFileUtil {
private static final String RAW_DIR = "src/test/res/raw/";
public static File getRawFile(@NonNull String rawFileName) {
return new File(RAW_DIR + rawFileName);
}
public static String readRawFile(String basename) throws IOException {
return readFile(getRawFile(basename));
}
@TargetApi(19)
private static String readFile(File file) throws IOException {
return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
@TargetApi(19)
public static String readStream(InputStream stream) throws IOException {
StringWriter writer = new StringWriter();
IOUtils.copy(stream, writer, StandardCharsets.UTF_8);
return writer.toString();
}
private TestFileUtil() { }
}

View file

@ -0,0 +1,35 @@
package org.wikipedia.test;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public final class TestParcelUtil {
/** @param parcelable Must implement hashCode and equals */
public static void test(Parcelable parcelable) throws Throwable {
Parcel parcel = parcel(parcelable);
parcel.setDataPosition(0);
Parcelable unparceled = unparcel(parcel, parcelable.getClass());
assertThat(parcelable, is(unparceled));
}
@NonNull private static Parcelable unparcel(@NonNull Parcel parcel,
Class<? extends Parcelable> clazz) throws Throwable {
Parcelable.Creator<?> creator = (Parcelable.Creator<?>) clazz.getField("CREATOR").get(null);
return (Parcelable) creator.createFromParcel(parcel);
}
@NonNull private static Parcel parcel(@NonNull Parcelable parcelable) {
Parcel parcel = Parcel.obtain();
parcelable.writeToParcel(parcel, 0);
return parcel;
}
private TestParcelUtil() { }
}

View file

@ -0,0 +1,56 @@
package org.wikipedia.test;
import androidx.annotation.NonNull;
import org.wikipedia.TestConstants;
import java.io.IOException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
public class TestWebServer {
private final MockWebServer server;
public TestWebServer() {
server = new MockWebServer();
}
public void setUp() throws IOException {
server.start();
}
public void tearDown() throws IOException {
server.shutdown();
}
public String getUrl() {
return getUrl("");
}
public String getUrl(String path) {
return server.url(path).url().toString();
}
public int getRequestCount() {
return server.getRequestCount();
}
public void enqueue(@NonNull String body) {
enqueue(new MockResponse().setBody(body));
}
public void enqueue(MockResponse response) {
server.enqueue(response);
}
@NonNull public RecordedRequest takeRequest() throws InterruptedException {
RecordedRequest req = server.takeRequest(TestConstants.TIMEOUT_DURATION,
TestConstants.TIMEOUT_UNIT);
if (req == null) {
throw new InterruptedException("Timeout elapsed.");
}
return req;
}
}

View file

@ -0,0 +1,28 @@
package org.wikipedia.util;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(RobolectricTestRunner.class)
public class DateUtilTest {
private static final String HTTP_DATE_HEADER = "Thu, 25 May 2017 21:13:47 GMT";
@Test
public void testGetHttpLastModifiedDate() throws Throwable {
assertThat(DateUtil.getExtraShortDateString(DateUtil.getHttpLastModifiedDate(HTTP_DATE_HEADER)), is("May 25"));
}
@Test
public void testIso8601DateFormat() throws Throwable {
assertThat(DateUtil.iso8601DateFormat(DateUtil.getHttpLastModifiedDate(HTTP_DATE_HEADER)), is("2017-05-25T21:13:47Z"));
}
@Test
public void testIso8601Identity() throws Throwable {
assertThat(DateUtil.iso8601DateFormat(DateUtil.iso8601DateParse("2017-05-25T21:13:47Z")), is("2017-05-25T21:13:47Z"));
}
}

View file

@ -0,0 +1,47 @@
package org.wikipedia.util;
import android.net.Uri;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(RobolectricTestRunner.class)
public class ImageUriUtilTest {
private static final int IMAGE_SIZE_1280 = 1280;
private static final int IMAGE_SIZE_200 = 200;
private static final String IMAGE_URL_200 = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/PaeoniaSuffruticosa7.jpg/200px-PaeoniaSuffruticosa7.jpg";
private static final String IMAGE_URL_320 = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/PaeoniaSuffruticosa7.jpg/320px-PaeoniaSuffruticosa7.jpg";
private static final String IMAGE_URL_1280 = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/PaeoniaSuffruticosa7.jpg/1280px-PaeoniaSuffruticosa7.jpg";
private static final String IMAGE_URL_WITH_NUMERIC_NAME_320 = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Paeonia_californica_2320679478.jpg/320px-Paeonia_californica_2320679478.jpg";
private static final String IMAGE_URL_WITH_NUMERIC_NAME_1280 = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Paeonia_californica_2320679478.jpg/1280px-Paeonia_californica_2320679478.jpg";
@Test
public void testUrlForSizeURI() {
Uri uri = Uri.parse(IMAGE_URL_320);
assertThat(ImageUrlUtil.getUrlForSize(uri, IMAGE_SIZE_1280).toString(), is(IMAGE_URL_320));
}
@Test
public void testUrlForSizeStringWithLargeSize() {
assertThat(ImageUrlUtil.getUrlForSize(IMAGE_URL_320, IMAGE_SIZE_1280), is(IMAGE_URL_320));
}
@Test
public void testUrlForSizeStringWithSmallSize() {
assertThat(ImageUrlUtil.getUrlForSize(IMAGE_URL_320, IMAGE_SIZE_200), is(IMAGE_URL_200));
}
@Test
public void testUrlForPreferredSizeWithRegularName() {
assertThat(ImageUrlUtil.getUrlForPreferredSize(IMAGE_URL_320, IMAGE_SIZE_1280), is(IMAGE_URL_1280));
}
@Test
public void testUrlForPreferredSizeWithNumericName() {
assertThat(ImageUrlUtil.getUrlForPreferredSize(IMAGE_URL_WITH_NUMERIC_NAME_320, IMAGE_SIZE_1280), is(IMAGE_URL_WITH_NUMERIC_NAME_1280));
}
}

View file

@ -0,0 +1,99 @@
package org.wikipedia.util;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(RobolectricTestRunner.class)
public class StringUtilTest {
@Test
@SuppressWarnings("checkstyle:magicnumber")
public void testGetBase26String() {
assertThat(StringUtil.getBase26String(1), is("A"));
assertThat(StringUtil.getBase26String(26), is("Z"));
assertThat(StringUtil.getBase26String(277), is("JQ"));
assertThat(StringUtil.getBase26String(2777), is("DBU"));
assertThat(StringUtil.getBase26String(27000), is("AMXL"));
assertThat(StringUtil.getBase26String(52), is("AZ"));
assertThat(StringUtil.getBase26String(53), is("BA"));
}
@Test
public void testListToCsv() {
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
assertThat(StringUtil.listToCsv(stringList), is("one,two"));
}
@Test
public void testCsvToList() {
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
assertThat(StringUtil.csvToList("one,two"), is(stringList));
}
@Test
public void testDelimiterStringToList() {
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
assertThat(StringUtil.delimiterStringToList("one,two", ","), is(stringList));
}
@Test
public void testMd5string() {
assertThat(StringUtil.md5string("test"), is("98f6bcd4621d373cade4e832627b4f6"));
}
@Test
public void testStrip() {
assertThat(StringUtil.strip("test"), is("test"));
assertThat(StringUtil.strip(" test "), is("test"));
}
@Test
public void testIntToHexStr() {
assertThat(StringUtil.intToHexStr(1), is("x00000001"));
}
@Test
public void testAddUnderscores() {
assertThat(StringUtil.addUnderscores("te st"), is("te_st"));
}
@Test
public void testRemoveUnderscores() {
assertThat(StringUtil.removeUnderscores("te_st"), is("te st"));
}
@Test
public void testHasSectionAnchor() {
assertThat(StringUtil.hasSectionAnchor("te_st"), is(false));
assertThat(StringUtil.hasSectionAnchor("#te_st"), is(true));
}
@Test
public void testRemoveSectionAnchor() {
assertThat(StringUtil.removeSectionAnchor("#te_st"), is(""));
assertThat(StringUtil.removeSectionAnchor("sec#te_st"), is("sec"));
}
@Test
public void testRemoveHTMLTags() {
assertThat(StringUtil.removeHTMLTags("<tag>te_st</tag>"), is("te_st"));
}
@Test
public void testSanitizeText() {
assertThat(StringUtil.sanitizeText(" [1] test"), is("test"));
assertThat(StringUtil.sanitizeText(" [1] (;test )"), is("(test )"));
}
}

View file

@ -0,0 +1,37 @@
package org.wikipedia.util;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class UriUtilTest {
/**
* Inspired by
* curl -s https://en.wikipedia.org/w/api.php?action=query&meta=siteinfo&format=json&siprop=general | jq .query.general.legaltitlechars
*/
private static final String TITLE
= " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+";
/**
* Inspired by
*from http://stackoverflow.com/questions/2849756/list-of-valid-characters-for-the-fragment-identifier-in-an-url
*/
private static final String LEGAL_FRAGMENT_CHARS
= "!$&'()*+,;=-._~:@/?abc0123456789%D8%f6";
@Test
public void testRemoveFragment() {
assertThat(UriUtil.removeFragment(TITLE + "#" + LEGAL_FRAGMENT_CHARS), is(TITLE));
}
@Test
public void testRemoveEmptyFragment() {
assertThat(UriUtil.removeFragment(TITLE + "#"), is(TITLE));
}
@Test
public void testRemoveFragmentWithHash() {
assertThat(UriUtil.removeFragment(TITLE + "##"), is(TITLE));
}
}