package org.wikipedia.nearby;
import android.support.annotation.NonNull;
import com.google.gson.stream.MalformedJsonException;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
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.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 NearbyClientTest extends MockWebServerTest {
@NonNull private final NearbyClient subject = new NearbyClient();
@Test public void testRequestSuccessHasResults() throws Throwable {
enqueueFromFile("nearby.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
assertCallbackSuccess(call, cb);
}
@Test public void testRequestNoResults() throws Throwable {
enqueueFromFile("nearby_empty.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
request(cb);
server().takeRequest();
// If no results are found we don't call success() or failure() but just do nothing;
// here, just make sure we're not hitting an error.
// noinspection unchecked
verify(cb, never()).failure(any(Call.class), any(Throwable.class));
}
@Test public void testLocationMissingCoordsIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_coords.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
ArgumentCaptor<NearbyResult> captor = ArgumentCaptor.forClass(NearbyResult.class);
verify(cb).success(eq(call), captor.capture());
NearbyResult result = captor.getValue();
assertThat(result.getList().size(), is(0));
}
@Test public void testLocationMissingLatOnlyIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_lat.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
ArgumentCaptor<NearbyResult> captor = ArgumentCaptor.forClass(NearbyResult.class);
verify(cb).success(eq(call), captor.capture());
NearbyResult result = captor.getValue();
assertThat(result.getList().size(), is(0));
}
@Test public void testLocationMissingLonOnlyIsExcludedFromResults() throws Throwable {
enqueueFromFile("nearby_missing_lon.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
ArgumentCaptor<NearbyResult> captor = ArgumentCaptor.forClass(NearbyResult.class);
verify(cb).success(eq(call), captor.capture());
NearbyResult result = captor.getValue();
assertThat(result.getList().size(), is(0));
}
@Test public void testRequestResponseApiError() throws Throwable {
enqueueFromFile("api_error.json");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
assertCallbackFailure(call, cb, MwException.class);
}
@Test public void testRequestResponseFailure() throws Throwable {
enqueue404();
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
assertCallbackFailure(call, cb, HttpStatusException.class);
}
@Test public void testRequestResponseMalformed() throws Throwable {
server().enqueue("(✿ ♥‿♥)");
NearbyClient.Callback cb = mock(NearbyClient.Callback.class);
Call<MwQueryResponse<Nearby>> call = request(cb);
server().takeRequest();
assertCallbackFailure(call, cb, MalformedJsonException.class);
}
private void assertCallbackSuccess(@NonNull Call<MwQueryResponse<Nearby>> call,
@NonNull NearbyClient.Callback cb) {
// Location objects contained in the NearbyPage members of the Nearby results will have
// unique timestamps assigned on creation that cause direct comparison of the NearbyResults
// to fail. So, let's just check to ensure that we have a valid NearbyResult.
verify(cb).success(eq(call), any(NearbyResult.class));
//noinspection unchecked
verify(cb, never()).failure(any(Call.class), any(Throwable.class));
}
private void assertCallbackFailure(@NonNull Call<MwQueryResponse<Nearby>> call,
@NonNull NearbyClient.Callback cb,
@NonNull Class<? extends Throwable> throwable) {
//noinspection unchecked
verify(cb, never()).success(any(Call.class), any(NearbyResult.class));
verify(cb).failure(eq(call), isA(throwable));
}
private Call<MwQueryResponse<Nearby>> request(@NonNull NearbyClient.Callback cb) {
return subject.request(WikiSite.forLanguageCode("test"),
service(NearbyClient.Service.class), 0, 0, 0, cb);
}
}