diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractDirectTransport.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractDirectTransport.java index da972660..a0b29e3f 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractDirectTransport.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/AbstractDirectTransport.java @@ -25,6 +25,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.RequestOutput; import org.springframework.graphql.client.GraphQlTransport; import org.springframework.test.util.AssertionErrors; @@ -45,22 +46,23 @@ abstract class AbstractDirectTransport implements GraphQlTransport { @Override - public Mono execute(GraphQlRequest request) { - return executeInternal(request).cast(ExecutionResult.class); + public Mono execute(GraphQlRequest request) { + return executeInternal(request).cast(GraphQlResponse.class); } @SuppressWarnings({"ConstantConditions", "unchecked"}) @Override - public Flux executeSubscription(GraphQlRequest request) { - return executeInternal(request).flatMapMany(result -> { + public Flux executeSubscription(GraphQlRequest request) { + return executeInternal(request).flatMapMany(output -> { try { - Object data = result.getData(); + Object data = output.getData(); AssertionErrors.assertTrue("Not a Publisher: " + data, data instanceof Publisher); - List errors = result.getErrors(); + List errors = output.getErrors(); AssertionErrors.assertTrue("Subscription errors: " + errors, CollectionUtils.isEmpty(errors)); - return Flux.from((Publisher) data); + return Flux.from((Publisher) data) + .map(result -> new RequestOutput(output.getExecutionInput(), result)); } catch (AssertionError ex) { throw new AssertionError(ex.getMessage() + "\nRequest: " + request, ex); diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java index 8349d6e3..1628b1ae 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java @@ -31,12 +31,12 @@ import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.TypeRef; -import graphql.ExecutionResult; import graphql.GraphQLError; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.client.GraphQlTransport; import org.springframework.graphql.support.DocumentSource; import org.springframework.lang.Nullable; @@ -165,7 +165,7 @@ final class DefaultGraphQlTester implements GraphQlTester { @SuppressWarnings("ConstantConditions") @Override public Response execute() { - return transport.execute(request()).map(result -> response(result, request())).block(responseTimeout); + return transport.execute(request()).map(response -> mapResponse(response, request())).block(responseTimeout); } @Override @@ -175,15 +175,15 @@ final class DefaultGraphQlTester implements GraphQlTester { @Override public Subscription executeSubscription() { - return () -> transport.executeSubscription(request()).map(result -> response(result, request())); + return () -> transport.executeSubscription(request()).map(result -> mapResponse(result, request())); } private GraphQlRequest request() { return new GraphQlRequest(this.document, this.operationName, this.variables); } - private DefaultResponse response(ExecutionResult result, GraphQlRequest request) { - return new DefaultResponse(result, errorFilter, assertDecorator(request), jsonPathConfig); + private DefaultResponse mapResponse(GraphQlResponse response, GraphQlRequest request) { + return new DefaultResponse(response, errorFilter, assertDecorator(request), jsonPathConfig); } private Consumer assertDecorator(GraphQlRequest request) { @@ -217,12 +217,12 @@ final class DefaultGraphQlTester implements GraphQlTester { private ResponseDelegate( - ExecutionResult result, @Nullable Predicate errorFilter, + GraphQlResponse response, @Nullable Predicate errorFilter, Consumer assertDecorator, Configuration jsonPathConfig) { - this.jsonDoc = JsonPath.parse(result.toSpecification(), jsonPathConfig); + this.jsonDoc = JsonPath.parse(response.toMap(), jsonPathConfig); this.jsonContent = this.jsonDoc::jsonString; - this.errors = result.getErrors(); + this.errors = response.getErrors(); this.unexpectedErrors = new ArrayList<>(this.errors); this.assertDecorator = assertDecorator; @@ -293,10 +293,10 @@ final class DefaultGraphQlTester implements GraphQlTester { private final ResponseDelegate delegate; private DefaultResponse( - ExecutionResult result, @Nullable Predicate errorFilter, + GraphQlResponse response, @Nullable Predicate errorFilter, Consumer assertDecorator, Configuration jsonPathConfig) { - this.delegate = new ResponseDelegate(result, errorFilter, assertDecorator, jsonPathConfig); + this.delegate = new ResponseDelegate(response, errorFilter, assertDecorator, jsonPathConfig); } @Override diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTester.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTester.java index a388897d..045a5f6c 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTester.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultWebSocketGraphQlTester.java @@ -20,11 +20,11 @@ package org.springframework.graphql.test.tester; import java.net.URI; import java.util.function.Consumer; -import graphql.ExecutionResult; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.client.CodecMappingProvider; import org.springframework.graphql.client.GraphQlClient; import org.springframework.graphql.client.GraphQlTransport; @@ -164,7 +164,7 @@ final class DefaultWebSocketGraphQlTester extends AbstractDelegatingGraphQlTeste return new GraphQlTransport() { @Override - public Mono execute(GraphQlRequest request) { + public Mono execute(GraphQlRequest request) { return client .document(request.getDocument()) .operationName(request.getOperationName()) @@ -174,7 +174,7 @@ final class DefaultWebSocketGraphQlTester extends AbstractDelegatingGraphQlTeste } @Override - public Flux executeSubscription(GraphQlRequest request) { + public Flux executeSubscription(GraphQlRequest request) { return client .document(request.getDocument()) .operationName(request.getOperationName()) diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebTestClientTransport.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebTestClientTransport.java index b16218d4..6e188e76 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebTestClientTransport.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebTestClientTransport.java @@ -19,14 +19,14 @@ package org.springframework.graphql.test.tester; import java.util.Collections; import java.util.Map; -import graphql.ExecutionResult; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.client.GraphQlTransport; -import org.springframework.graphql.support.MapExecutionResult; +import org.springframework.graphql.support.MapGraphQlResponse; import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.util.Assert; @@ -53,9 +53,9 @@ final class WebTestClientTransport implements GraphQlTransport { @Override - public Mono execute(GraphQlRequest request) { + public Mono execute(GraphQlRequest request) { - Map resultMap = this.webTestClient.post() + Map responseMap = this.webTestClient.post() .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .bodyValue(request.toMap()) @@ -66,13 +66,13 @@ final class WebTestClientTransport implements GraphQlTransport { .returnResult() .getResponseBody(); - resultMap = (resultMap != null ? resultMap : Collections.emptyMap()); - ExecutionResult result = MapExecutionResult.from(resultMap); - return Mono.just(result); + responseMap = (responseMap != null ? responseMap : Collections.emptyMap()); + GraphQlResponse response = MapGraphQlResponse.forResponse(responseMap); + return Mono.just(response); } @Override - public Flux executeSubscription(GraphQlRequest request) { + public Flux executeSubscription(GraphQlRequest request) { throw new UnsupportedOperationException("Subscriptions not supported over HTTP"); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/GraphQlResponse.java b/spring-graphql/src/main/java/org/springframework/graphql/GraphQlResponse.java new file mode 100644 index 00000000..19a1a5b8 --- /dev/null +++ b/spring-graphql/src/main/java/org/springframework/graphql/GraphQlResponse.java @@ -0,0 +1,77 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.graphql; + + +import java.util.List; +import java.util.Map; + +import graphql.GraphQLError; + +import org.springframework.lang.Nullable; + +/** + * Represents a GraphQL response with the result of executing a request operation. + * + * @author Rossen Stoyanchev + * @since 1.0.0 + */ +public interface GraphQlResponse { + + /** + * Whether the response is valid. A response is invalid in one of the + * following two cases: + *
    + *
  • the {@link #toMap() response map} has no "data" entry indicating + * errors before execution, e.g. grammar parse and validation + *
  • the "data" entry has a {@code null} value indicating errors during + * execution that prevented a valid response + *
+ *

A valid response has a "data" key with a {@code non-null} value, but + * it may still be partial and have some fields set to {@code null} due to + * field errors. + *

For more details, see section 7 "Response" in the GraphQL spec. + */ + boolean isValid(); + + /** + * Return the data part of the response, or {@code null} when the response + * is not {@link #isValid() valid}. + * @param a map or a list + */ + @Nullable + T getData(); + + /** + * Return errors for the response. This contains "request errors" when the + * response is not {@link #isValid() valid} and/or "field errors" for a + * partial response. + */ + List getErrors(); + + /** + * Return implementor specific, protocol extensions, if any. + */ + Map getExtensions(); + + /** + * Return a map representation of the response, formatted as required in the + * "Response" section of the GraphQL spec. + */ + Map toMap(); + +} diff --git a/spring-graphql/src/main/java/org/springframework/graphql/RequestOutput.java b/spring-graphql/src/main/java/org/springframework/graphql/RequestOutput.java index 8b58ef2b..e8680a64 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/RequestOutput.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/RequestOutput.java @@ -15,6 +15,7 @@ */ package org.springframework.graphql; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -26,29 +27,37 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Wraps an {@link ExecutionResult} and also exposes the {@link ExecutionInput} - * prepared for the request. + * {@link GraphQlResponse} for server use that wraps the {@link ExecutionResult} + * returned from {@link graphql.GraphQL} and also exposes the actual + * {@link ExecutionInput} instance passed into it. * * @author Rossen Stoyanchev * @since 1.0.0 */ -public class RequestOutput implements ExecutionResult { +public class RequestOutput implements GraphQlResponse { - private final ExecutionInput executionInput; + private final ExecutionInput input; - private final ExecutionResult executionResult; + private final ExecutionResult result; /** - * Create an instance. - * @param executionInput the input prepared for the request - * @param executionResult the result from performing the request + * Constructor to create initial instance. */ - public RequestOutput(ExecutionInput executionInput, ExecutionResult executionResult) { - Assert.notNull(executionInput, "ExecutionInput is required."); - Assert.notNull(executionResult, "ExecutionResult is required."); - this.executionInput = executionInput; - this.executionResult = executionResult; + public RequestOutput(ExecutionInput input, ExecutionResult result) { + Assert.notNull(input, "ExecutionInput is required."); + Assert.notNull(result, "ExecutionResult is required."); + this.input = input; + this.result = result; + } + + /** + * Constructor to re-wrap from transport specific subclass. + */ + protected RequestOutput(RequestOutput requestOutput) { + Assert.notNull(requestOutput, "RequestOutput is required."); + this.input = requestOutput.getExecutionInput(); + this.result = requestOutput.result; } @@ -57,37 +66,40 @@ public class RequestOutput implements ExecutionResult { * {@link RequestInput} and passed to {@link graphql.GraphQL}. */ public ExecutionInput getExecutionInput() { - return this.executionInput; + return this.input; + } + + protected ExecutionResult getExecutionResult() { + return this.result; + } + + @Override + public boolean isValid() { + return (this.result.isDataPresent() && this.result.getData() != null); } @Nullable @Override public T getData() { - return this.executionResult.getData(); - } - - @Override - public boolean isDataPresent() { - return this.executionResult.isDataPresent(); + return this.result.getData(); } public List getErrors() { - return this.executionResult.getErrors(); + return this.result.getErrors(); } - @Nullable public Map getExtensions() { - return this.executionResult.getExtensions(); + return (this.result.getExtensions() != null ? this.result.getExtensions() : Collections.emptyMap()); } @Override - public Map toSpecification() { - return this.executionResult.toSpecification(); + public Map toMap() { + return this.result.toSpecification(); } @Override public String toString() { - return this.executionResult.toString(); + return this.result.toString(); } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java b/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java index b45de9b8..8e5238af 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/AbstractGraphQlClientBuilder.java @@ -116,7 +116,7 @@ public abstract class AbstractGraphQlClientBuilder errors; - private DefaultResponse(ExecutionResult result, Configuration jsonPathConfig) { - this.result = result; - this.jsonPathDoc = JsonPath.parse(result.toSpecification(), jsonPathConfig); - this.errors = result.getErrors(); + private DefaultResponse(GraphQlResponse response, Configuration jsonPathConfig) { + this.response = response; + this.jsonPathDoc = JsonPath.parse(response.toMap(), jsonPathConfig); + this.errors = response.getErrors(); } @Override @@ -226,8 +226,8 @@ final class DefaultGraphQlClient implements GraphQlClient { } @Override - public ExecutionResult andReturn() { - return this.result; + public GraphQlResponse andReturn() { + return this.response; } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlClient.java b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlClient.java index 8d042d0b..5fba9a3b 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlClient.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlClient.java @@ -18,12 +18,12 @@ package org.springframework.graphql.client; import java.util.List; import java.util.Map; -import graphql.ExecutionResult; import graphql.GraphQLError; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.support.DocumentSource; import org.springframework.graphql.support.ResourceDocumentSource; import org.springframework.lang.Nullable; @@ -218,9 +218,9 @@ public interface GraphQlClient { List errors(); /** - * Return the underlying {@link ExecutionResult} for the response. + * Return the underlying {@link GraphQlResponse}. */ - ExecutionResult andReturn(); + GraphQlResponse andReturn(); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java index ee24f6ae..fe053ea5 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java @@ -16,11 +16,11 @@ package org.springframework.graphql.client; -import graphql.ExecutionResult; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; /** @@ -34,16 +34,16 @@ public interface GraphQlTransport { /** * Execute a request with a single response such as a "query" or "mutation". * @param request the request to execute - * @return a {@code Mono} with the {@code ExecutionResult} for the response. + * @return a {@code Mono} with the {@code GraphQlResponse} for the response. * The {@code Mono} may end wth an error due to transport or other issues * such as failures to encode the request or decode the response. */ - Mono execute(GraphQlRequest request); + Mono execute(GraphQlRequest request); /** * Execute a "subscription" request with a stream of responses. * @param request the request to execute - * @return a {@code Flux} of {@code ExecutionResult} responses. + * @return a {@code Flux} of {@code GraphQlResponse} responses. * The {@code Flux} may terminate as follows: *

    *
  • Completes if the subscription completes before the connection is closed. @@ -55,6 +55,6 @@ public interface GraphQlTransport { *

    The {@code Flux} may be cancelled to notify the server to end the * subscription stream. */ - Flux executeSubscription(GraphQlRequest request); + Flux executeSubscription(GraphQlRequest request); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java index 3d0ccfd8..c4ff834a 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java @@ -18,13 +18,13 @@ package org.springframework.graphql.client; import java.util.Map; -import graphql.ExecutionResult; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; import org.springframework.graphql.GraphQlRequest; -import org.springframework.graphql.support.MapExecutionResult; +import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.support.MapGraphQlResponse; import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.web.reactive.function.client.WebClient; @@ -54,18 +54,18 @@ final class HttpGraphQlTransport implements GraphQlTransport { @Override - public Mono execute(GraphQlRequest request) { + public Mono execute(GraphQlRequest request) { return this.webClient.post() .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .bodyValue(request.toMap()) .retrieve() .bodyToMono(MAP_TYPE) - .map(MapExecutionResult::from); + .map(MapGraphQlResponse::forResponse); } @Override - public Flux executeSubscription(GraphQlRequest request) { + public Flux executeSubscription(GraphQlRequest request) { throw new UnsupportedOperationException("Subscriptions not supported over HTTP"); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java index 89251664..e20a634f 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java @@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; -import graphql.ExecutionResult; import graphql.GraphQLError; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -34,8 +33,9 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import org.springframework.graphql.GraphQlRequest; -import org.springframework.graphql.support.MapExecutionResult; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.support.MapGraphQlError; +import org.springframework.graphql.support.MapGraphQlResponse; import org.springframework.graphql.web.support.GraphQlMessage; import org.springframework.graphql.web.support.GraphQlMessageType; import org.springframework.http.HttpHeaders; @@ -145,12 +145,12 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { } @Override - public Mono execute(GraphQlRequest request) { + public Mono execute(GraphQlRequest request) { return this.graphQlSessionMono.flatMap(session -> session.execute(request)); } @Override - public Flux executeSubscription(GraphQlRequest request) { + public Flux executeSubscription(GraphQlRequest request) { return this.graphQlSessionMono.flatMapMany(session -> session.executeSubscription(request)); } @@ -372,9 +372,9 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { private final Sinks.Many requestSink = Sinks.many().unicast().onBackpressureBuffer(); - private final Map> resultSinks = new ConcurrentHashMap<>(); + private final Map> responseSinks = new ConcurrentHashMap<>(); - private final Map> streamingSinks = new ConcurrentHashMap<>(); + private final Map> streamSinks = new ConcurrentHashMap<>(); GraphQlSession(WebSocketSession webSocketSession) { @@ -389,32 +389,32 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { return this.requestSink.asFlux(); } - public Mono execute(GraphQlRequest request) { + public Mono execute(GraphQlRequest request) { String id = String.valueOf(this.requestIndex.incrementAndGet()); try { GraphQlMessage message = GraphQlMessage.subscribe(id, request); - Sinks.One sink = Sinks.one(); - this.resultSinks.put(id, sink); + Sinks.One sink = Sinks.one(); + this.responseSinks.put(id, sink); trySend(message); - return sink.asMono().doOnCancel(() -> this.resultSinks.remove(id)); + return sink.asMono().doOnCancel(() -> this.responseSinks.remove(id)); } catch (Exception ex) { - this.resultSinks.remove(id); + this.responseSinks.remove(id); return Mono.error(ex); } } - public Flux executeSubscription(GraphQlRequest request) { + public Flux executeSubscription(GraphQlRequest request) { String id = String.valueOf(this.requestIndex.incrementAndGet()); try { GraphQlMessage message = GraphQlMessage.subscribe(id, request); - Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer(); - this.streamingSinks.put(id, sink); + Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer(); + this.streamSinks.put(id, sink); trySend(message); return sink.asFlux().doOnCancel(() -> cancelStream(id)); } catch (Exception ex) { - this.streamingSinks.remove(id); + this.streamSinks.remove(id); return Flux.error(ex); } } @@ -438,7 +438,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { } private void cancelStream(String id) { - Sinks.Many streamSink = this.streamingSinks.remove(id); + Sinks.Many streamSink = this.streamSinks.remove(id); if (streamSink != null) { try { trySend(GraphQlMessage.complete(id)); @@ -458,8 +458,8 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { */ public void handleNext(GraphQlMessage message) { String id = message.getId(); - Sinks.One sink = this.resultSinks.remove(id); - Sinks.Many streamingSink = this.streamingSinks.get(id); + Sinks.One sink = this.responseSinks.remove(id); + Sinks.Many streamingSink = this.streamSinks.get(id); if (sink == null && streamingSink == null) { if (logger.isDebugEnabled()) { @@ -468,10 +468,10 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { return; } - Map resultMap = message.getPayload(); - ExecutionResult result = MapExecutionResult.from(resultMap); + Map responseMap = message.getPayload(); + GraphQlResponse response = MapGraphQlResponse.forResponse(responseMap); - Sinks.EmitResult emitResult = (sink != null ? sink.tryEmitValue(result) : streamingSink.tryEmitNext(result)); + Sinks.EmitResult emitResult = (sink != null ? sink.tryEmitValue(response) : streamingSink.tryEmitNext(response)); if (emitResult.isFailure()) { // Just log: cannot overflow, is serialized, and cancel is handled in doOnCancel if (logger.isDebugEnabled()) { @@ -481,13 +481,13 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { } /** - * Handle an "error" message, turning it into an {@link ExecutionResult} - * for a single result response, or signaling an error to streams. + * Handle an "error" message, turning it into an {@link GraphQlResponse} + * for single responses, or signaling an error for streams. */ public void handleError(GraphQlMessage message) { String id = message.getId(); - Sinks.One sink = this.resultSinks.remove(id); - Sinks.Many streamingSink = this.streamingSinks.remove(id); + Sinks.One sink = this.responseSinks.remove(id); + Sinks.Many streamingSink = this.streamSinks.remove(id); if (sink == null && streamingSink == null ) { if (logger.isDebugEnabled()) { @@ -500,8 +500,8 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { Sinks.EmitResult emitResult; if (sink != null) { - ExecutionResult result = MapExecutionResult.forErrorsOnly(payload); - emitResult = sink.tryEmitValue(result); + GraphQlResponse response = MapGraphQlResponse.forErrorsOnly(payload); + emitResult = sink.tryEmitValue(response); } else { List graphQLErrors = MapGraphQlError.from(payload); @@ -518,14 +518,14 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { * Handle a "complete" message. */ public void handleComplete(GraphQlMessage message) { - Sinks.One resultSink = this.resultSinks.remove(message.getId()); - Sinks.Many streamingResultSink = this.streamingSinks.remove(message.getId()); + Sinks.One sink = this.responseSinks.remove(message.getId()); + Sinks.Many streamSink = this.streamSinks.remove(message.getId()); - if (resultSink != null) { - resultSink.tryEmitEmpty(); + if (sink != null) { + sink.tryEmitEmpty(); } - else if (streamingResultSink != null) { - streamingResultSink.tryEmitComplete(); + else if (streamSink != null) { + streamSink.tryEmitComplete(); } } @@ -548,10 +548,10 @@ final class WebSocketGraphQlTransport implements GraphQlTransport { * Terminate and clean all in-progress requests with the given error. */ public void terminateRequests(Exception ex) { - this.resultSinks.values().forEach(sink -> sink.tryEmitError(ex)); - this.streamingSinks.values().forEach(sink -> sink.tryEmitError(ex)); - this.resultSinks.clear(); - this.streamingSinks.clear(); + this.responseSinks.values().forEach(sink -> sink.tryEmitError(ex)); + this.streamSinks.values().forEach(sink -> sink.tryEmitError(ex)); + this.responseSinks.clear(); + this.streamSinks.clear(); } @Override diff --git a/spring-graphql/src/main/java/org/springframework/graphql/support/MapExecutionResult.java b/spring-graphql/src/main/java/org/springframework/graphql/support/MapGraphQlResponse.java similarity index 68% rename from spring-graphql/src/main/java/org/springframework/graphql/support/MapExecutionResult.java rename to spring-graphql/src/main/java/org/springframework/graphql/support/MapGraphQlResponse.java index fdf7b5d6..7454e720 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/support/MapExecutionResult.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/support/MapGraphQlResponse.java @@ -21,18 +21,18 @@ import java.util.List; import java.util.Map; import graphql.ExecutionResult; -import graphql.ExecutionResultImpl; import graphql.GraphQLError; +import org.springframework.graphql.GraphQlResponse; import org.springframework.util.Assert; /** - * Implementation of {@link ExecutionResult} backed by a {@link Map}. + * {@link GraphQlResponse} for client use that wraps the GraphQL response map. * * @author Rossen Stoyanchev * @since 1.0.0 */ -public final class MapExecutionResult implements ExecutionResult { +public final class MapGraphQlResponse implements GraphQlResponse { private final Map resultMap; @@ -40,13 +40,18 @@ public final class MapExecutionResult implements ExecutionResult { @SuppressWarnings("unchecked") - private MapExecutionResult(Map resultMap) { + private MapGraphQlResponse(Map resultMap) { Assert.notNull(resultMap, "'resultMap' is required"); this.resultMap = resultMap; this.errors = MapGraphQlError.from((List>) resultMap.get("errors")); } + @Override + public boolean isValid() { + return (this.resultMap.containsKey("data") && this.resultMap.get("data") != null); + } + @Override public List getErrors() { return this.errors; @@ -58,26 +63,21 @@ public final class MapExecutionResult implements ExecutionResult { return (T) this.resultMap.get("data"); } - @Override - public boolean isDataPresent() { - return (this.resultMap.get("data") != null); - } - @SuppressWarnings("unchecked") @Override public Map getExtensions() { - return (Map) this.resultMap.get("extensions"); + return (Map) this.resultMap.getOrDefault("extensions", Collections.emptyMap()); } @Override - public Map toSpecification() { - return ExecutionResultImpl.newExecutionResult().from(this).build().toSpecification(); + public Map toMap() { + return this.resultMap; } @Override public boolean equals(Object other) { - return (other instanceof MapExecutionResult && - this.resultMap.equals(((MapExecutionResult) other).resultMap)); + return (other instanceof MapGraphQlResponse && + this.resultMap.equals(((MapGraphQlResponse) other).resultMap)); } @Override @@ -95,24 +95,24 @@ public final class MapExecutionResult implements ExecutionResult { * Create an instance from an {@code ExecutionResult} serialized to map via * {@link ExecutionResult#toSpecification()}. */ - public static ExecutionResult from(Map map) { - return new MapExecutionResult(map); + public static GraphQlResponse forResponse(Map map) { + return new MapGraphQlResponse(map); } /** * Create an {@code ExecutionResult} with a "data" key that returns the * given map. */ - public static ExecutionResult forDataOnly(Map map) { - return new MapExecutionResult(Collections.singletonMap("data", map)); + public static GraphQlResponse forDataOnly(Map map) { + return new MapGraphQlResponse(Collections.singletonMap("data", map)); } /** * Create an {@code ExecutionResult} with an "errors" key that returns the * given serialized errors. */ - public static ExecutionResult forErrorsOnly(List> errors) { - return new MapExecutionResult(Collections.singletonMap("errors", errors)); + public static GraphQlResponse forErrorsOnly(List> errors) { + return new MapGraphQlResponse(Collections.singletonMap("errors", errors)); } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/WebOutput.java b/spring-graphql/src/main/java/org/springframework/graphql/web/WebOutput.java index 26059303..6cf7b922 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/WebOutput.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/WebOutput.java @@ -16,7 +16,6 @@ package org.springframework.graphql.web; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -49,15 +48,14 @@ public class WebOutput extends RequestOutput { * @param requestOutput the output from an executed request */ public WebOutput(RequestOutput requestOutput) { - this(requestOutput.getExecutionInput(), requestOutput, new HttpHeaders()); + super(requestOutput); + this.responseHeaders = new HttpHeaders(); } - private WebOutput(ExecutionInput executionInput, ExecutionResult executionResult, - HttpHeaders responseHeaders) { - + private WebOutput(ExecutionInput executionInput, ExecutionResult executionResult, HttpHeaders headers) { super(executionInput, executionResult); - Assert.notNull(responseHeaders, "HttpHeaders is required"); - this.responseHeaders = responseHeaders; + Assert.notNull(headers, "HttpHeaders is required"); + this.responseHeaders = headers; } @@ -90,21 +88,13 @@ public class WebOutput extends RequestOutput { */ public static final class Builder { - private final WebOutput webOutput; + private final WebOutput original; - @Nullable - private Object data; + private final ExecutionResultImpl.Builder builder; - private List errors; - - @Nullable - private Map extensions; - - private Builder(WebOutput output) { - this.webOutput = output; - this.data = output.getData(); - this.errors = output.getErrors(); - this.extensions = output.getExtensions(); + private Builder(WebOutput original) { + this.original = original; + this.builder = ExecutionResultImpl.newExecutionResult().from(original.getExecutionResult()); } /** @@ -112,8 +102,8 @@ public class WebOutput extends RequestOutput { * @param data the execution result data * @return the current builder */ - public Builder data(@Nullable Object data) { - this.data = data; + public Builder data(Object data) { + this.builder.data(data); return this; } @@ -124,7 +114,7 @@ public class WebOutput extends RequestOutput { * @return the current builder */ public Builder errors(@Nullable List errors) { - this.errors = (errors != null) ? errors : Collections.emptyList(); + this.builder.errors(errors); return this; } @@ -135,13 +125,13 @@ public class WebOutput extends RequestOutput { * @return the current builder */ public Builder extensions(@Nullable Map extensions) { - this.extensions = extensions; + this.builder.extensions(extensions); return this; } public WebOutput build() { - ExecutionResult result = new ExecutionResultImpl(this.data, this.errors, this.extensions); - return new WebOutput(this.webOutput.getExecutionInput(), result, this.webOutput.getResponseHeaders()); + return new WebOutput(this.original.getExecutionInput(), this.builder.build(), + this.original.getResponseHeaders()); } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/support/GraphQlMessage.java b/spring-graphql/src/main/java/org/springframework/graphql/web/support/GraphQlMessage.java index a1c696e7..6c56e4e8 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/support/GraphQlMessage.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/support/GraphQlMessage.java @@ -20,10 +20,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import graphql.ExecutionResult; import graphql.GraphQLError; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.RequestOutput; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -63,6 +63,7 @@ public class GraphQlMessage { /** * Constructor for deserialization. */ + @SuppressWarnings("unused") GraphQlMessage() { this.type = GraphQlMessageType.NOT_SPECIFIED; } @@ -176,11 +177,21 @@ public class GraphQlMessage { /** * Create a {@code "next"} server message. * @param id unique request id - * @param result the result from request execution to add as the message payload + * @param output the output to obtain the result map from */ - public static GraphQlMessage next(String id, ExecutionResult result) { - Assert.notNull(result, "ExecutionResult is required"); - return new GraphQlMessage(id, GraphQlMessageType.NEXT, result.toSpecification()); + public static GraphQlMessage next(String id, RequestOutput output) { + Assert.notNull(output, "'RequestOutput' is required"); + return next(id, output.toMap()); + } + + /** + * Create a {@code "next"} server message. + * @param id unique request id + * @param responseMap the response map + */ + public static GraphQlMessage next(String id, Map responseMap) { + Assert.notNull(responseMap, "'responseMap' is required"); + return new GraphQlMessage(id, GraphQlMessageType.NEXT, responseMap); } /** diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/CodecDelegate.java b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/CodecDelegate.java index 9cd05e9f..27659466 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/CodecDelegate.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/CodecDelegate.java @@ -15,7 +15,8 @@ */ package org.springframework.graphql.web.webflux; -import graphql.ExecutionResult; +import java.util.Map; + import graphql.GraphQLError; import graphql.GraphqlErrorBuilder; @@ -93,8 +94,8 @@ final class CodecDelegate { return encode(session, GraphQlMessage.connectionAck(ackPayload)); } - public WebSocketMessage encodeNext(WebSocketSession session, String id, ExecutionResult result) { - return encode(session, GraphQlMessage.next(id, result)); + public WebSocketMessage encodeNext(WebSocketSession session, String id, Map responseMap) { + return encode(session, GraphQlMessage.next(id, responseMap)); } public WebSocketMessage encodeError(WebSocketSession session, String id, Throwable ex) { diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlHttpHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlHttpHandler.java index d2194086..9556256d 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlHttpHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlHttpHandler.java @@ -72,14 +72,13 @@ public class GraphQlHttpHandler { } return this.graphQlHandler.handleRequest(input); }) - .flatMap((output) -> { - Map spec = output.toSpecification(); + .flatMap(output -> { if (logger.isDebugEnabled()) { logger.debug("Execution complete"); } ServerResponse.BodyBuilder builder = ServerResponse.ok(); builder.headers(headers -> headers.putAll(output.getResponseHeaders())); - return builder.bodyValue(spec); + return builder.bodyValue(output.toMap()); }); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlWebSocketHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlWebSocketHandler.java index 8fe56974..c4a4f895 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlWebSocketHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/webflux/GraphQlWebSocketHandler.java @@ -185,10 +185,11 @@ public class GraphQlWebSocketHandler implements WebSocketHandler { + "."); } - Flux outputFlux; + Flux> responseFlux; if (output.getData() instanceof Publisher) { // Subscription - outputFlux = Flux.from((Publisher) output.getData()) + responseFlux = Flux.from((Publisher) output.getData()) + .map(ExecutionResult::toSpecification) .doOnSubscribe((subscription) -> { Subscription previous = subscriptions.putIfAbsent(id, subscription); if (previous != null) { @@ -198,11 +199,11 @@ public class GraphQlWebSocketHandler implements WebSocketHandler { } else { // Single response (query or mutation) that may contain errors - outputFlux = Flux.just(output); + responseFlux = Flux.just(output.toMap()); } - return outputFlux - .map(result -> this.codecDelegate.encodeNext(session, id, result)) + return responseFlux + .map(responseMap -> this.codecDelegate.encodeNext(session, id, responseMap)) .concatWith(Mono.fromCallable(() -> this.codecDelegate.encodeComplete(session, id))) .onErrorResume(ex -> { if (ex instanceof SubscriptionExistsException) { diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlHttpHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlHttpHandler.java index 84be58b5..9588b8e2 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlHttpHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlHttpHandler.java @@ -82,14 +82,15 @@ public class GraphQlHttpHandler { logger.debug("Executing: " + input); } - Mono responseMono = this.graphQlHandler.handleRequest(input).map((output) -> { - if (logger.isDebugEnabled()) { - logger.debug("Execution complete"); - } - ServerResponse.BodyBuilder builder = ServerResponse.ok(); - builder.headers(headers -> headers.putAll(output.getResponseHeaders())); - return builder.body(output.toSpecification()); - }); + Mono responseMono = this.graphQlHandler.handleRequest(input) + .map(output -> { + if (logger.isDebugEnabled()) { + logger.debug("Execution complete"); + } + ServerResponse.BodyBuilder builder = ServerResponse.ok(); + builder.headers(headers -> headers.putAll(output.getResponseHeaders())); + return builder.body(output.toMap()); + }); return ServerResponse.async(responseMono); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlWebSocketHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlWebSocketHandler.java index ba71c095..c96b3af0 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlWebSocketHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/webmvc/GraphQlWebSocketHandler.java @@ -48,7 +48,6 @@ import org.springframework.graphql.web.WebInput; import org.springframework.graphql.web.WebOutput; import org.springframework.graphql.web.WebSocketInterceptor; import org.springframework.graphql.web.support.GraphQlMessage; -import org.springframework.graphql.web.support.GraphQlMessageType; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; @@ -226,10 +225,11 @@ public class GraphQlWebSocketHandler extends TextWebSocketHandler implements Sub + (!CollectionUtils.isEmpty(output.getErrors()) ? " with errors: " + output.getErrors() : "") + "."); } - Flux outputFlux; + Flux> responseFlux; if (output.getData() instanceof Publisher) { // Subscription - outputFlux = Flux.from((Publisher) output.getData()) + responseFlux = Flux.from((Publisher) output.getData()) + .map(ExecutionResult::toSpecification) .doOnSubscribe((subscription) -> { Subscription prev = getSessionInfo(session).getSubscriptions().putIfAbsent(id, subscription); if (prev != null) { @@ -239,11 +239,11 @@ public class GraphQlWebSocketHandler extends TextWebSocketHandler implements Sub } else { // Single response (query or mutation) that may contain errors - outputFlux = Flux.just(output); + responseFlux = Flux.just(output.toMap()); } - return outputFlux - .map(result -> encode(GraphQlMessage.next(id, result))) + return responseFlux + .map(responseMap -> encode(GraphQlMessage.next(id, responseMap))) .concatWith(Mono.fromCallable(() -> encode(GraphQlMessage.complete(id)))) .onErrorResume((ex) -> { if (ex instanceof SubscriptionExistsException) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/GraphQlResponse.java b/spring-graphql/src/test/java/org/springframework/graphql/ResponseHelper.java similarity index 77% rename from spring-graphql/src/test/java/org/springframework/graphql/GraphQlResponse.java rename to spring-graphql/src/test/java/org/springframework/graphql/ResponseHelper.java index 838720a9..98e982aa 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/GraphQlResponse.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/ResponseHelper.java @@ -48,9 +48,9 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Rossen Stoyanchev */ -public class GraphQlResponse { +public class ResponseHelper { - private static final Log logger = LogFactory.getLog(GraphQlResponse.class); + private static final Log logger = LogFactory.getLog(ResponseHelper.class); private final DocumentContext documentContext; @@ -60,9 +60,9 @@ public class GraphQlResponse { private boolean errorsChecked; - private GraphQlResponse(ExecutionResult result) { - this.documentContext = JsonPath.parse(result.toSpecification(), initJsonPathConfig()); - this.errors = result.getErrors(); + private ResponseHelper(Map responseMap, List errors) { + this.documentContext = JsonPath.parse(responseMap, initJsonPathConfig()); + this.errors = errors; } private static Configuration initJsonPathConfig() { @@ -73,7 +73,7 @@ public class GraphQlResponse { } - public GraphQlResponse log() { + public ResponseHelper log() { logger.debug("GraphQlResponse: " + this.documentContext.jsonString()); return this; } @@ -132,27 +132,33 @@ public class GraphQlResponse { } - public static GraphQlResponse from(ExecutionResult result) { - return new GraphQlResponse(result); + public static ResponseHelper forResult(ExecutionResult result) { + return new ResponseHelper(result.toSpecification(), result.getErrors()); } - public static GraphQlResponse from(Mono resultMono) { + public static ResponseHelper forResult(Mono resultMono) { ExecutionResult result = resultMono.block(Duration.ofSeconds(5)); assertThat(result).isNotNull(); - return from(result); + return forResult(result); } - public static Flux forSubscription(ExecutionResult result) { + public static ResponseHelper forResponse(Mono outputMono) { + RequestOutput output = outputMono.block(Duration.ofSeconds(5)); + assertThat(output).isNotNull(); + return forResult(output.getExecutionResult()); + } + + public static Flux forSubscription(ExecutionResult result) { assertThat(result.getErrors()).as("Errors present in GraphQL response").isEmpty(); Publisher publisher = result.getData(); - return Flux.from(publisher).map(GraphQlResponse::from); + return Flux.from(publisher).map(ResponseHelper::forResult); } @SuppressWarnings("BlockingMethodInNonBlockingContext") - public static Flux forSubscription(Mono resultMono) { - ExecutionResult result = resultMono.block(Duration.ofSeconds(5)); - assertThat(result).isNotNull(); - return forSubscription(result); + public static Flux forSubscription(Mono resultMono) { + RequestOutput output = resultMono.block(Duration.ofSeconds(5)); + assertThat(output).isNotNull(); + return forSubscription(output.getExecutionResult()); } @@ -165,15 +171,15 @@ public class GraphQlResponse { } public String message() { - return GraphQlResponse.this.errors.get(index).getMessage(); + return ResponseHelper.this.errors.get(index).getMessage(); } public String errorType() { - return GraphQlResponse.this.errors.get(index).getErrorType().toString(); + return ResponseHelper.this.errors.get(index).getErrorType().toString(); } public Map extensions() { - return GraphQlResponse.this.errors.get(index).getExtensions(); + return ResponseHelper.this.errors.get(index).getExtensions(); } } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java index e5ff2765..156ed599 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTestSupport.java @@ -23,7 +23,6 @@ import java.util.function.Consumer; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import graphql.ExecutionInput; import graphql.ExecutionResult; import graphql.ExecutionResultImpl; import graphql.GraphQLError; @@ -31,7 +30,8 @@ import org.mockito.ArgumentCaptor; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; -import org.springframework.graphql.RequestOutput; +import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.support.MapGraphQlResponse; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -80,14 +80,11 @@ public class GraphQlClientTestSupport { } private void setMockResponse(Consumer consumer) { - ExecutionResultImpl.Builder builder = new ExecutionResultImpl.Builder(); consumer.accept(builder); - ExecutionInput executionInput = ExecutionInput.newExecutionInput("{}").build(); ExecutionResult result = builder.build(); - - when(this.transport.execute(this.requestCaptor.capture())) - .thenReturn(Mono.just(new RequestOutput(executionInput, result))); + GraphQlResponse response = MapGraphQlResponse.forResponse(result.toSpecification()); + when(this.transport.execute(this.requestCaptor.capture())).thenReturn(Mono.just(response)); } private void serialize(String data, ExecutionResultImpl.Builder builder) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/MockGraphQlWebSocketServer.java b/spring-graphql/src/test/java/org/springframework/graphql/client/MockGraphQlWebSocketServer.java index 2fecff65..e66ce1c8 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/MockGraphQlWebSocketServer.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/MockGraphQlWebSocketServer.java @@ -20,7 +20,6 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; -import graphql.ExecutionResult; import graphql.GraphQLError; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,6 +28,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; +import org.springframework.graphql.GraphQlResponse; import org.springframework.graphql.web.support.GraphQlMessage; import org.springframework.lang.Nullable; import org.springframework.web.reactive.socket.WebSocketHandler; @@ -100,7 +100,7 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { return Flux.error(new IllegalStateException("Unexpected request: " + message)); } return request.getResponseFlux() - .map(result -> GraphQlMessage.next(id, result)) + .map(response -> GraphQlMessage.next(id, response.toMap())) .concatWithValues( request.getError() != null ? GraphQlMessage.error(id, request.getError()) : @@ -118,12 +118,12 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { /** * Respond with the given a single result. */ - GraphQlRequest andRespond(ExecutionResult result); + GraphQlRequest andRespond(GraphQlResponse response); /** * Respond with the given a single result {@code Mono}. */ - GraphQlRequest andRespond(Mono resultMono); + GraphQlRequest andRespond(Mono responseMono); /** * Respond with a GraphQL over WebSocket "error" message. @@ -133,12 +133,12 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { /** * Respond with the given stream of responses. */ - GraphQlRequest andStream(Flux resultFlux); + GraphQlRequest andStream(Flux responseFlux); /** * Respond with the given stream of responses and terminate with an error. */ - GraphQlRequest andStreamWithError(Flux resultFlux, GraphQLError error); + GraphQlRequest andStreamWithError(Flux responseFlux, GraphQLError error); } @@ -147,7 +147,7 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { private final GraphQlRequest request; - private Flux responseFlux = Flux.empty(); + private Flux responseFlux = Flux.empty(); @Nullable private GraphQLError error; @@ -158,13 +158,13 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { } @Override - public GraphQlRequest andRespond(ExecutionResult result) { - return addResponse(Flux.just(result), null); + public GraphQlRequest andRespond(GraphQlResponse response) { + return addResponse(Flux.just(response), null); } @Override - public GraphQlRequest andRespond(Mono resultMono) { - return addResponse(Flux.from(resultMono), null); + public GraphQlRequest andRespond(Mono responseMono) { + return addResponse(Flux.from(responseMono), null); } @Override @@ -173,17 +173,17 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { } @Override - public GraphQlRequest andStream(Flux resultFlux) { - return addResponse(resultFlux, null); + public GraphQlRequest andStream(Flux responseFlux) { + return addResponse(responseFlux, null); } @Override - public GraphQlRequest andStreamWithError(Flux resultFlux, GraphQLError error) { - return addResponse(resultFlux, error); + public GraphQlRequest andStreamWithError(Flux responseFlux, GraphQLError error) { + return addResponse(responseFlux, error); } - private GraphQlRequest addResponse(Flux resultFlux, @Nullable GraphQLError error) { - this.responseFlux = resultFlux; + private GraphQlRequest addResponse(Flux responseFlux, @Nullable GraphQLError error) { + this.responseFlux = responseFlux; this.error = error; return this.request; } @@ -192,7 +192,7 @@ public final class MockGraphQlWebSocketServer implements WebSocketHandler { return this.request; } - public Flux getResponseFlux() { + public Flux getResponseFlux() { return this.responseFlux; } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/MockWebSocketGraphQlTransportTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/MockWebSocketGraphQlTransportTests.java index e25b6096..4173319a 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/MockWebSocketGraphQlTransportTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/MockWebSocketGraphQlTransportTests.java @@ -25,7 +25,6 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; -import graphql.ExecutionResult; import graphql.GraphQLError; import graphql.GraphqlErrorBuilder; import org.junit.jupiter.api.Test; @@ -34,7 +33,8 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import org.springframework.graphql.GraphQlRequest; -import org.springframework.graphql.support.MapExecutionResult; +import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.support.MapGraphQlResponse; import org.springframework.graphql.web.TestWebSocketClient; import org.springframework.graphql.web.TestWebSocketConnection; import org.springframework.graphql.web.support.GraphQlMessage; @@ -70,17 +70,17 @@ public class MockWebSocketGraphQlTransportTests { private final WebSocketGraphQlTransport transport = createTransport(this.webSocketClient); - private final ExecutionResult result1 = MapExecutionResult.forDataOnly(Collections.singletonMap("key1", "value1")); + private final GraphQlResponse response1 = MapGraphQlResponse.forDataOnly(Collections.singletonMap("key1", "value1")); - private final ExecutionResult result2 = MapExecutionResult.forDataOnly(Collections.singletonMap("key2", "value2")); + private final GraphQlResponse response2 = MapGraphQlResponse.forDataOnly(Collections.singletonMap("key2", "value2")); @Test void request() { - GraphQlRequest request = this.mockServer.expectOperation("{Query1}").andRespond(this.result1); + GraphQlRequest request = this.mockServer.expectOperation("{Query1}").andRespond(this.response1); StepVerifier.create(this.transport.execute(request)) - .expectNext(this.result1).expectComplete() + .expectNext(this.response1).expectComplete() .verify(TIMEOUT); assertActualClientMessages( @@ -90,10 +90,10 @@ public class MockWebSocketGraphQlTransportTests { @Test void requestStream() { - GraphQlRequest request = this.mockServer.expectOperation("{Sub1}").andStream(Flux.just(this.result1, result2)); + GraphQlRequest request = this.mockServer.expectOperation("{Sub1}").andStream(Flux.just(this.response1, response2)); StepVerifier.create(this.transport.executeSubscription(request)) - .expectNext(this.result1, result2).expectComplete() + .expectNext(this.response1, response2).expectComplete() .verify(TIMEOUT); assertActualClientMessages( @@ -108,7 +108,7 @@ public class MockWebSocketGraphQlTransportTests { StepVerifier.create(this.transport.execute(request)) .consumeNextWith(result -> { - assertThat(result.isDataPresent()).isFalse(); + assertThat(result.isValid()).isFalse(); assertThat(result.getErrors()).extracting(GraphQLError::getMessage).containsExactly("boo"); }) .expectComplete() @@ -122,10 +122,10 @@ public class MockWebSocketGraphQlTransportTests { @Test void requestStreamError() { GraphQlRequest request = this.mockServer.expectOperation("{Sub1}") - .andStreamWithError(Flux.just(this.result1), GraphqlErrorBuilder.newError().message("boo").build()); + .andStreamWithError(Flux.just(this.response1), GraphqlErrorBuilder.newError().message("boo").build()); StepVerifier.create(this.transport.executeSubscription(request)) - .expectNext(this.result1) + .expectNext(this.response1) .expectErrorSatisfies(actualEx -> { List errorList = ((SubscriptionErrorException) actualEx).getErrors(); assertThat(errorList).extracting(GraphQLError::getMessage).containsExactly("boo"); @@ -154,10 +154,10 @@ public class MockWebSocketGraphQlTransportTests { @Test void requestStreamCancelled() { GraphQlRequest request = this.mockServer.expectOperation("{Sub1}") - .andStream(Flux.just(this.result1).concatWith(Flux.never())); + .andStream(Flux.just(this.response1).concatWith(Flux.never())); StepVerifier.create(this.transport.executeSubscription(request)) - .expectNext(this.result1) + .expectNext(this.response1) .thenAwait(Duration.ofMillis(200)) .thenCancel() .verify(TIMEOUT); @@ -171,11 +171,11 @@ public class MockWebSocketGraphQlTransportTests { @Test void pingHandling() { - TestWebSocketClient client = new TestWebSocketClient(new PingResponseHandler(this.result1)); + TestWebSocketClient client = new TestWebSocketClient(new PingResponseHandler(this.response1)); WebSocketGraphQlTransport transport = createTransport(client); StepVerifier.create(transport.execute(new GraphQlRequest("{Query1}"))) - .expectNext(this.result1) + .expectNext(this.response1) .expectComplete() .verify(TIMEOUT); @@ -219,7 +219,7 @@ public class MockWebSocketGraphQlTransportTests { assertThat(this.webSocketClient.getConnection(0).closeStatus().block(TIMEOUT)).isEqualTo(CloseStatus.NORMAL); // New requests are rejected - GraphQlRequest request = this.mockServer.expectOperation("{Query1}").andRespond(this.result1); + GraphQlRequest request = this.mockServer.expectOperation("{Query1}").andRespond(this.response1); StepVerifier.create(this.transport.execute(request)) .expectErrorMessage("WebSocketGraphQlTransport has been stopped") .verify(TIMEOUT); @@ -230,23 +230,23 @@ public class MockWebSocketGraphQlTransportTests { assertThat(this.webSocketClient.getConnection(1).isOpen()).isTrue(); // Requests allowed again - request = this.mockServer.expectOperation("{Query1}").andRespond(this.result1); + request = this.mockServer.expectOperation("{Query1}").andRespond(this.response1); StepVerifier.create(this.transport.execute(request)) - .expectNext(this.result1).expectComplete() + .expectNext(this.response1).expectComplete() .verify(TIMEOUT); } @Test void sessionIsCachedUntilClosed() { - GraphQlRequest request1 = this.mockServer.expectOperation("{Query1}").andRespond(this.result1); - StepVerifier.create(this.transport.execute(request1)).expectNext(this.result1).expectComplete().verify(TIMEOUT); + GraphQlRequest request1 = this.mockServer.expectOperation("{Query1}").andRespond(this.response1); + StepVerifier.create(this.transport.execute(request1)).expectNext(this.response1).expectComplete().verify(TIMEOUT); assertThat(this.webSocketClient.getConnectionCount()).isEqualTo(1); TestWebSocketConnection originalConnection = this.webSocketClient.getConnection(0); - GraphQlRequest request2 = this.mockServer.expectOperation("{Query2}").andRespond(this.result2); - StepVerifier.create(this.transport.execute(request2)).expectNext(this.result2).expectComplete().verify(TIMEOUT); + GraphQlRequest request2 = this.mockServer.expectOperation("{Query2}").andRespond(this.response2); + StepVerifier.create(this.transport.execute(request2)).expectNext(this.response2).expectComplete().verify(TIMEOUT); assertThat(this.webSocketClient.getConnectionCount()).isEqualTo(1); assertThat(this.webSocketClient.getConnection(0)).isSameAs(originalConnection); @@ -254,8 +254,8 @@ public class MockWebSocketGraphQlTransportTests { // Close the connection originalConnection.closeServerSession(CloseStatus.NORMAL).block(TIMEOUT); - request1 = this.mockServer.expectOperation("{Query1}").andRespond(this.result1); - StepVerifier.create(this.transport.execute(request1)).expectNext(this.result1).expectComplete().verify(TIMEOUT); + request1 = this.mockServer.expectOperation("{Query1}").andRespond(this.response1); + StepVerifier.create(this.transport.execute(request1)).expectNext(this.response1).expectComplete().verify(TIMEOUT); assertThat(this.webSocketClient.getConnectionCount()).isEqualTo(2); assertThat(this.webSocketClient.getConnection(1)).isNotSameAs(originalConnection); @@ -332,12 +332,12 @@ public class MockWebSocketGraphQlTransportTests { */ private static class PingResponseHandler implements WebSocketHandler { - private final ExecutionResult result; + private final GraphQlResponse response; private final CodecDelegate codecDelegate = new CodecDelegate(); - private PingResponseHandler(ExecutionResult result) { - this.result = result; + private PingResponseHandler(GraphQlResponse response) { + this.response = response; } @Override @@ -349,7 +349,7 @@ public class MockWebSocketGraphQlTransportTests { case CONNECTION_INIT: return Flux.just(GraphQlMessage.connectionAck(null), GraphQlMessage.ping(null)); case SUBSCRIBE: - return Flux.just(GraphQlMessage.next("1", this.result)); + return Flux.just(GraphQlMessage.next("1", this.response.toMap())); case PONG: return Flux.empty(); default: diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingInvocationTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingInvocationTests.java index 78d5bb67..b2d61967 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingInvocationTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingInvocationTests.java @@ -28,7 +28,7 @@ import org.junit.jupiter.params.provider.MethodSource; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.RequestOutput; import org.springframework.graphql.TestRequestInput; import org.springframework.graphql.data.method.annotation.BatchMapping; @@ -70,10 +70,10 @@ public class BatchMappingInvocationTests extends BatchMappingTestSupport { " }" + "}"; - Mono resultMono = createGraphQlService(controller) + Mono outputMono = createGraphQlService(controller) .execute(TestRequestInput.forDocument(query)); - List actualCourses = GraphQlResponse.from(resultMono).toList("courses", Course.class); + List actualCourses = ResponseHelper.forResponse(outputMono).toList("courses", Course.class); List courses = Course.allCourses(); assertThat(actualCourses).hasSize(courses.size()); @@ -103,10 +103,10 @@ public class BatchMappingInvocationTests extends BatchMappingTestSupport { " }" + "}"; - Mono resultMono = createGraphQlService(controller) + Mono outputMono = createGraphQlService(controller) .execute(TestRequestInput.forDocument(document)); - List actualCourses = GraphQlResponse.from(resultMono).toList("courses", Course.class); + List actualCourses = ResponseHelper.forResponse(outputMono).toList("courses", Course.class); List courses = Course.allCourses(); assertThat(actualCourses).hasSize(courses.size()); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingPrincipalMethodArgumentResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingPrincipalMethodArgumentResolverTests.java index 8c74ab8c..4cae1be2 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingPrincipalMethodArgumentResolverTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/BatchMappingPrincipalMethodArgumentResolverTests.java @@ -30,7 +30,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.context.Context; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.RequestOutput; import org.springframework.graphql.TestRequestInput; import org.springframework.graphql.data.method.annotation.BatchMapping; @@ -92,14 +92,14 @@ public class BatchMappingPrincipalMethodArgumentResolverTests extends BatchMappi } private void testBatchLoading(PrincipalCourseController controller, Function contextWriter) { - Mono resultMono = Mono.delay(Duration.ofMillis(10)) + Mono outputMono = Mono.delay(Duration.ofMillis(10)) .flatMap(aLong -> { String document = "{ courses { id instructor { id } } }"; return createGraphQlService(controller).execute(TestRequestInput.forDocument(document)); }) .contextWrite(contextWriter); - List actualCourses = GraphQlResponse.from(resultMono).toList("courses", Course.class); + List actualCourses = ResponseHelper.forResponse(outputMono).toList("courses", Course.class); List courses = Course.allCourses(); assertThat(actualCourses).hasSize(courses.size()); for (int i = 0; i < courses.size(); i++) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingInvocationTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingInvocationTests.java index 27e530ce..0b70284e 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingInvocationTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingInvocationTests.java @@ -33,7 +33,7 @@ import org.springframework.graphql.Author; import org.springframework.graphql.Book; import org.springframework.graphql.BookCriteria; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlService; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.RequestInput; @@ -71,9 +71,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - Book book = GraphQlResponse.from(resultMono).toEntity("bookById", Book.class); + Book book = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(book.getId()).isEqualTo(1); assertThat(book.getName()).isEqualTo("Nineteen Eighty-Four"); @@ -91,9 +91,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - List bookList = GraphQlResponse.from(resultMono).toList("booksByCriteria", Book.class); + List bookList = ResponseHelper.forResponse(outputMono).toList("booksByCriteria", Book.class); assertThat(bookList).hasSize(2); assertThat(bookList.get(0).getName()).isEqualTo("Nineteen Eighty-Four"); assertThat(bookList.get(1).getName()).isEqualTo("Animal Farm"); @@ -108,9 +108,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - List bookList = GraphQlResponse.from(resultMono).toList("booksByProjectedArguments", Book.class); + List bookList = ResponseHelper.forResponse(outputMono).toList("booksByProjectedArguments", Book.class); assertThat(bookList).hasSize(2); assertThat(bookList.get(0).getName()).isEqualTo("Nineteen Eighty-Four"); assertThat(bookList.get(1).getName()).isEqualTo("Animal Farm"); @@ -125,9 +125,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - List bookList = GraphQlResponse.from(resultMono).toList("booksByProjectedCriteria", Book.class); + List bookList = ResponseHelper.forResponse(outputMono).toList("booksByProjectedCriteria", Book.class); assertThat(bookList).hasSize(2); assertThat(bookList.get(0).getName()).isEqualTo("Nineteen Eighty-Four"); assertThat(bookList.get(1).getName()).isEqualTo("Animal Farm"); @@ -150,9 +150,9 @@ public class SchemaMappingInvocationTests { return executionInput; }); - Mono resultMono = graphQlService().execute(requestInput); + Mono outputMono = graphQlService().execute(requestInput); - Author author = GraphQlResponse.from(resultMono).toEntity("authorById", Author.class); + Author author = ResponseHelper.forResponse(outputMono).toEntity("authorById", Author.class); assertThat(author.getId()).isEqualTo(101); assertThat(author.getFirstName()).isEqualTo("George"); assertThat(author.getLastName()).isEqualTo("Orwell"); @@ -170,9 +170,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - Author author = GraphQlResponse.from(resultMono).toEntity("addAuthor", Author.class); + Author author = ResponseHelper.forResponse(outputMono).toEntity("addAuthor", Author.class); assertThat(author.getId()).isEqualTo(99); assertThat(author.getFirstName()).isEqualTo("James"); assertThat(author.getLastName()).isEqualTo("Joyce"); @@ -187,9 +187,9 @@ public class SchemaMappingInvocationTests { " }" + "}"; - Mono resultMono = graphQlService().execute(TestRequestInput.forDocument(document)); + Mono outputMono = graphQlService().execute(TestRequestInput.forDocument(document)); - Flux bookFlux = GraphQlResponse.forSubscription(resultMono) + Flux bookFlux = ResponseHelper.forSubscription(outputMono) .map(response -> response.toEntity("bookSearch", Book.class)); StepVerifier.create(bookFlux) diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingPrincipalMethodArgumentResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingPrincipalMethodArgumentResolverTests.java index c53c7fa9..df1f2e4e 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingPrincipalMethodArgumentResolverTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingPrincipalMethodArgumentResolverTests.java @@ -31,7 +31,7 @@ import reactor.util.context.Context; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.MethodParameter; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.RequestOutput; import org.springframework.graphql.TestRequestInput; @@ -106,7 +106,7 @@ public class SchemaMappingPrincipalMethodArgumentResolverTests { Mono resultMono = executeAsync( "type Query { " + field + ": String }", "{ " + field + " }", contextWriter); - String greeting = GraphQlResponse.from(resultMono).toEntity(field, String.class); + String greeting = ResponseHelper.forResponse(resultMono).toEntity(field, String.class); assertThat(greeting).isEqualTo("Hello"); assertThat(greetingController.principal()).isSameAs(authentication); } @@ -141,7 +141,7 @@ public class SchemaMappingPrincipalMethodArgumentResolverTests { "subscription Greeting { " + field + " }", contextModifier); - Flux greetingFlux = GraphQlResponse.forSubscription(resultMono) + Flux greetingFlux = ResponseHelper.forSubscription(resultMono) .map(response -> response.toEntity(field, String.class)); StepVerifier.create(greetingFlux).expectNext("Hello", "Hi").verifyComplete(); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java index 21f559dc..238d939b 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java @@ -43,7 +43,7 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.Repository; import org.springframework.graphql.Author; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.data.GraphQlRepository; import org.springframework.graphql.execution.RuntimeWiringConfigurer; @@ -77,7 +77,7 @@ class QuerydslDataFetcherTests { Consumer tester = setup -> { Mono output = setup.toWebGraphQlHandler().handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(output).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(output).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo(book.getName()); }; @@ -98,7 +98,7 @@ class QuerydslDataFetcherTests { Consumer tester = graphQlSetup -> { Mono output = graphQlSetup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(output).toList("books", Book.class) + List names = ResponseHelper.forResponse(output).toList("books", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder(book1.getName(), book2.getName()); @@ -120,7 +120,7 @@ class QuerydslDataFetcherTests { Mono output = graphQlSetup(mockRepository).toWebGraphQlHandler() .handleRequest(input("{ booksById(id: [42,53]) {name}}")); - List names = GraphQlResponse.from(output).toList("booksById", Book.class) + List names = ResponseHelper.forResponse(output).toList("booksById", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder(book1.getName(), book2.getName()); @@ -136,7 +136,7 @@ class QuerydslDataFetcherTests { Consumer tester = graphQlSetup -> { Mono output = graphQlSetup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(output).toList("books", Book.class) + List names = ResponseHelper.forResponse(output).toList("books", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder(book1.getName(), book2.getName()); @@ -179,7 +179,7 @@ class QuerydslDataFetcherTests { WebGraphQlHandler handler = graphQlSetup(mockRepository).toWebGraphQlHandler(); Mono outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy"); // 2) Automatic registration and explicit wiring @@ -189,7 +189,7 @@ class QuerydslDataFetcherTests { outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Breaking Bad"); } @@ -203,7 +203,7 @@ class QuerydslDataFetcherTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy by Douglas Adams"); } @@ -217,7 +217,7 @@ class QuerydslDataFetcherTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy"); } @@ -229,7 +229,7 @@ class QuerydslDataFetcherTests { Consumer tester = setup -> { Mono outputMono = setup.toWebGraphQlHandler().handleRequest(input("{ bookById(id: 1) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo(book.getName()); }; @@ -251,7 +251,7 @@ class QuerydslDataFetcherTests { Consumer tester = setup -> { Mono outputMono = setup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(outputMono).toList("books", Book.class) + List names = ResponseHelper.forResponse(outputMono).toList("books", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder("Breaking Bad", "Hitchhiker's Guide to the Galaxy"); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java index 9c611b18..ee2ce1a2 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java @@ -40,7 +40,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.query.QueryByExampleExecutor; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.data.query.QueryByExampleDataFetcher; import org.springframework.graphql.execution.RuntimeWiringConfigurer; @@ -80,7 +80,7 @@ class QueryByExampleDataFetcherJpaTests { Consumer tester = setup -> { Mono output = setup.toWebGraphQlHandler().handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(output).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(output).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo(book.getName()); }; @@ -101,7 +101,7 @@ class QueryByExampleDataFetcherJpaTests { Consumer tester = graphQlSetup -> { Mono output = graphQlSetup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(output).toList("books", Book.class) + List names = ResponseHelper.forResponse(output).toList("books", Book.class) .stream() .map(Book::getName) .collect(Collectors.toList()); @@ -126,7 +126,7 @@ class QueryByExampleDataFetcherJpaTests { WebGraphQlHandler handler = graphQlSetup(mockRepository).toWebGraphQlHandler(); Mono outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy"); // 2) Automatic registration and explicit wiring @@ -136,7 +136,7 @@ class QueryByExampleDataFetcherJpaTests { outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Breaking Bad"); } @@ -150,7 +150,7 @@ class QueryByExampleDataFetcherJpaTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy by Douglas Adams"); } @@ -165,7 +165,7 @@ class QueryByExampleDataFetcherJpaTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy"); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java index 82752601..74ed1ead 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java @@ -42,7 +42,7 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.repository.query.QueryByExampleExecutor; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.data.query.QueryByExampleDataFetcher; import org.springframework.graphql.execution.RuntimeWiringConfigurer; @@ -81,7 +81,7 @@ class QueryByExampleDataFetcherMongoDbTests { Consumer tester = setup -> { Mono output = setup.toWebGraphQlHandler().handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(output).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(output).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo(book.getName()); }; @@ -102,7 +102,7 @@ class QueryByExampleDataFetcherMongoDbTests { Consumer tester = graphQlSetup -> { Mono output = graphQlSetup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(output).toList("books", Book.class) + List names = ResponseHelper.forResponse(output).toList("books", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder(book1.getName(), book2.getName()); @@ -125,7 +125,7 @@ class QueryByExampleDataFetcherMongoDbTests { WebGraphQlHandler handler = graphQlSetup(mockRepository).toWebGraphQlHandler(); Mono outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy"); // 2) Automatic registration and explicit wiring @@ -135,7 +135,7 @@ class QueryByExampleDataFetcherMongoDbTests { outputMono = handler.handleRequest(input("{ bookById(id: 1) {name}}")); - actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Breaking Bad"); } @@ -149,7 +149,7 @@ class QueryByExampleDataFetcherMongoDbTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy by Douglas Adams"); } @@ -163,7 +163,7 @@ class QueryByExampleDataFetcherMongoDbTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy"); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java index 3632c892..41a8c1be 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java @@ -41,7 +41,7 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.data.query.QueryByExampleDataFetcher; import org.springframework.graphql.execution.RuntimeWiringConfigurer; @@ -77,7 +77,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests { Consumer tester = setup -> { Mono outputMono = setup.toWebGraphQlHandler().handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo(book.getName()); }; @@ -99,7 +99,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("Hitchhiker's Guide to the Galaxy by Douglas Adams"); } @@ -113,7 +113,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests { Mono outputMono = handler.handleRequest(input("{ bookById(id: 42) {name}}")); - Book actualBook = GraphQlResponse.from(outputMono).toEntity("bookById", Book.class); + Book actualBook = ResponseHelper.forResponse(outputMono).toEntity("bookById", Book.class); assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy"); } @@ -126,7 +126,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests { Consumer tester = setup -> { Mono outputMono = setup.toWebGraphQlHandler().handleRequest(input("{ books {name}}")); - List names = GraphQlResponse.from(outputMono).toList("books", Book.class) + List names = ResponseHelper.forResponse(outputMono).toList("books", Book.class) .stream().map(Book::getName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder("Breaking Bad", "Hitchhiker's Guide to the Galaxy"); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/BatchLoadingTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/BatchLoadingTests.java index 2a39aee2..11789db0 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/BatchLoadingTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/BatchLoadingTests.java @@ -27,7 +27,7 @@ import reactor.core.publisher.Mono; import org.springframework.graphql.Author; import org.springframework.graphql.Book; import org.springframework.graphql.BookSource; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlService; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.RequestOutput; @@ -76,9 +76,9 @@ public class BatchLoadingTests { .dataLoaders(this.registry) .toGraphQlService(); - Mono resultMono = service.execute(TestRequestInput.forDocument(document)); + Mono outputMono = service.execute(TestRequestInput.forDocument(document)); - List books = GraphQlResponse.from(resultMono).toList("booksByCriteria", Book.class); + List books = ResponseHelper.forResponse(outputMono).toList("booksByCriteria", Book.class); assertThat(books).hasSize(2); Author author = books.get(0).getAuthor(); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ClassNameTypeResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ClassNameTypeResolverTests.java index 4613c89d..416865f9 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ClassNameTypeResolverTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ClassNameTypeResolverTests.java @@ -22,7 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.RequestOutput; import org.springframework.graphql.TestRequestInput; @@ -83,11 +83,11 @@ public class ClassNameTypeResolverTests { " }" + "}"; - Mono resultMono = graphQlSetup.queryFetcher("animals", env -> animalList) + Mono outputMono = graphQlSetup.queryFetcher("animals", env -> animalList) .toGraphQlService() .execute(TestRequestInput.forDocument(document)); - GraphQlResponse response = GraphQlResponse.from(resultMono); + ResponseHelper response = ResponseHelper.forResponse(outputMono); for (int i = 0; i < animalList.size(); i++) { Animal animal = animalList.get(i); if (animal instanceof Bird) { @@ -125,12 +125,12 @@ public class ClassNameTypeResolverTests { ClassNameTypeResolver typeResolver = new ClassNameTypeResolver(); typeResolver.addMapping(Tree.class, "Plant"); - Mono result = graphQlSetup.queryFetcher("sightings", env -> animalAndPlantList) + Mono output = graphQlSetup.queryFetcher("sightings", env -> animalAndPlantList) .typeResolver(typeResolver) .toGraphQlService() .execute(TestRequestInput.forDocument(document)); - GraphQlResponse response = GraphQlResponse.from(result); + ResponseHelper response = ResponseHelper.forResponse(output); for (int i = 0; i < animalAndPlantList.size(); i++) { Object sighting = animalAndPlantList.get(i); if (sighting instanceof Animal) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java index 71c5e4e9..b4b7f1d1 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java @@ -29,7 +29,7 @@ import reactor.test.StepVerifier; import reactor.util.context.Context; import reactor.util.context.ContextView; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.TestThreadLocalAccessor; @@ -56,7 +56,7 @@ public class ContextDataFetcherDecoratorTests { ExecutionResult executionResult = graphQl.executeAsync(input).get(); - String greeting = GraphQlResponse.from(executionResult).toEntity("greeting", String.class); + String greeting = ResponseHelper.forResult(executionResult).toEntity("greeting", String.class); assertThat(greeting).isEqualTo("Hello 007"); } @@ -76,7 +76,7 @@ public class ContextDataFetcherDecoratorTests { ExecutionResult result = graphQl.executeAsync(input).get(); - List data = GraphQlResponse.from(result).toList("greetings", String.class); + List data = ResponseHelper.forResult(result).toList("greetings", String.class); assertThat(data).containsExactly("Hi 007", "Bonjour 007", "Hola 007"); } @@ -96,7 +96,7 @@ public class ContextDataFetcherDecoratorTests { ExecutionResult executionResult = graphQl.executeAsync(input).get(); - Flux greetingsFlux = GraphQlResponse.forSubscription(executionResult) + Flux greetingsFlux = ResponseHelper.forSubscription(executionResult) .map(response -> response.toEntity("greetings", String.class)); StepVerifier.create(greetingsFlux) @@ -121,7 +121,7 @@ public class ContextDataFetcherDecoratorTests { Mono resultMono = Mono.delay(Duration.ofMillis(10)) .flatMap((aLong) -> Mono.fromFuture(graphQl.executeAsync(input))); - String greeting = GraphQlResponse.from(resultMono).toEntity("greeting", String.class); + String greeting = ResponseHelper.forResult(resultMono).toEntity("greeting", String.class); assertThat(greeting).isEqualTo("Hello 007"); } finally { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java index 3cb0efc4..39668c3c 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,19 +18,16 @@ package org.springframework.graphql.execution; import java.time.Duration; import java.util.Collections; -import java.util.List; import graphql.ExecutionInput; import graphql.ExecutionResult; -import graphql.GraphQLError; import graphql.GraphqlErrorBuilder; -import graphql.schema.DataFetchingEnvironment; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import reactor.util.context.Context; import reactor.util.context.ContextView; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.TestThreadLocalAccessor; @@ -62,7 +59,7 @@ public class ExceptionResolversExceptionHandlerTests { ExecutionResult result = this.graphQlSetup.exceptionResolver(resolver).toGraphQl() .executeAsync(this.input).get(); - GraphQlResponse response = GraphQlResponse.from(result); + ResponseHelper response = ResponseHelper.forResult(result); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Resolved error: Invalid greeting"); assertThat(response.error(0).errorType()).isEqualTo("BAD_REQUEST"); @@ -84,7 +81,7 @@ public class ExceptionResolversExceptionHandlerTests { ExecutionResult result = this.graphQlSetup.exceptionResolver(resolver).toGraphQl() .executeAsync(this.input).get(); - GraphQlResponse response = GraphQlResponse.from(result); + ResponseHelper response = ResponseHelper.forResult(result); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Resolved error: Invalid greeting, name=007"); } @@ -110,7 +107,7 @@ public class ExceptionResolversExceptionHandlerTests { Mono result = Mono.delay(Duration.ofMillis(10)).flatMap((aLong) -> Mono.fromFuture(this.graphQlSetup.exceptionResolver(resolver).toGraphQl().executeAsync(this.input))); - GraphQlResponse response = GraphQlResponse.from(result); + ResponseHelper response = ResponseHelper.forResult(result); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Resolved error: Invalid greeting, name=007"); } @@ -127,7 +124,7 @@ public class ExceptionResolversExceptionHandlerTests { ExecutionResult result = this.graphQlSetup.exceptionResolver(resolver).toGraphQl() .executeAsync(this.input).get(); - GraphQlResponse response = GraphQlResponse.from(result); + ResponseHelper response = ResponseHelper.forResult(result); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Invalid greeting"); assertThat(response.error(0).errorType()).isEqualTo("INTERNAL_ERROR"); @@ -143,7 +140,7 @@ public class ExceptionResolversExceptionHandlerTests { .exceptionResolver((ex, env) -> Mono.just(Collections.emptyList())).toGraphQl() .executeAsync(input).get(); - String greeting = GraphQlResponse.from(result).rawValue("greeting"); + String greeting = ResponseHelper.forResult(result).rawValue("greeting"); assertThat(greeting).isNull(); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/web/WebGraphQlHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/web/WebGraphQlHandlerTests.java index 7b492d1a..97d29c7c 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/web/WebGraphQlHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/web/WebGraphQlHandlerTests.java @@ -25,7 +25,7 @@ import graphql.schema.DataFetcher; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; -import org.springframework.graphql.GraphQlResponse; +import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.TestThreadLocalAccessor; import org.springframework.graphql.execution.DataFetcherExceptionResolver; @@ -63,7 +63,7 @@ public class WebGraphQlHandlerTests { .handleRequest(webInput) .contextWrite((context) -> context.put("name", "007")); - String greeting = GraphQlResponse.from(outputMono).toEntity("greeting", String.class); + String greeting = ResponseHelper.forResponse(outputMono).toEntity("greeting", String.class); assertThat(greeting).isEqualTo("Hello 007"); } @@ -82,7 +82,7 @@ public class WebGraphQlHandlerTests { .handleRequest(webInput) .contextWrite((cxt) -> cxt.put("name", "007")); - GraphQlResponse response = GraphQlResponse.from(outputMono); + ResponseHelper response = ResponseHelper.forResponse(outputMono); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Resolved error: Invalid greeting, name=007"); @@ -104,7 +104,7 @@ public class WebGraphQlHandlerTests { .toWebGraphQlHandler() .handleRequest(webInput); - String greeting = GraphQlResponse.from(outputMono).toEntity("greeting", String.class); + String greeting = ResponseHelper.forResponse(outputMono).toEntity("greeting", String.class); assertThat(greeting).isEqualTo("Hello 007"); } finally { @@ -131,7 +131,7 @@ public class WebGraphQlHandlerTests { .toWebGraphQlHandler() .handleRequest(webInput); - GraphQlResponse response = GraphQlResponse.from(outputMono); + ResponseHelper response = ResponseHelper.forResponse(outputMono); assertThat(response.errorCount()).isEqualTo(1); assertThat(response.error(0).message()).isEqualTo("Resolved error: Invalid greeting, name=007"); }