package com.apollographql.apollo;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.apollographql.android.impl.httpcache.AllFilms;
import com.apollographql.android.impl.httpcache.AllPlanets;
import com.apollographql.android.impl.httpcache.type.CustomType;
import com.apollographql.android.impl.normalizer.HeroName;
import com.apollographql.apollo.api.Error;
import com.apollographql.apollo.api.Response;
import com.apollographql.apollo.exception.ApolloException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import okhttp3.OkHttpClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import static com.google.common.truth.Truth.assertThat;
public class IntegrationTest {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
private ApolloClient apolloClient;
private CustomTypeAdapter<Date> dateCustomTypeAdapter;
private static final long TIME_OUT_SECONDS = 3;
@Rule public final MockWebServer server = new MockWebServer();
@Before public void setUp() {
dateCustomTypeAdapter = new CustomTypeAdapter<Date>() {
@Override public Date decode(String value) {
try {
return DATE_FORMAT.parse(value);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Override public String encode(Date value) {
return DATE_FORMAT.format(value);
}
};
apolloClient = ApolloClient.builder()
.serverUrl(server.url("/"))
.okHttpClient(new OkHttpClient.Builder().build())
.addCustomTypeAdapter(CustomType.DATE, dateCustomTypeAdapter)
.build();
}
@After public void tearDown() {
try {
server.shutdown();
} catch (IOException ignored) {
}
}
@SuppressWarnings("ConstantConditions") @Test public void allPlanetQuery() throws Exception {
server.enqueue(mockResponse("HttpCacheTestAllPlanets.json"));
Response<AllPlanets.Data> body = apolloClient.query(new AllPlanets()).execute();
assertThat(body.hasErrors()).isFalse();
assertThat(server.takeRequest().getBody().readString(Charsets.UTF_8))
.isEqualTo("{\"query\":\"query AllPlanets { "
+ "allPlanets(first: 300) {"
+ " __typename"
+ " planets {"
+ " __typename"
+ " ...PlanetFragment"
+ " filmConnection {"
+ " __typename"
+ " totalCount"
+ " films {"
+ " __typename"
+ " title"
+ " ...FilmFragment"
+ " }"
+ " }"
+ " }"
+ " }"
+ "}"
+ "fragment FilmFragment on Film {"
+ " __typename"
+ " title"
+ " producers"
+ "}"
+ "fragment PlanetFragment on Planet {"
+ " __typename"
+ " name"
+ " climates"
+ " surfaceWater"
+ "}\",\"variables\":{}}");
AllPlanets.Data data = body.data();
assertThat(data.allPlanets().planets().size()).isEqualTo(60);
List<String> planets = FluentIterable.from(data.allPlanets().planets())
.transform(new Function<AllPlanets.Planet, String>() {
@Override public String apply(AllPlanets.Planet planet) {
return planet.fragments().planetFragment().name();
}
}).toList();
assertThat(planets).isEqualTo(Arrays.asList(("Tatooine, Alderaan, Yavin IV, Hoth, Dagobah, Bespin, Endor, Naboo, "
+ "Coruscant, Kamino, Geonosis, Utapau, Mustafar, Kashyyyk, Polis Massa, Mygeeto, Felucia, Cato Neimoidia, "
+ "Saleucami, Stewjon, Eriadu, Corellia, Rodia, Nal Hutta, Dantooine, Bestine IV, Ord Mantell, unknown, "
+ "Trandosha, Socorro, Mon Cala, Chandrila, Sullust, Toydaria, Malastare, Dathomir, Ryloth, Aleen Minor, "
+ "Vulpter, Troiken, Tund, Haruun Kal, Cerea, Glee Anselm, Iridonia, Tholoth, Iktotch, Quermia, Dorin, "
+ "Champala, Mirial, Serenno, Concord Dawn, Zolan, Ojom, Skako, Muunilinst, Shili, Kalee, Umbara")
.split("\\s*,\\s*")
));
AllPlanets.Planet firstPlanet = data.allPlanets().planets().get(0);
assertThat(firstPlanet.fragments().planetFragment().climates()).isEqualTo(Collections.singletonList("arid"));
assertThat(firstPlanet.fragments().planetFragment().surfaceWater()).isWithin(1d);
assertThat(firstPlanet.filmConnection().totalCount()).isEqualTo(5);
assertThat(firstPlanet.filmConnection().films().size()).isEqualTo(5);
assertThat(firstPlanet.filmConnection().films().get(0).fragments().filmFragment().title()).isEqualTo("A New Hope");
assertThat(firstPlanet.filmConnection().films().get(0).fragments().filmFragment().producers()).isEqualTo(Arrays
.asList("Gary Kurtz", "Rick McCallum"));
}
@Test public void errorResponse() throws Exception {
server.enqueue(mockResponse("ResponseError.json"));
Response<AllPlanets.Data> body = apolloClient.query(new AllPlanets()).execute();
assertThat(body.hasErrors()).isTrue();
//noinspection ConstantConditions
assertThat(body.errors()).containsExactly(new Error(
"Cannot query field \"names\" on type \"Species\".",
Collections.singletonList(new Error.Location(3, 5))));
}
@Test public void allFilmsWithDate() throws Exception {
server.enqueue(mockResponse("HttpCacheTestAllFilms.json"));
Response<AllFilms.Data> body = apolloClient.query(new AllFilms()).execute();
assertThat(body.hasErrors()).isFalse();
AllFilms.Data data = body.data();
assertThat(data.allFilms().films()).hasSize(6);
List<String> dates = FluentIterable.from(data.allFilms().films())
.transform(new Function<AllFilms.Film, String>() {
@Override public String apply(AllFilms.Film film) {
Date releaseDate = film.releaseDate();
return dateCustomTypeAdapter.encode(releaseDate);
}
}).copyInto(new ArrayList<String>());
assertThat(dates).isEqualTo(Arrays.asList("1977-05-25", "1980-05-17", "1983-05-25", "1999-05-19", "2002-05-16",
"2005-05-19"));
}
@Test public void allPlanetQueryAsync() throws Exception {
server.enqueue(mockResponse("HttpCacheTestAllPlanets.json"));
final NamedCountDownLatch latch = new NamedCountDownLatch("latch", 1);
apolloClient.query(new AllPlanets()).enqueue(new ApolloCall.Callback<AllPlanets.Data>() {
@Override public void onResponse(@Nonnull Response<AllPlanets.Data> response) {
assertThat(response.hasErrors()).isFalse();
assertThat(response.data().allPlanets().planets().size()).isEqualTo(60);
latch.countDown();
}
@Override public void onFailure(@Nonnull ApolloException e) {
latch.countDown();
Assert.fail("expected success");
}
});
latch.awaitOrThrowWithTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS);
}
@Test(expected = ApolloException.class) public void dataEmpty() throws Exception {
MockResponse mockResponse = mockResponse("ResponseDataEmpty.json");
server.enqueue(mockResponse);
ApolloCall<HeroName.Data> call = apolloClient.query(new HeroName());
call.execute();
}
@Test public void dataNull() throws Exception {
MockResponse mockResponse = mockResponse("ResponseDataNull.json");
server.enqueue(mockResponse);
ApolloCall<HeroName.Data> call = apolloClient.query(new HeroName());
Response<HeroName.Data> body = call.execute();
assertThat(body.data()).isNull();
assertThat(body.hasErrors()).isFalse();
}
@Test(expected = ApolloException.class) public void fieldMissing() throws Exception {
MockResponse mockResponse = mockResponse("ResponseDataMissing.json");
server.enqueue(mockResponse);
ApolloCall<HeroName.Data> call = apolloClient.query(new HeroName());
call.execute();
}
private MockResponse mockResponse(String fileName) throws IOException {
return new MockResponse().setChunkedBody(Utils.readFileToString(getClass(), "/" + fileName), 32);
}
}