diff --git a/libraries/apollo-api/api/apollo-api.api b/libraries/apollo-api/api/apollo-api.api index 7fbd6ba3782..02e56a1089f 100644 --- a/libraries/apollo-api/api/apollo-api.api +++ b/libraries/apollo-api/api/apollo-api.api @@ -786,6 +786,11 @@ public final class com/apollographql/apollo3/api/Operations { public static final fun parseJsonResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Lcom/apollographql/apollo3/api/ApolloResponse; public static final fun parseJsonResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/util/Set;)Lcom/apollographql/apollo3/api/ApolloResponse; public static synthetic fun parseJsonResponse$default (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/util/Set;ILjava/lang/Object;)Lcom/apollographql/apollo3/api/ApolloResponse; + public static final fun parseResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;)Lcom/apollographql/apollo3/api/ApolloResponse; + public static final fun parseResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Ljava/util/UUID;)Lcom/apollographql/apollo3/api/ApolloResponse; + public static final fun parseResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Ljava/util/UUID;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Lcom/apollographql/apollo3/api/ApolloResponse; + public static final fun parseResponse (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Ljava/util/UUID;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/util/Set;)Lcom/apollographql/apollo3/api/ApolloResponse; + public static synthetic fun parseResponse$default (Lcom/apollographql/apollo3/api/Operation;Lcom/apollographql/apollo3/api/json/JsonReader;Ljava/util/UUID;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/util/Set;ILjava/lang/Object;)Lcom/apollographql/apollo3/api/ApolloResponse; } public abstract class com/apollographql/apollo3/api/Optional { diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt index c2cef4ded56..eb1eeda6f79 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Assertions.kt @@ -1,10 +1,7 @@ @file:JvmName("Assertions") package com.apollographql.apollo3.api -import com.apollographql.apollo3.exception.ApolloException import com.apollographql.apollo3.exception.DefaultApolloException -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract import kotlin.jvm.JvmName /** @@ -12,6 +9,6 @@ import kotlin.jvm.JvmName */ fun checkFieldNotMissing(value: Any?, name: String) { if (value == null) { - throw DefaultApolloException("Field $name is missing") + throw DefaultApolloException("Field '$name' is missing") } } diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Operations.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Operations.kt index 5079167452a..d05bab1abc7 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Operations.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/Operations.kt @@ -6,11 +6,13 @@ import com.apollographql.apollo3.annotations.ApolloExperimental import com.apollographql.apollo3.api.internal.ResponseParser import com.apollographql.apollo3.api.json.JsonReader import com.apollographql.apollo3.api.json.JsonWriter -import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.json.writeObject +import com.apollographql.apollo3.exception.ApolloException +import com.apollographql.apollo3.exception.ApolloParseException import com.apollographql.apollo3.exception.JsonDataException import com.apollographql.apollo3.exception.JsonEncodingException -import okio.Buffer +import com.benasher44.uuid.Uuid +import com.benasher44.uuid.uuid4 import okio.IOException import okio.use import kotlin.jvm.JvmName @@ -46,7 +48,8 @@ fun Operation.composeJsonRequest( } /** - * Reads a GraphQL Json response like below to a [ApolloResponse] + * Reads a GraphQL Json response to a [ApolloResponse]. GraphQL Json responses look like so: + * * ``` * { * "data": ... @@ -62,26 +65,65 @@ fun Operation.composeJsonRequest( * @throws JsonDataException if the data is not of the expected type */ @JvmOverloads +@Deprecated("Use parseResponse or jsonReader.toApolloResponse() instead", ReplaceWith("parseResponse")) fun Operation.parseJsonResponse( jsonReader: JsonReader, customScalarAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty, deferredFragmentIdentifiers: Set? = null, ): ApolloResponse { - return ResponseParser.parse( - jsonReader, - this, - customScalarAdapters, - deferredFragmentIdentifiers, - ) + return jsonReader.use { + ResponseParser.parse( + it, + this, + null, + customScalarAdapters, + deferredFragmentIdentifiers, + ) + } } +/** + * Reads a GraphQL Json response like below to a [ApolloResponse]. GraphQL Json responses look like so: + * + * ``` + * { + * "data": ... + * "errors": ... + * "extensions": ... + * } + * ``` + * + * By default, this method does not close the [jsonReader] + */ @JvmOverloads -@ApolloExperimental -fun Operation.parseJsonResponse( - json: String, +fun Operation.parseResponse( + jsonReader: JsonReader, + requestUuid: Uuid? = null, customScalarAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty, + deferredFragmentIdentifiers: Set? = null, ): ApolloResponse { - return parseJsonResponse(Buffer().writeUtf8(json).jsonReader(), customScalarAdapters) + return try { + ResponseParser.parse( + jsonReader, + this, + requestUuid, + customScalarAdapters, + deferredFragmentIdentifiers, + ) + } catch (throwable: Throwable) { + val apolloException = if (throwable is ApolloException) { + throwable + } else { + // This happens for null pointer exceptions on missing fields + ApolloParseException( + message = "Failed to parse GraphQL http network response", + cause = throwable + ) + } + return ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = this, exception = apolloException) + .isLast(true) + .build() + } } /** @@ -103,3 +145,16 @@ fun Operation.composeJsonResponse( } } + +@ApolloExperimental +fun JsonReader.toApolloResponse( + operation: Operation, + requestUuid: Uuid? = null, + customScalarAdapters: CustomScalarAdapters = CustomScalarAdapters.Empty, + deferredFragmentIdentifiers: Set? = null, +): ApolloResponse { + return use { + operation.parseResponse(it, requestUuid, customScalarAdapters, deferredFragmentIdentifiers) + } +} + diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt index b1fc352ae09..8d14a3cdc68 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/internal/ResponseParser.kt @@ -9,10 +9,9 @@ import com.apollographql.apollo3.api.falseVariables import com.apollographql.apollo3.api.json.JsonReader import com.apollographql.apollo3.api.json.MapJsonReader import com.apollographql.apollo3.api.json.readAny -import com.apollographql.apollo3.api.nullable import com.apollographql.apollo3.api.parseData +import com.benasher44.uuid.Uuid import com.benasher44.uuid.uuid4 -import okio.use /** * [ResponseParser] parses network responses, including data, errors and extensions from a [JsonReader] @@ -21,33 +20,31 @@ internal object ResponseParser { fun parse( jsonReader: JsonReader, operation: Operation, + requestUuid: Uuid?, customScalarAdapters: CustomScalarAdapters, deferredFragmentIds: Set?, ): ApolloResponse { - @Suppress("NAME_SHADOWING") - return jsonReader.use { jsonReader -> - jsonReader.beginObject() - - var data: D? = null - var errors: List? = null - var extensions: Map? = null - while (jsonReader.hasNext()) { - @Suppress("UNCHECKED_CAST") - when (jsonReader.nextName()) { - "data" -> { - val falseVariables = operation.falseVariables(customScalarAdapters) - data = operation.parseData(jsonReader, customScalarAdapters, falseVariables, deferredFragmentIds) - } - "errors" -> errors = jsonReader.readErrors() - "extensions" -> extensions = jsonReader.readAny() as? Map - else -> jsonReader.skipValue() + jsonReader.beginObject() + + var data: D? = null + var errors: List? = null + var extensions: Map? = null + while (jsonReader.hasNext()) { + @Suppress("UNCHECKED_CAST") + when (jsonReader.nextName()) { + "data" -> { + val falseVariables = operation.falseVariables(customScalarAdapters) + data = operation.parseData(jsonReader, customScalarAdapters, falseVariables, deferredFragmentIds) } + "errors" -> errors = jsonReader.readErrors() + "extensions" -> extensions = jsonReader.readAny() as? Map + else -> jsonReader.skipValue() } + } - jsonReader.endObject() + jsonReader.endObject() - ApolloResponse.Builder(requestUuid = uuid4(), operation = operation, data = data, errors = errors, extensions = extensions).build() - } + return ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = operation, data = data, errors = errors, extensions = extensions).build() } fun parseError( diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java index 43201d61511..f646acaeb7c 100644 --- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java +++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/http/HttpNetworkTransport.java @@ -62,13 +62,9 @@ public void execute(@NotNull ApolloRequest request } } else { BufferedSourceJsonReader jsonReader = new BufferedSourceJsonReader(response.getBody()); - try { - CustomScalarAdapters customScalarAdapters = request.getExecutionContext().get(CustomScalarAdapters.Key); - ApolloResponse apolloResponse = Operations.parseJsonResponse(request.getOperation(), jsonReader, customScalarAdapters); - callback.onResponse(apolloResponse); - } catch (Exception e) { - callback.onResponse(getExceptionResponse(request, new ApolloParseException("Cannot parse response", e))); - } + CustomScalarAdapters customScalarAdapters = request.getExecutionContext().get(CustomScalarAdapters.Key); + ApolloResponse apolloResponse = Operations.toApolloResponse(jsonReader, request.getOperation(), request.getRequestUuid(), customScalarAdapters, null); + callback.onResponse(apolloResponse); } } diff --git a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java index 16610ad13ca..b09528b23fd 100644 --- a/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java +++ b/libraries/apollo-runtime-java/src/main/java/com/apollographql/apollo3/runtime/java/network/ws/WebSocketNetworkTransport.java @@ -141,7 +141,7 @@ private void disposeSubscription(String id) { CustomScalarAdapters customScalarAdapters = request.getExecutionContext().get(CustomScalarAdapters.Key); JsonReader jsonReader = new MapJsonReader(payload); //noinspection rawtypes - ApolloResponse apolloResponse = Operations.parseJsonResponse(request.getOperation(), jsonReader, customScalarAdapters).newBuilder().requestUuid(request.getRequestUuid()).build(); + ApolloResponse apolloResponse = Operations.toApolloResponse(jsonReader, request.getOperation(), request.getRequestUuid(), customScalarAdapters, null); //noinspection unchecked subscriptionInfo.callback.onResponse(apolloResponse); } diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt index ef22e0eef06..0aa90046b30 100644 --- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt +++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/http/HttpNetworkTransport.kt @@ -13,7 +13,7 @@ import com.apollographql.apollo3.api.http.HttpResponse import com.apollographql.apollo3.api.json.JsonReader import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.json.readAny -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.exception.ApolloException import com.apollographql.apollo3.exception.ApolloHttpException import com.apollographql.apollo3.exception.ApolloParseException @@ -26,7 +26,6 @@ import com.apollographql.apollo3.network.NetworkTransport import com.benasher44.uuid.Uuid import com.benasher44.uuid.uuid4 import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf @@ -138,15 +137,11 @@ private constructor( customScalarAdapters: CustomScalarAdapters, httpResponse: HttpResponse, ): Flow> { - val response = try { - operation.parseJsonResponse( - jsonReader = httpResponse.body!!.jsonReader(), - customScalarAdapters = customScalarAdapters, - deferredFragmentIdentifiers = null, - ) - } catch (e: Exception) { - errorResponse(operation, e) - } + val response = httpResponse.body!!.jsonReader().toApolloResponse( + operation, + customScalarAdapters = customScalarAdapters, + deferredFragmentIdentifiers = null, + ) return flowOf(response.newBuilder().isLast(true).build()) } @@ -194,11 +189,10 @@ private constructor( reader.beginObject() reader.nextName() - // TODO: make parseJsonResponse not close the jsonReader - operation.parseJsonResponse( - jsonReader = reader, + reader.toApolloResponse( + operation = operation, customScalarAdapters = customScalarAdapters, - deferredFragmentIdentifiers = null, + deferredFragmentIdentifiers = null ) } @@ -220,15 +214,13 @@ private constructor( if (jsonMerger!!.isEmptyPayload) { null } else { - operation.parseJsonResponse( - jsonReader = merged.jsonReader(), + merged.jsonReader().toApolloResponse( + operation = operation, customScalarAdapters = customScalarAdapters, - deferredFragmentIdentifiers = deferredFragmentIds, + deferredFragmentIdentifiers = deferredFragmentIds ).newBuilder().isLast(isLast).build() } } - }.catch { - emit(errorResponse(operation, it)) } } diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt index 24cde7668d7..1d4e8862459 100644 --- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt +++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/WebSocketNetworkTransport.kt @@ -6,7 +6,7 @@ import com.apollographql.apollo3.api.CustomScalarAdapters import com.apollographql.apollo3.api.Operation import com.apollographql.apollo3.api.http.HttpHeader import com.apollographql.apollo3.api.json.jsonReader -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.exception.ApolloException import com.apollographql.apollo3.exception.ApolloNetworkException import com.apollographql.apollo3.exception.SubscriptionOperationException @@ -311,11 +311,13 @@ private constructor( } else { responsePayload to null } - val apolloResponse: ApolloResponse = request.operation - .parseJsonResponse(jsonReader = payload.jsonReader(), customScalarAdapters = requestCustomScalarAdapters, deferredFragmentIdentifiers = mergedFragmentIds) - .newBuilder() - .requestUuid(request.requestUuid) - .build() + val apolloResponse: ApolloResponse = payload.jsonReader().toApolloResponse( + operation = request.operation, + requestUuid = request.requestUuid, + customScalarAdapters = requestCustomScalarAdapters, + deferredFragmentIdentifiers = mergedFragmentIds + ) + if (!deferredJsonMerger.hasNext) { // Last deferred payload: reset the deferredJsonMerger for potential subsequent responses deferredJsonMerger.reset() diff --git a/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt b/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt index 04b0e4f4740..003767df3ec 100644 --- a/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt +++ b/tests/include-skip-operation-based/src/test/kotlin/IncludeTest.kt @@ -1,10 +1,11 @@ + import com.apollographql.apollo3.api.ApolloResponse import com.apollographql.apollo3.api.CustomScalarAdapters import com.apollographql.apollo3.api.GlobalBuilder import com.apollographql.apollo3.api.Operation import com.apollographql.apollo3.api.Optional import com.apollographql.apollo3.api.json.MapJsonReader -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.cache.normalized.api.TypePolicyCacheKeyGenerator import com.apollographql.apollo3.cache.normalized.api.normalize import com.example.GetCatIncludeFalseQuery @@ -27,7 +28,7 @@ import kotlin.test.assertNull class IncludeTest { private fun Operation.parseData(data: Map): ApolloResponse { - return parseJsonResponse(MapJsonReader(mapOf("data" to data))) + return MapJsonReader(mapOf("data" to data)).toApolloResponse(this) } @Test diff --git a/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/NormalizerTest.kt b/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/NormalizerTest.kt index 2672f751ef3..223a5e4b0aa 100644 --- a/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/NormalizerTest.kt +++ b/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/NormalizerTest.kt @@ -4,6 +4,7 @@ import IdCacheKeyGenerator import com.apollographql.apollo3.api.CustomScalarAdapters import com.apollographql.apollo3.api.Operation import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.cache.normalized.api.CacheHeaders import com.apollographql.apollo3.cache.normalized.api.CacheKey import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory @@ -248,7 +249,7 @@ class NormalizerTest { companion object { internal fun records(operation: Operation, name: String): Map { - val response = operation.parseJsonResponse(testFixtureToJsonReader(name)) + val response = testFixtureToJsonReader(name).toApolloResponse(operation) return operation.normalize(data = response.data!!, CustomScalarAdapters.Empty, cacheKeyGenerator = IdCacheKeyGenerator) } diff --git a/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt b/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt index af6be143138..229ec8f3c00 100644 --- a/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt +++ b/tests/integration-tests/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt @@ -6,9 +6,10 @@ import com.apollographql.apollo3.api.CustomScalarAdapters import com.apollographql.apollo3.api.fromJson import com.apollographql.apollo3.api.json.MapJsonReader import com.apollographql.apollo3.api.json.jsonReader -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.api.toJsonString import com.apollographql.apollo3.exception.ApolloException +import com.apollographql.apollo3.exception.DefaultApolloException import com.apollographql.apollo3.integration.httpcache.AllFilmsQuery import com.apollographql.apollo3.integration.httpcache.AllPlanetsQuery import com.apollographql.apollo3.integration.httpcache.type.Date @@ -23,6 +24,7 @@ import testFixtureToJsonReader import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse +import kotlin.test.assertIs import kotlin.test.assertNull import kotlin.test.assertTrue @@ -34,7 +36,7 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun errorsAreProperlyRead() { - val response = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("ResponseError.json")) + val response = testFixtureToJsonReader("ResponseError.json").toApolloResponse(operation = AllPlanetsQuery()) assertTrue(response.hasErrors()) val errors = response.errors assertEquals2(errors?.get(0)?.message, "Cannot query field \"names\" on type \"Species\".") @@ -52,7 +54,7 @@ class ParseResponseBodyTest { * If I'm reading the spec right, passing null in location/path/extensions is most likely * an error, but we are lenient there and allow it */ - val response = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("ResponseErrorWithNulls.json")) + val response = testFixtureToJsonReader("ResponseErrorWithNulls.json").toApolloResponse(operation = AllPlanetsQuery()) assertTrue(response.hasErrors()) assertEquals(response.errors?.size, 1) assertEquals(response.errors!![0].message, "Response with nulls") @@ -67,7 +69,7 @@ class ParseResponseBodyTest { /** * location, path and extensions are all optional */ - val response = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("ResponseErrorWithAbsent.json")) + val response = testFixtureToJsonReader("ResponseErrorWithAbsent.json").toApolloResponse(operation = AllPlanetsQuery()) assertTrue(response.hasErrors()) assertEquals(response.errors?.size, 1) assertEquals(response.errors!![0].message, "Response with absent") @@ -84,7 +86,7 @@ class ParseResponseBodyTest { * Extensions are mapped to Kotlin types. * Big numbers should throw although this is not tested here */ - val response = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("ResponseErrorWithExtensions.json")) + val response = testFixtureToJsonReader("ResponseErrorWithExtensions.json").toApolloResponse(operation = AllPlanetsQuery()) assertTrue(response.hasErrors()) assertEquals(response.errors!![0].extensions?.size, 4) assertEquals(response.errors!![0].extensions?.get("code"), 500) @@ -101,7 +103,7 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun errorWithNonStandardFields() { - val response = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("ResponseErrorWithNonStandardFields.json")) + val response = testFixtureToJsonReader("ResponseErrorWithNonStandardFields.json").toApolloResponse(operation = AllPlanetsQuery()) assertTrue(response.hasErrors()) val nonStandardFields = response.errors!![0].nonStandardFields!! assertEquals(3, nonStandardFields.size) @@ -125,7 +127,7 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun errorResponse_with_data() { - val response = EpisodeHeroNameQuery(Episode.JEDI).parseJsonResponse(testFixtureToJsonReader("ResponseErrorWithData.json")) + val response = testFixtureToJsonReader("ResponseErrorWithData.json").toApolloResponse(operation = EpisodeHeroNameQuery(Episode.JEDI)) val data = response.data val errors = response.errors assertTrue(data != null) @@ -142,10 +144,7 @@ class ParseResponseBodyTest { @Throws(Exception::class) fun allFilmsWithDate() { - val response = AllFilmsQuery().parseJsonResponse( - testFixtureToJsonReader("HttpCacheTestAllFilms.json"), - CustomScalarAdapters.Builder().add(Date.type, KotlinxLocalDateAdapter).build() - ) + val response = testFixtureToJsonReader("HttpCacheTestAllFilms.json").toApolloResponse(operation = AllFilmsQuery(), customScalarAdapters = CustomScalarAdapters.Builder().add(Date.type, KotlinxLocalDateAdapter).build()) assertFalse(response.hasErrors()) assertEquals(response.data!!.allFilms?.films?.size, 6) assertEquals( @@ -157,7 +156,7 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun dataNull() { - val response = HeroNameQuery().parseJsonResponse(testFixtureToJsonReader("ResponseDataNull.json")) + val response = testFixtureToJsonReader("ResponseDataNull.json").toApolloResponse(operation = HeroNameQuery()) assertTrue(response.data == null) assertFalse(response.hasErrors()) } @@ -165,20 +164,21 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun fieldMissing() { - try { - HeroNameQuery().parseJsonResponse(testFixtureToJsonReader("ResponseDataMissing.json")) - error("an error was expected") - } catch (e: NullPointerException) { - // This is the Kotlin codegen case - } catch (e: ApolloException) { + val exception = testFixtureToJsonReader("ResponseDataMissing.json").toApolloResponse(operation = HeroNameQuery()).exception + if (exception is DefaultApolloException) { // This is the (better) Java codegen case + assertTrue(exception.message?.contains("Field 'name' is missing") == true) + } else { + // Kotlin codegen case + assertIs(exception) + assertIs(exception.cause) } } @Test @Throws(Exception::class) fun operationResponseParser() { - val data = HeroNameQuery().parseJsonResponse(testFixtureToJsonReader("HeroNameResponse.json")).data + val data = testFixtureToJsonReader("HeroNameResponse.json").toApolloResponse(operation = HeroNameQuery()).data assertEquals(data!!.hero?.name, "R2-D2") } @@ -186,7 +186,7 @@ class ParseResponseBodyTest { @Throws(Exception::class) fun parseSuccessOperationRawResponse() { val query = AllPlanetsQuery() - val response = query.parseJsonResponse(testFixtureToJsonReader("AllPlanetsNullableField.json")) + val response = testFixtureToJsonReader("AllPlanetsNullableField.json").toApolloResponse(operation = query) assertEquals(response.operation, query) assertFalse(response.hasErrors()) assertTrue(response.data != null) @@ -196,10 +196,7 @@ class ParseResponseBodyTest { @Test @Throws(Exception::class) fun parseErrorOperationRawResponse() { - val response = EpisodeHeroNameQuery(Episode.EMPIRE).parseJsonResponse( - testFixtureToJsonReader("/ResponseErrorWithData.json"), - CustomScalarAdapters.Empty - ) + val response = testFixtureToJsonReader("/ResponseErrorWithData.json").toApolloResponse(operation = EpisodeHeroNameQuery(Episode.EMPIRE), customScalarAdapters = CustomScalarAdapters.Empty) val data = response.data val errors = response.errors @@ -216,7 +213,7 @@ class ParseResponseBodyTest { @Throws(Exception::class) fun extensionsAreReadFromResponse() { val query = HeroNameQuery() - val extensions = query.parseJsonResponse(testFixtureToJsonReader("HeroNameResponse.json")).extensions + val extensions = testFixtureToJsonReader("HeroNameResponse.json").toApolloResponse(operation = query).extensions assertEquals( extensions, mapOf( diff --git a/tests/js/src/jsTest/kotlin/JsTest.kt b/tests/js/src/jsTest/kotlin/JsTest.kt index d7e6c5d99f6..30496e200f3 100644 --- a/tests/js/src/jsTest/kotlin/JsTest.kt +++ b/tests/js/src/jsTest/kotlin/JsTest.kt @@ -1,5 +1,5 @@ import com.apollographql.apollo3.api.json.DynamicJsJsonReader -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import js.test.CreateCustomerMutation import js.test.GetSalesPeopleQuery import kotlin.test.Test @@ -28,7 +28,7 @@ class JsTest { """.trimIndent()) as dynamic val query = GetSalesPeopleQuery() val jsonReader = DynamicJsJsonReader(dynamicResponse) - val response = query.parseJsonResponse(jsonReader) + val response = jsonReader.toApolloResponse(operation = query) assertEquals( GetSalesPeopleQuery.Data( getSalesPeople = listOf( diff --git a/tests/models-operation-based-with-interfaces/src/test/kotlin/test/ParseResponseBodyTest.kt b/tests/models-operation-based-with-interfaces/src/test/kotlin/test/ParseResponseBodyTest.kt index c6cafb828c5..321cfcc1ab6 100644 --- a/tests/models-operation-based-with-interfaces/src/test/kotlin/test/ParseResponseBodyTest.kt +++ b/tests/models-operation-based-with-interfaces/src/test/kotlin/test/ParseResponseBodyTest.kt @@ -6,6 +6,7 @@ import com.apollographql.apollo3.api.json.buildJsonString import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.json.readAny import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import okio.Buffer import testFixtureToJsonReader import testFixtureToUtf8 @@ -18,7 +19,7 @@ class ParseResponseBodyTest { */ @Test fun allPlanetQuery() { - val data = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("AllPlanets.json")).data + val data = testFixtureToJsonReader("AllPlanets.json").toApolloResponse(operation = AllPlanetsQuery()).data assertEquals(data!!.allPlanets?.planets?.size, 60) val planets = data.allPlanets?.planets?.mapNotNull { @@ -48,7 +49,7 @@ class ParseResponseBodyTest { val expected = testFixtureToUtf8("OperationJsonWriter.json") val query = AllPlanetsQuery() - val data = query.parseJsonResponse(Buffer().writeUtf8(expected).jsonReader()).data + val data = Buffer().writeUtf8(expected).jsonReader().toApolloResponse(operation = query).data val actual = buildJsonString(indent = " ") { query.composeJsonResponse(this, data!!) } diff --git a/tests/models-operation-based/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt b/tests/models-operation-based/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt index c6cafb828c5..6daf36bcb2d 100644 --- a/tests/models-operation-based/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt +++ b/tests/models-operation-based/src/kotlinCodegenTest/kotlin/test/ParseResponseBodyTest.kt @@ -5,7 +5,7 @@ import com.apollographql.apollo3.api.composeJsonResponse import com.apollographql.apollo3.api.json.buildJsonString import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.json.readAny -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import okio.Buffer import testFixtureToJsonReader import testFixtureToUtf8 @@ -18,7 +18,7 @@ class ParseResponseBodyTest { */ @Test fun allPlanetQuery() { - val data = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("AllPlanets.json")).data + val data = testFixtureToJsonReader("AllPlanets.json").toApolloResponse(operation = AllPlanetsQuery()).data assertEquals(data!!.allPlanets?.planets?.size, 60) val planets = data.allPlanets?.planets?.mapNotNull { @@ -48,7 +48,7 @@ class ParseResponseBodyTest { val expected = testFixtureToUtf8("OperationJsonWriter.json") val query = AllPlanetsQuery() - val data = query.parseJsonResponse(Buffer().writeUtf8(expected).jsonReader()).data + val data = Buffer().writeUtf8(expected).jsonReader().toApolloResponse(operation = query).data val actual = buildJsonString(indent = " ") { query.composeJsonResponse(this, data!!) } diff --git a/tests/models-response-based/src/commonTest/kotlin/test/ParseResponseBodyTest.kt b/tests/models-response-based/src/commonTest/kotlin/test/ParseResponseBodyTest.kt index 6b701c8e7a5..a845ab5e6e9 100644 --- a/tests/models-response-based/src/commonTest/kotlin/test/ParseResponseBodyTest.kt +++ b/tests/models-response-based/src/commonTest/kotlin/test/ParseResponseBodyTest.kt @@ -9,6 +9,7 @@ import com.apollographql.apollo3.api.composeJsonResponse import com.apollographql.apollo3.api.json.buildJsonString import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.mpp.Platform import com.apollographql.apollo3.mpp.platform import okio.Buffer @@ -23,7 +24,7 @@ class ParseResponseBodyTest { */ @Test fun allPlanetQuery() { - val data = AllPlanetsQuery().parseJsonResponse(testFixtureToJsonReader("AllPlanets.json")).data + val data = testFixtureToJsonReader("AllPlanets.json").toApolloResponse(operation = AllPlanetsQuery()).data assertEquals(data!!.allPlanets?.planets?.size, 60) val planets = data.allPlanets?.planets?.mapNotNull { @@ -52,7 +53,7 @@ class ParseResponseBodyTest { fun operationJsonWriter() { val expected = testFixtureToUtf8("OperationJsonWriter.json") val query = AllPlanetsQuery() - val data = query.parseJsonResponse(Buffer().writeUtf8(expected).jsonReader()).data + val data = Buffer().writeUtf8(expected).jsonReader().toApolloResponse(operation = query).data val actual = buildJsonString(indent = " ") { query.composeJsonResponse(this, data!!) } diff --git a/tests/no-runtime/src/test/kotlin/test/NoRuntimeTest.kt b/tests/no-runtime/src/test/kotlin/test/NoRuntimeTest.kt index 54da89ebf52..5170840e680 100644 --- a/tests/no-runtime/src/test/kotlin/test/NoRuntimeTest.kt +++ b/tests/no-runtime/src/test/kotlin/test/NoRuntimeTest.kt @@ -5,7 +5,7 @@ import com.apollographql.apollo3.annotations.ApolloInternal import com.apollographql.apollo3.api.composeJsonRequest import com.apollographql.apollo3.api.json.BufferedSinkJsonWriter import com.apollographql.apollo3.api.json.BufferedSourceJsonReader -import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.example.GetRandomQuery import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient @@ -59,7 +59,7 @@ class NoRuntimeTest { assertTrue(response.body != null) val apolloResponse = response.body?.use { - query.parseJsonResponse(BufferedSourceJsonReader(it.source())) + BufferedSourceJsonReader(it.source()).toApolloResponse(operation = query) } assertEquals(42, apolloResponse?.data?.random) diff --git a/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt b/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt index 2ab2c597c1b..929743c613c 100644 --- a/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt +++ b/tests/normalization-tests/src/test/kotlin/com/example/NormalizationTest.kt @@ -6,6 +6,7 @@ import com.apollographql.apollo3.api.CustomScalarAdapters import com.apollographql.apollo3.api.Executable import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import com.apollographql.apollo3.cache.normalized.ApolloStore import com.apollographql.apollo3.cache.normalized.api.CacheKey import com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator @@ -48,7 +49,7 @@ class NormalizationTest { val query = Issue3672Query() - val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse).jsonReader(), CustomScalarAdapters.Empty).dataOrThrow() + val data1 = Buffer().writeUtf8(nestedResponse).jsonReader().toApolloResponse(operation = query, customScalarAdapters = CustomScalarAdapters.Empty).dataOrThrow() store.writeOperation(query, data1) val data2 = store.readOperation(query) @@ -65,7 +66,7 @@ class NormalizationTest { val query = NestedFragmentQuery() - val data1 = query.parseJsonResponse(Buffer().writeUtf8(nestedResponse_list).jsonReader(), CustomScalarAdapters.Empty).dataOrThrow() + val data1 = Buffer().writeUtf8(nestedResponse_list).jsonReader().toApolloResponse(operation = query, customScalarAdapters = CustomScalarAdapters.Empty).dataOrThrow() store.writeOperation(query, data1) val data2 = store.readOperation(query) diff --git a/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt b/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt index d11e660ecd7..e48c245d540 100644 --- a/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt +++ b/tests/outofbounds/src/test/kotlin/test/OutOfBoundsTest.kt @@ -2,6 +2,7 @@ package test import com.apollographql.apollo3.api.json.jsonReader import com.apollographql.apollo3.api.parseJsonResponse +import com.apollographql.apollo3.api.toApolloResponse import okio.buffer import okio.source import org.junit.Test @@ -11,6 +12,6 @@ import java.io.File class OutOfBoundsTest { @Test fun checkOutOfBounds() { - GetAnimalQuery().parseJsonResponse(File("src/main/json/response.json").source().buffer().jsonReader()).dataOrThrow() + File("src/main/json/response.json").source().buffer().jsonReader().toApolloResponse(operation = GetAnimalQuery()).dataOrThrow() } } \ No newline at end of file