From dce3d3f4cf46f62ee998ba860e5e7e9029422096 Mon Sep 17 00:00:00 2001 From: irawoof Date: Wed, 25 Oct 2023 15:46:00 -0400 Subject: [PATCH] test: add asserts for outgoing query in integration tests --- .../AliasFragmentSpreadWithNestedSpec.groovy | 45 ++++++++++++------- .../InterfaceImplementInterfaceSpec.groovy | 4 ++ .../JavaPrimitiveScalarSpec.groovy | 3 ++ .../NestedFieldResolverSpec.groovy | 8 ++++ .../integration/TopLevelStitchingSpec.groovy | 12 ++++- .../BaseIntegrationTestSpecification.groovy | 38 ++++++++++++++++ 6 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/test/groovy/com/intuit/graphql/orchestrator/integration/AliasFragmentSpreadWithNestedSpec.groovy b/src/test/groovy/com/intuit/graphql/orchestrator/integration/AliasFragmentSpreadWithNestedSpec.groovy index d28137b0..fb07f40d 100644 --- a/src/test/groovy/com/intuit/graphql/orchestrator/integration/AliasFragmentSpreadWithNestedSpec.groovy +++ b/src/test/groovy/com/intuit/graphql/orchestrator/integration/AliasFragmentSpreadWithNestedSpec.groovy @@ -59,15 +59,19 @@ class AliasFragmentSpreadWithNestedSpec extends BaseIntegrationTestSpecification ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + //query QUERY { + // a {b {foo:c(a:"foo") {d {f1}}}} + // a {b {bar:c(a:"bar") {d {f2}}}} + // } + compareQueryToExecutionInput(null, + "queryQUERY{a{b{foo:c(a:\"foo\"){d{f1}}bar:c(a:\"bar\"){d{f2}}}}}", service1) + compareQueryToExecutionInput(null,null, service2) + executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.a?.b?.foo?.d?.f1 instanceof String && data.a?.b?.foo?.d?.f1 == "foo1" data.a?.b?.bar?.d?.f2 instanceof String && data.a?.b?.bar?.d?.f2 == "bar2" - //query QUERY { - // a {b {foo:c(a:"foo") {d {f1}}}} - // a {b {bar:c(a:"bar") {d {f2}}}} - // } } def "Fragments used at the type-merge level with arguments"() { @@ -92,6 +96,15 @@ class AliasFragmentSpreadWithNestedSpec extends BaseIntegrationTestSpecification ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + // fragment fr on C {d {f1 f2}} + // + // query QUERY { + // a {b {foo:c(a:"foo") {...fr}}} + // a {b {bar:c(a:"bar") {...fr}}} + // } + compareQueryToExecutionInput(null, + "fragmentfronC{d{f1f2}}queryQUERY{a{b{foo:c(a:\"foo\"){...fr}bar:c(a:\"bar\"){...fr}}}}", service1) + compareQueryToExecutionInput(null,null, service2) executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.a?.b?.foo?.d?.f1 instanceof String && data.a?.b?.foo?.d?.f1 == "foo1" @@ -100,12 +113,7 @@ class AliasFragmentSpreadWithNestedSpec extends BaseIntegrationTestSpecification data.a?.b?.bar?.d?.f2 instanceof String && data.a?.b?.bar?.d?.f2 == "bar2" } -// fragment fr on C {d {f1 f2}} -// -// query QUERY { -// a {b {foo:c(a:"foo") {...fr}}} -// a {b {bar:c(a:"bar") {...fr}}} -// } + def "Basic Nested"() { given: def mockServiceResponseBasic1 = [ @@ -150,6 +158,15 @@ class AliasFragmentSpreadWithNestedSpec extends BaseIntegrationTestSpecification ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + // fragment fr on C {d {f1 f2}} + // + // query QUERY { + // a {b {foo:c(a:"foo") {...fr}}} + // a {b {bar:c(a:"bar") {...fr}}} + // } + compareQueryToExecutionInput(null, + "queryQUERY{a{b{c(a:\"foo\"){d{f1f2}}}e{f1}}}", service1) + compareQueryToExecutionInput(null,"queryQUERY{a{b{c(a:\"foo\"){f{f1f2}}}}}", service2) executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.a?.b?.c?.d?.f1 instanceof String && data.a?.b?.c?.d?.f1 == "foo1" @@ -158,11 +175,5 @@ class AliasFragmentSpreadWithNestedSpec extends BaseIntegrationTestSpecification data.a?.b?.c?.f?.f2 instanceof String && data.a?.b?.c?.f?.f2 == "bar2" data.a?.e?.f1 instanceof String && data.a?.e?.f1 == "eoo" } - -// fragment fr on C {d {f1 f2}} -// -// query QUERY { -// a {b {foo:c(a:"foo") {...fr}}} -// a {b {bar:c(a:"bar") {...fr}}} -// } + } diff --git a/src/test/groovy/com/intuit/graphql/orchestrator/integration/InterfaceImplementInterfaceSpec.groovy b/src/test/groovy/com/intuit/graphql/orchestrator/integration/InterfaceImplementInterfaceSpec.groovy index ac6b4ae3..b77d97ad 100644 --- a/src/test/groovy/com/intuit/graphql/orchestrator/integration/InterfaceImplementInterfaceSpec.groovy +++ b/src/test/groovy/com/intuit/graphql/orchestrator/integration/InterfaceImplementInterfaceSpec.groovy @@ -1,6 +1,7 @@ package com.intuit.graphql.orchestrator.integration import com.intuit.graphql.orchestrator.GraphQLOrchestrator +import com.intuit.graphql.orchestrator.testhelpers.SimpleMockServiceProvider import graphql.ExecutionInput import graphql.ExecutionResult import graphql.schema.GraphQLInterfaceType @@ -130,6 +131,9 @@ class InterfaceImplementInterfaceSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + compareQueryToExecutionInput(null, + "queryQUERY{pets{edges{...onDogEdge{node{idnameisServiceDog__typename}__typename}__typename}__typename}}", + (SimpleMockServiceProvider) testService) executionResult.getErrors().isEmpty() Map data = executionResult.getData() diff --git a/src/test/groovy/com/intuit/graphql/orchestrator/integration/JavaPrimitiveScalarSpec.groovy b/src/test/groovy/com/intuit/graphql/orchestrator/integration/JavaPrimitiveScalarSpec.groovy index a788b76e..9f99a7c2 100644 --- a/src/test/groovy/com/intuit/graphql/orchestrator/integration/JavaPrimitiveScalarSpec.groovy +++ b/src/test/groovy/com/intuit/graphql/orchestrator/integration/JavaPrimitiveScalarSpec.groovy @@ -1,6 +1,8 @@ package com.intuit.graphql.orchestrator.integration import com.intuit.graphql.orchestrator.GraphQLOrchestrator +import com.intuit.graphql.orchestrator.schema.Operation +import com.intuit.graphql.orchestrator.testhelpers.SimpleMockServiceProvider import graphql.ExecutionInput import graphql.ExecutionResult import helpers.BaseIntegrationTestSpecification @@ -57,6 +59,7 @@ class JavaPrimitiveScalarSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + compareQueryToExecutionInput(Operation.QUERY, graphqlQuery, (SimpleMockServiceProvider) testService); executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.a instanceof Long && data.a == Long.MAX_VALUE diff --git a/src/test/groovy/com/intuit/graphql/orchestrator/integration/NestedFieldResolverSpec.groovy b/src/test/groovy/com/intuit/graphql/orchestrator/integration/NestedFieldResolverSpec.groovy index e8b7a984..baebc93c 100644 --- a/src/test/groovy/com/intuit/graphql/orchestrator/integration/NestedFieldResolverSpec.groovy +++ b/src/test/groovy/com/intuit/graphql/orchestrator/integration/NestedFieldResolverSpec.groovy @@ -120,6 +120,14 @@ class NestedFieldResolverSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + specUnderTest.runtimeGraph.codeRegistry.dataFetcherMap.size() == 6 + checkIfKeyExistsInDataFetcherMap(specUnderTest, "BObjectType.bObjectField") + checkIfKeyExistsInDataFetcherMap(specUnderTest, "Query.cTopField") + checkIfKeyExistsInDataFetcherMap(specUnderTest, "Query._namespace") + checkIfKeyExistsInDataFetcherMap(specUnderTest, "Query.arootField") + checkIfKeyExistsInDataFetcherMap(specUnderTest, "Query.bTopField") + checkIfKeyExistsInDataFetcherMap(specUnderTest, "AObjectType.cTopField") + executionResult.getErrors().isEmpty() executionResult?.data?.bTopField?.size() == 2 executionResult?.data?.bTopField[0]?.size() == 2 diff --git a/src/test/groovy/com/intuit/graphql/orchestrator/integration/TopLevelStitchingSpec.groovy b/src/test/groovy/com/intuit/graphql/orchestrator/integration/TopLevelStitchingSpec.groovy index 6c24a044..6efef23d 100644 --- a/src/test/groovy/com/intuit/graphql/orchestrator/integration/TopLevelStitchingSpec.groovy +++ b/src/test/groovy/com/intuit/graphql/orchestrator/integration/TopLevelStitchingSpec.groovy @@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableMap import com.intuit.graphql.orchestrator.ServiceProvider import com.intuit.graphql.orchestrator.TestHelper import com.intuit.graphql.orchestrator.TestServiceProvider +import com.intuit.graphql.orchestrator.schema.Operation import com.intuit.graphql.orchestrator.stitching.StitchingException +import com.intuit.graphql.orchestrator.testhelpers.SimpleMockServiceProvider import graphql.ExecutionInput import graphql.ExecutionResult import helpers.BaseIntegrationTestSpecification @@ -85,6 +87,8 @@ class TopLevelStitchingSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + compareQueryToExecutionInput(Operation.QUERY, graphqlQuery, (SimpleMockServiceProvider) personService) + compareQueryToExecutionInput(null, null, (SimpleMockServiceProvider) epsService) executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.person?.name instanceof String && data.person?.name == "Test Name" @@ -104,18 +108,22 @@ class TopLevelStitchingSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + compareQueryToExecutionInput(Operation.QUERY, graphqlQuery, (SimpleMockServiceProvider) epsService) + compareQueryToExecutionInput(null, null, (SimpleMockServiceProvider) personService) executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.Profile?.prefFirstName instanceof String && data.Profile?.prefFirstName == "First Name" data.Profile?.prefLastName instanceof String && data.Profile?.prefLastName == "Last Name" data.Profile?.version instanceof Integer && data.Profile?.version == Short.MAX_VALUE + } def "Eps service is stitched and mutation query is successful"() { given: specUnderTest = createGraphQLOrchestrator([epsMutationService, personService]) - def graphqlQuery = "mutation { upsertProfile(corpId: \"test corp\", input: {version: ${Short.MAX_VALUE}}) { prefFirstName prefLastName version } }" + def baseGraphqlQuery = "{ upsertProfile(corpId: \"test corp\", input: {version: ${Short.MAX_VALUE}}) { prefFirstName prefLastName version } }" + def graphqlQuery = "mutation " + baseGraphqlQuery ExecutionInput executionInput = createExecutionInput(graphqlQuery) @@ -123,6 +131,8 @@ class TopLevelStitchingSpec extends BaseIntegrationTestSpecification { ExecutionResult executionResult = specUnderTest.execute(executionInput).get() then: + compareQueryToExecutionInput(Operation.MUTATION, baseGraphqlQuery, (SimpleMockServiceProvider) epsMutationService) + compareQueryToExecutionInput(null, null, (SimpleMockServiceProvider) personService) executionResult.getErrors().isEmpty() Map data = executionResult.getData() data.upsertProfile?.prefFirstName instanceof String && data.upsertProfile?.prefFirstName == "First Name" diff --git a/src/test/groovy/helpers/BaseIntegrationTestSpecification.groovy b/src/test/groovy/helpers/BaseIntegrationTestSpecification.groovy index 512d327a..e77d3845 100644 --- a/src/test/groovy/helpers/BaseIntegrationTestSpecification.groovy +++ b/src/test/groovy/helpers/BaseIntegrationTestSpecification.groovy @@ -2,6 +2,7 @@ package helpers import com.intuit.graphql.orchestrator.GraphQLOrchestrator import com.intuit.graphql.orchestrator.ServiceProvider +import com.intuit.graphql.orchestrator.schema.Operation import com.intuit.graphql.orchestrator.schema.RuntimeGraph import com.intuit.graphql.orchestrator.stitching.SchemaStitcher import com.intuit.graphql.orchestrator.testhelpers.MockServiceProvider @@ -110,6 +111,43 @@ class BaseIntegrationTestSpecification extends Specification { createExecutionInput(graphqlQuery, Collections.emptyMap()) } + static boolean compareQueryToExecutionInput(Operation operation, String query, + SimpleMockServiceProvider simpleMockServiceProvider) { + if (query == null) { + return getExecutionInputQueryNoSpace(simpleMockServiceProvider) == null + } + else { + String graphQuery = (operation != null) ? operation.toString().toLowerCase() + + operation.toString().toUpperCase() + query + : query + graphQuery = graphQuery.replaceAll("\\s", ""); + return (graphQuery) == getExecutionInputQueryNoSpace(simpleMockServiceProvider) + } + } + + static String getExecutionInputQueryNoSpace(SimpleMockServiceProvider simpleMockServiceProvider) { + String query = getExecutionInputQuery(simpleMockServiceProvider) + return query != null ? query.replaceAll("\\s", "") : null + } + + static String getExecutionInputQuery(SimpleMockServiceProvider simpleMockServiceProvider) { + try { + Object executionInputArgs = simpleMockServiceProvider.executionInputArgumentCaptor.capturingMatcher.arguments + return (executionInputArgs != null && !executionInputArgs.isEmpty()) + ? executionInputArgs.get(0).query + : null; + } catch (NullPointerException e) { + return null; // NPE hidden as its expected to be thrown + } + } + + static String checkIfKeyExistsInDataFetcherMap(GraphQLOrchestrator graphQLOrchestrator, String key){ + return graphQLOrchestrator.runtimeGraph.codeRegistry.dataFetcherMap.entrySet().stream().anyMatch( + { entry -> + (String.format("%s.%s", entry.getKey().getTypeName(), entry.getKey().getFieldName().toString()) + != key) }) + } + ExecutionInput getCapturedDownstreamExecutionInput() { return testService.getExecutionInputArgumentCaptor().getValue() }