コード例 #1
0
        public async Task IteratingACollection_CallsResolutions_Correctly()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <SimpleExecutionController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText("query Operation1{  simple {  collectionQueryMethod { property1 property2 } } }");
            builder.AddOperationName("Operation1");

            // supply no values, allowing the defaults to take overand returning the single
            // requested "Property1" with the default string defined on the method.
            var result = await server.RenderResult(builder);

            var output = @"{
                ""data"" : {
                    ""simple"": {
                        ""collectionQueryMethod"": [
                            { ""property1"": ""string0"", ""property2"": 0 },
                            { ""property1"": ""string1"", ""property2"": 1 },
                            { ""property1"": ""string2"", ""property2"": 2 }
                            ]
                        }
                    }
                }";

            CommonAssertions.AreEqualJsonStrings(
                output,
                result);
        }
コード例 #2
0
        public async Task ProductionDefaults_CamelCasedTypeNames()
        {
            var builder = new TestServerBuilder()
                          .AddGraphType <FanController>();

            builder.AddGraphQL(o =>
            {
                o.DeclarationOptions.GraphNamingFormatter = new GraphNameFormatter(typeNameStrategy: GraphNameFormatStrategy.CamelCase);
            });

            var server = builder.Build();

            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("{ __type(name: \"fanItem\"){ name, kind} }");

            var result = await server.RenderResult(queryBuilder).ConfigureAwait(false);

            var expectedResult = @"
            {
                ""data"" : {
                    ""__type"": {
                        ""name"" : ""fanItem"",
                        ""kind"" : ""OBJECT"",
                    }
                }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedResult, result);
        }
コード例 #3
0
        public async Task NestedScalarVariable_IsUsedInsteadOfDefault()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <InputValueController>()
                         .AddGraphQL(o =>
            {
                o.ResponseOptions.ExposeExceptions = true;
            })
                         .Build();

            // variable passed is just 1 value of hte input object (not the whole thing)
            var builder = server.CreateQueryContextBuilder();

            builder.AddVariableData("{ \"variable1\" : \"stringPassedValue\" }");
            builder.AddQueryText("query($variable1: String){ " +
                                 "complexValue(arg1: { property1: $variable1, property2: 15} ) " +
                                 "{ property1 property2 } }");
            var result = await server.RenderResult(builder);

            var expected = @"{
                                ""data"" : {
                                  ""complexValue"" : {
                                        ""property1"" : ""stringPassedValue"",
                                        ""property2"" : 15
                                    }
                                }
                            }";

            CommonAssertions.AreEqualJsonStrings(expected, result);
        }
コード例 #4
0
        public async Task ProductionDefaults_UpperCaseFieldNames()
        {
            var builder = new TestServerBuilder()
                          .AddGraphType <FanController>();

            builder.AddGraphQL(o =>
            {
                o.DeclarationOptions.GraphNamingFormatter = new GraphNameFormatter(fieldNameStrategy: GraphNameFormatStrategy.UpperCase);
            });

            var server = builder.Build();

            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("{ RETRIEVEFAN(NAME: \"bob\"){ ID, NAME, FANSPEED} }");

            var result = await server.RenderResult(queryBuilder).ConfigureAwait(false);

            var expectedResult = @"
            {
                ""data"" : {
                    ""RETRIEVEFAN"": {
                        ""ID"" : 1,
                        ""NAME"" : ""bob"",
                        ""FANSPEED"" : ""MEDIUM""
                    }
                }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedResult, result);
        }
コード例 #5
0
        public async Task ExtendedTypeOfToAKnownGraphType_ShouldBeProcessed()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <MixedReturnTypeController>()
                         .Build();

            // controller returns a MixedReturnTypeB, but is declared in the schema as MixedReturnTypeA
            // (the return type of the controller method signature)
            // MixedB should be able to masquerade as MixedA
            var builder = server.CreateQueryContextBuilder()
                          .AddQueryText("query  { createReturnObject { field1 }}");

            // the returned object should be carried forward to produce a result
            var result = await server.RenderResult(builder);

            var expectedOutput =
                @"{
                ""data"": {
                    ""createReturnObject"" : {
                        ""field1"": ""FieldValue1""
                    }
                }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedOutput, result);
        }
コード例 #6
0
        public async Task Schema_QueryAndMutationTypeNames_ReturnsValidData()
        {
            var serverBuilder = new TestServerBuilder();
            var server        = serverBuilder.AddGraphType <SodaCanController>()
                                .Build();

            var builder = server.CreateQueryContextBuilder();

            // need to resolve type field now
            builder.AddQueryText(@"{
                               __schema
                              {
                                 queryType { name }
                                 mutationType { name }
                              }
                            }");

            var response = await server.RenderResult(builder);

            var output =
                @"{
                    ""data"": {
                        ""__schema"" : {
                            ""queryType"" : {""name"": ""Query""},
                            ""mutationType"" : null
                        }
                    }
                }";

            CommonAssertions.AreEqualJsonStrings(output, response);
        }
コード例 #7
0
        public async Task ProductionDefaults_LowerCaseEnumValues()
        {
            var builder = new TestServerBuilder()
                          .AddGraphType <FanController>();

            builder.AddGraphQL(o =>
            {
                o.DeclarationOptions.GraphNamingFormatter = new GraphNameFormatter(enumValueStrategy: GraphNameFormatStrategy.LowerCase);
            });

            var server = builder.Build();

            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("{ retrieveFan(name: \"bob\"){ id, name, fanSpeed} }");

            var result = await server.RenderResult(queryBuilder).ConfigureAwait(false);

            var expectedResult = @"
            {
                ""data"" : {
                    ""retrieveFan"": {
                        ""id"" : 1,
                        ""name"" : ""bob"",
                        ""fanSpeed"" : ""medium""
                    }
                }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedResult, result);
        }
コード例 #8
0
        public async Task TypeNameMetaField_OnObject_returnsValue()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <SimpleExecutionController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText("query Operation1{  simple {  simpleQueryMethod { property1 __typename} } }");
            builder.AddOperationName("Operation1");

            // supply no values, allowing the defaults to take overand returning the single
            // requested "Property1" with the default string defined on the method.
            var result = await server.RenderResult(builder);

            CommonAssertions.AreEqualJsonStrings(
                @"{
                    ""data"": {
                        ""simple"": {
                                ""simpleQueryMethod"" : {
                                        ""property1"" : ""default string"",
                                        ""__typename"" : ""TwoPropertyObject""
                                }
                        }
                    }
                 }",
                result);
        }
コード例 #9
0
        public async Task SingleType_ScalarType_ReturnsValidData()
        {
            var serverBuilder = new TestServerBuilder();

            // contains an enum CapacityType on SodaCanBuildingData
            var server  = serverBuilder.AddGraphType <SodaCanBuildingController>().Build();
            var builder = server.CreateQueryContextBuilder();

            // need to resolve type field now
            builder.AddQueryText(@"{
                               __type(name: ""Int"")
                              {
                                name  kind
                                }
                            }");

            var response = await server.RenderResult(builder);

            var output = @"
                            {
                                ""data"": {
                                   ""__type"": {
                                            ""name"": ""Int"",
                                            ""kind"" : ""SCALAR"",
                                        }
                                }
                            }";

            CommonAssertions.AreEqualJsonStrings(output, response);
        }
コード例 #10
0
        public async Task SingleFieldResolution_NoSuppliedVariables_ResolvePathThroughController_CallsResolutions_Correctly()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <SimpleExecutionController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"query Operation1($var1: String = ""not-default string"") {
                                simple{
                                    simpleQueryMethod (arg1: $var1) {
                                        property1} } }");
            builder.AddOperationName("Operation1");

            // supply no values, allowing the defaults to take overand returning the single
            // requested "Property1" with the default string defined on the method.
            var result = await server.RenderResult(builder);

            CommonAssertions.AreEqualJsonStrings(
                @"{
                    ""data"": {
                        ""simple"": {
                            ""simpleQueryMethod"" : {
                                ""property1"" : ""not-default string""
                            }
                        }
                    }
                }",
                result);
        }
コード例 #11
0
        public async Task ListOfEnums_ProjectsIntoAListCorrectly()
        {
            // test the case where a leaf graph type is returne das a
            // list List<int>, List<string>, List<SomeEnum> etc.
            // ensure the data items are properly projected into a list
            // when rendered
            var server = new TestServerBuilder()
                         .AddGraphType <ListController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder()
                          .AddQueryText("query  { createEnumList }");

            // ensure its a string when printed
            var result = await server.RenderResult(builder);

            var expectedOutput =
                @"{
                    ""data"": {
                       ""createEnumList"" : [""TESTVALUE1"", ""TESTVALUE2""]
                    }
                  }";

            CommonAssertions.AreEqualJsonStrings(expectedOutput, result);
        }
コード例 #12
0
        public async Task ObjectMethodAsField_Asyncronously_ResolvesCorrectly()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <ObjectMethodController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder()
                          .AddQueryText("query  { objects {  retrieveObject { asyncMethod} } }");

            // call the child AsyncMethod (which is a asycrnous method described as a field on an object, not a controller)
            // ensure it returns a value
            var result = await server.RenderResult(builder);

            var expectedOutput =
                @"{
                    ""data"": {
                       ""objects"" : {
                                ""retrieveObject"" : {
                                    ""asyncMethod"" : 8
                                }
                            }
                        }
                   }";

            CommonAssertions.AreEqualJsonStrings(expectedOutput, result);
        }
コード例 #13
0
        public async Task Execution_GeneralReturnCheck()
        {
            var(processor, httpContext) = this.CreateQueryArtifacts(new GraphQueryData()
            {
                Query         = "{ candy { count } }",
                OperationName = null,
            });

            var response = httpContext.Response;
            await processor.Invoke(httpContext);

            // headers that should be set
            Assert.IsTrue(response.Headers.ContainsKey(HeaderNames.ContentType), "No content type header");
            Assert.IsTrue(response.Headers.ContainsKey(Constants.ServerInformation.SERVER_INFORMATION_HEADER), "No server info header");

            // check the response body that was written
            var expectedOutput = @"
                {
                    ""data"" : {
                        ""candy"" : {
                              ""count"" : 5
                        }
                    }
                }";

            string responseText;

            response.Body.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(response.Body))
                responseText = reader.ReadToEnd();

            CommonAssertions.AreEqualJsonStrings(expectedOutput, responseText);
        }
コード例 #14
0
        public async Task ExceptionOnMessage_RendersAsExpected()
        {
            var fixedDate = DateTimeOffset.UtcNow.UtcDateTime;

            var builder = new TestServerBuilder()
                          .AddGraphType <SimpleExecutionController>();

            builder.AddGraphQL(o =>
            {
                o.ResponseOptions.TimeStampLocalizer = (_) => fixedDate;
            });

            var server       = builder.Build();
            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("query Operation1{  simple  {  throwsException  } }");

            var response = await server.ExecuteQuery(queryBuilder);

            var writer = new DefaultResponseWriter <GraphSchema>(server.Schema);
            var result = await this.WriteResponse(writer, response);

            var exceptionStackTrace = JsonEncodedText.Encode(response.Messages[0].Exception.StackTrace, JavaScriptEncoder.UnsafeRelaxedJsonEscaping).ToString();

            var expectedData = @"
                                {
                                  ""errors"": [
                                    {
                                      ""message"": ""Operation failed."",
                                      ""locations"": [
                                        {
                                          ""line"": 1,
                                          ""column"": 31
                                        }
                                      ],
                                      ""path"": [
                                        ""simple"",
                                        ""throwsException""
                                      ],
                                      ""extensions"": {
                                        ""code"": ""UNHANDLED_EXCEPTION"",
                                        ""timestamp"": """ + fixedDate.ToRfc3339String() + @""",
                                        ""severity"": ""CRITICAL"",
                                        ""exception"": {
                                          ""type"": ""InvalidOperationException"",
                                          ""message"": ""This is an invalid message"",
                                          ""stacktrace"": """ + exceptionStackTrace + @""",
                                        }
                                      }
                                    }
                                  ]
                                }";

            CommonAssertions.AreEqualJsonStrings(
                expectedData,
                result);
        }
コード例 #15
0
        public async Task BatchExtension_SingleQueryForSingleSybling_ExecutesOnce_AndReturnsData()
        {
            var counter      = new Dictionary <string, int>();
            var batchService = new Mock <IBatchCounterService>();

            batchService.Setup(x => x.CallCount).Returns(counter);

            var serverBuilder = new TestServerBuilder()
                                .AddGraphType <BatchController>();

            serverBuilder.AddSingleton(batchService.Object);
            var server = serverBuilder.Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText("query { batch { fetchData { property1, property2, sybling { syblingId, name }}}}");

            var response = await server.RenderResult(builder);

            var expected = @"
               {
                  ""data"": {
                    ""batch"" : {
                            ""fetchData"": [
                            {
                                ""property1"": ""object0"",
                                ""property2"": 0,
                                ""sybling"": {
                                    ""syblingId"": ""object0"",
                                    ""name"": ""object0_sybling""
                                }
                            },
                            {
                                ""property1"": ""object1"",
                                ""property2"": 1,
                                ""sybling"": {
                                    ""syblingId"": ""object1"",
                                    ""name"": ""object1_sybling""
                                }
                            },
                            {
                                ""property1"": ""object2"",
                                ""property2"": 2,
                                ""sybling"": {
                                    ""syblingId"": ""object2"",
                                    ""name"": ""object2_sybling""
                                }
                            }]
                        }
                    }
                }";

            CommonAssertions.AreEqualJsonStrings(expected, response);
            Assert.AreEqual(1, counter[nameof(BatchController.PrimaryDataFetch)]);
            Assert.IsFalse(counter.ContainsKey(nameof(BatchController.FetchChildren)));
            Assert.AreEqual(1, counter[nameof(BatchController.FetchSibling)]);
        }
コード例 #16
0
        public async Task SingleType_EnumType_ReturnsValidData()
        {
            var serverBuilder = new TestServerBuilder();

            // contains an enum CapacityType on SodaCanBuildingData
            var server = serverBuilder.AddGraphType <SodaCanBuildingController>()
                         .AddSchemaBuilderAction(o =>
            {
                o.Options.ResponseOptions.ExposeExceptions = true;
            })
                         .Build();
            var builder = server.CreateQueryContextBuilder();

            // need to resolve type field now
            builder.AddQueryText(@"{
                               __type(name: ""CapacityType"")
                              {
                                name
                                kind
                                enumValues (includeDeprecated: true) {name description isDeprecated deprecationReason}
                                }
                            }");

            var response = await server.RenderResult(builder);

            var output = @"
                            {
                            ""data"": {
                                  ""__type"": {
                                            ""name"": ""CapacityType"",
                                            ""kind"" : ""ENUM"",
                                            ""enumValues"": [
                                            {
                                                ""name"": ""SMALL"",
                                                ""description"": ""A small room"",
                                                ""isDeprecated"": false,
                                                ""deprecationReason"" : null,
                                            },
                                            {
                                                ""name"": ""MEDIUM"",
                                                ""description"": null,
                                                ""isDeprecated"": false,
                                                ""deprecationReason"" : null,
                                            },
                                            {
                                                ""name"": ""LARGE"",
                                                ""description"": null,
                                                ""isDeprecated"": true,
                                                ""deprecationReason"" : ""Room too big"",
                                            },
                                        ]}
                                    }
                                }";

            CommonAssertions.AreEqualJsonStrings(output, response);
        }
コード例 #17
0
        public async Task BasicBranch_ViaNamedFragments_RendersCorrectly()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <FragmentProcessingController>()
                         .Build();
            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"
                        query {
                            fragTester {
                                makeHybridData {
                                    ...aData
                                    ...bData
                                }
                            }
                        }

                        fragment aData on FragmentDataA{
                           property1
                        }

                        fragment bData on FragmentDataB{
                           property2
                           property1
                        }");

            var r = await server.ExecuteQuery(builder);

            var result = await server.RenderResult(builder);

            // note the ordering on bData fragment
            var expectedReslt = @"
                                {
                                    ""data"" : {
                                          ""fragTester"": {
                                                ""makeHybridData"": [
                                                {
                                                    ""property1"": ""fragmentA_prop1_0""
                                                },
                                                {
                                                    ""property1"": ""fragmentA_prop1_1""
                                                },
                                                {
                                                    ""property2"": ""fragmentB_prop2_0"",
                                                    ""property1"": ""fragmentB_prop1_0""
                                                },
                                                {
                                                    ""property2"": ""fragmentB_prop2_1"",
                                                    ""property1"": ""fragmentB_prop1_1""
                                                }]
                                            }
                                    }
                                }";

            CommonAssertions.AreEqualJsonStrings(expectedReslt, result);
        }
コード例 #18
0
        public async Task TypeExtension_AppliedToAnInterface_CanBeActedOnByMultipleConcreteObjects()
        {
            var server = new TestServerBuilder()

                         .AddGraphType <ConcreteObjectA>()
                         .AddGraphType <ConcreteObjectB>()
                         .AddGraphType <InterfaceExtensionController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"
                                {
                                    multiObjects {
                                       firstName
                                       fullName
                                    }
                                }");

            // fullName is an type extension keyed on the interface that both object types inherit it does not exist as a declared
            // member of ObjectA, B or the common interface
            // the interface explicitly DOES NOT declare FirstName or LastName ensuring they must be generated from the
            // concrete types
            var result = await server.RenderResult(builder);

            // output combines declared methods on concrete objects, firstName, and the interface extension, fullName
            var expectedOutput = @"
                        {
                          ""data"": {
                                    ""multiObjects"": [
                                    {
                                        ""firstName"" : ""0A_prop1"",
                                        ""fullName"": ""0A_prop1 0A_prop2""
                                    },
                                    {
                                        ""firstName"" : ""1A_prop1"",
                                        ""fullName"": ""1A_prop1 1A_prop2""
                                    },
                                    {
                                        ""firstName"" : ""0B_prop1"",
                                        ""fullName"": ""0B_prop1 0B_prop2""
                                    },
                                    {
                                        ""firstName"" : ""1B_prop1"",
                                        ""fullName"": ""1B_prop1 1B_prop2""
                                    }
                                    ]
                                }
                            }";

            CommonAssertions.AreEqualJsonStrings(expectedOutput, result);
        }
コード例 #19
0
        public async Task SingleType_WrappedTypeOnField_ReturnsValidData()
        {
            var serverBuilder = new TestServerBuilder();
            var server        = serverBuilder.AddGraphType <VendingMachineController>().Build();
            var builder       = server.CreateQueryContextBuilder();

            // need to resolve type field now
            builder.AddQueryText(@"{
                               __type(name: ""Query_Vending"")
                              {
                                name
                                fields{
                                    name
                                    type {
                                        kind
                                        ofType {
                                            kind
                                            ofType {name kind }
                                        }
                                    }
                                }
                              }
                            }");

            var response = await server.RenderResult(builder);

            var output = @"
                        {
                        ""data"": {
                              ""__type"": {
                                        ""name"": ""Query_Vending"",
                                        ""fields"": [
                                        {
                                            ""name"": ""cansPerRow"",
                                            ""type"": {
                                                ""kind"": ""LIST"",
                                                ""ofType"": {
                                                    ""kind"": ""NON_NULL"",
                                                    ""ofType"": {
                                                        ""name"": ""Int"",
                                                        ""kind"": ""SCALAR""
                                                    }
                                                }
                                            }
                                        }]
                                    }
                                }
                            }";

            CommonAssertions.AreEqualJsonStrings(output, response);
        }
コード例 #20
0
        public void ErrorMessage_WithId_SerializesWithIdParameter()
        {
            var dt     = DateTime.UtcNow;
            var server = new TestServerBuilder()
                         .AddGraphController <ApolloDataMessageController>()
                         .AddSubscriptionServer()
                         .AddGraphQL(options =>
            {
                options.ResponseOptions.TimeStampLocalizer = (time) => dt;
            })
                         .Build();

            var converter = new ApolloServerErrorMessageConverter(server.Schema);

            var message = new ApolloServerErrorMessage(
                "an error occured",
                Constants.ErrorCodes.BAD_REQUEST,
                GraphMessageSeverity.Warning,
                "prev123",
                lastMessageType: ApolloMessageType.START,
                clientProvidedId: "abc123");

            var options = new JsonSerializerOptions();

            options.Converters.Add(converter);
            var response = JsonSerializer.Serialize(message, message.GetType(), options);

            // error message should render a single IGraphMessage
            // that is normally part of the errors collection on a standard response
            var expected = @"
            {
                ""id"": ""abc123"",
                ""type"":""error"",
                ""payload"":{
                    ""message"":""an error occured"",
                    ""extensions"":{
                        ""code"":""BAD_REQUEST"",
                        ""timestamp"":""{dateString}"",
                        ""severity"":""WARNING"",
                        ""metaData"":{
                            ""lastMessage_id"":""prev123"",
                            ""lastMessage_type"":""start""
                        }
                    }
                }
            }";

            expected = expected.Replace("{dateString}", dt.ToRfc3339String());

            CommonAssertions.AreEqualJsonStrings(expected, response);
        }
コード例 #21
0
        public async Task WhenAnInterfaceIsSpreadInAUnion_TheUnionMembersThatImplementTheInterface_ShouldReturnInterfaceFields()
        {
            // sourceDataInheritance returns a union type (FragmentDataA | FragmentDataB | FragmentDataC)
            // All Three implement interface graph type FragmentDataItem and should include any fields in the "sampleFrag" fragment
            // which is typed to the interface
            var server = new TestServerBuilder()
                         .AddGraphType <FragmentProcessingController>()
                         .AddGraphType <IFragmentDataItem>()
                         .AddSchemaBuilderAction(o =>
            {
                o.Options.ResponseOptions.ExposeExceptions = true;
            })
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"
                            query {
                                fragTester {
                                    sourceDataInheritance {
                                        ...sampleFrag
                                    }
                                }
                            }

                            fragment sampleFrag on FragmentDataItem {
                               property1
                            }");

            var expectedResult = @"
                                    {
                                        ""data"" : {
                                              ""fragTester"": {
                                                    ""sourceDataInheritance"": [
                                                    {
                                                        ""property1"": ""fragmentA_prop1_0""
                                                    },
                                                    {
                                                        ""property1"": ""fragmentB_prop1_0""
                                                    },
                                                    {
                                                        ""property1"": ""fragmentA_prop1_FromC""
                                                    }]
                                                }
                                        }
                                    }";

            var result = await server.RenderResult(builder);

            CommonAssertions.AreEqualJsonStrings(expectedResult, result);
        }
コード例 #22
0
        public async Task Schema_TypeNameAndKind_ThroughAFragment_ReturnsValidData()
        {
            var serverBuilder = new TestServerBuilder();
            var server        = serverBuilder.AddGraphType <SodaCanController>().Build();
            var builder       = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"
                            {
                               __schema
                              {
                                 types {
                                    ...FullType
                                }
                              }
                            }
                             fragment FullType on __Type {
                                  kind
                                  name
                            }");

            var response = await server.RenderResult(builder);

            var output = @"
                        {
                            ""data"": {
                                ""__schema"": {
                                    ""types"": [
                                      { ""name"": ""__DirectiveLocation"", ""kind"": ""ENUM"" },
                                      { ""name"": ""__InputValue"", ""kind"": ""OBJECT"" },
                                      { ""name"": ""__Directive"", ""kind"": ""OBJECT"" },
                                      { ""name"": ""__Type"", ""kind"": ""OBJECT"" },
                                      { ""name"": ""__TypeKind"", ""kind"": ""ENUM"" },
                                      { ""name"": ""__Schema"", ""kind"": ""OBJECT"" },
                                        { ""name"": ""__Field"", ""kind"": ""OBJECT"" },
                                        { ""name"": ""__EnumValue"", ""kind"": ""OBJECT"" },
                                        { ""name"": ""String"", ""kind"": ""SCALAR"" },
                                        { ""name"": ""Boolean"", ""kind"": ""SCALAR"" },
                                        { ""name"": ""Int"", ""kind"": ""SCALAR"" },
                                        { ""name"": ""SodaCan"", ""kind"": ""OBJECT"" },
                                        { ""name"": ""Query_Sodas"", ""kind"": ""OBJECT"" },
                                        { ""name"": ""Query"", ""kind"": ""OBJECT"" },
                                        ]
                                }
                            }
                        }";

            CommonAssertions.AreEqualJsonStrings(output, response);
        }
コード例 #23
0
        public async Task WhenNoLeafValuesAreRequested_ItemIsReturnedAsNullAndPropegated()
        {
            var server = new TestServerBuilder()
                         .AddGraphType <SimpleExecutionController>()
                         .Build();

            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText("query Operation1{  simple {  simpleQueryMethod  } }");
            builder.AddOperationName("Operation1");

            var result = await server.RenderResult(builder);

            CommonAssertions.AreEqualJsonStrings(
                "{ \"data\" : null }",
                result);
        }
コード例 #24
0
        public void GeneralMessage_WithoutId_SerializesCorrectly()
        {
            var message   = new ApolloServerAckOperationMessage();
            var converter = new ApolloMessageConverter();

            var options = new JsonSerializerOptions();

            options.Converters.Add(converter);
            var response = JsonSerializer.Serialize(message, typeof(ApolloMessage), options);

            var expected = @"
            {
                ""type"" : ""connection_ack""
            }";

            CommonAssertions.AreEqualJsonStrings(expected, response);
        }
コード例 #25
0
        public void CompleteMessage_WithoutId_SerializesWithNoIdParameter()
        {
            var message   = new ApolloServerCompleteMessage(null);
            var converter = new ApolloServerCompleteMessageConverter();

            var options = new JsonSerializerOptions();

            options.Converters.Add(converter);
            var response = JsonSerializer.Serialize(message, message.GetType(), options);

            var expected = @"
            {
                ""type"" : ""complete"",
            }";

            CommonAssertions.AreEqualJsonStrings(expected, response);
        }
コード例 #26
0
        private static void AssertApolloResponse(
            this MockClientConnection connection,
            ApolloMessageType type,
            string id,
            bool compareId,
            string expectedPayloadJson,
            bool compareJson,
            bool dequeue = true)
        {
            if (connection.ResponseMessageCount == 0)
            {
                Assert.Fail("No messages queued.");
            }

            var message = dequeue ? connection.DequeueNextReceivedMessage() : connection.PeekNextReceivedMessage();
            var str     = Encoding.UTF8.GetString(message.Data);

            var options = new JsonSerializerOptions();

            options.PropertyNameCaseInsensitive = true;
            options.AllowTrailingCommas         = true;
            options.Converters.Add(new ApolloResponseMessageConverter());

            var convertedMessage = System.Text.Json.JsonSerializer.Deserialize <ApolloResponseMessage>(str, options);

            Assert.IsNotNull(convertedMessage, "Could not deserialized response message");
            Assert.AreEqual(type, convertedMessage.Type, $"Expected message type of {type.ToString()} but got {convertedMessage.Type.ToString()}");

            if (compareJson)
            {
                if (expectedPayloadJson == null)
                {
                    Assert.IsNull(convertedMessage.Payload);
                }
                else
                {
                    CommonAssertions.AreEqualJsonStrings(expectedPayloadJson, convertedMessage.Payload);
                }
            }

            if (compareId)
            {
                Assert.AreEqual(id, convertedMessage.Id);
            }
        }
コード例 #27
0
        public async Task WithAuthorizedUser_AllFieldsResolve()
        {
            var serverBuilder = new TestServerBuilder()
                                .AddGraphController <SecuredController>()
                                .AddGraphQL(options =>
            {
                options.AuthorizationOptions.Method = AuthorizationMethod.PerRequest;
            });

            serverBuilder.User.Authenticate();

            // should produce no errors and render both fields
            var server  = serverBuilder.Build();
            var builder = server.CreateQueryContextBuilder();

            builder.AddQueryText(@"
                    query {
                        unsecured {
                            property1
                            property2
                        }
                        secured {
                           property1
                           property2
                        }
                    }");

            var result = await server.RenderResult(builder);

            var expectedResults = @"
            {
              ""data"": {
                ""unsecured"": {
                  ""property1"": ""unsecure object"",
                  ""property2"": 1
                },
                ""secured"": {
                  ""property1"": ""secured object"",
                  ""property2"": 5
                }
              }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedResults, result);
        }
コード例 #28
0
        public async Task MetaDataOnMessage_RendersAsExpected()
        {
            var fixedDate = DateTimeOffset.UtcNow.UtcDateTime;

            var builder = new TestServerBuilder()
                          .AddGraphType <SimpleExecutionController>();

            builder.AddGraphQL(o =>
            {
                o.ResponseOptions.TimeStampLocalizer = (_) => fixedDate;
            });

            var server       = builder.Build();
            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("query Operation1{  simple  {  customMessage  } }");

            var response = await server.ExecuteQuery(queryBuilder);

            var writer = new DefaultResponseWriter <GraphSchema>(server.Schema);
            var result = await this.WriteResponse(writer, response);

            var expectedData = @"
                {
                  ""errors"": [
                    {
                      ""message"": ""fail text"",
                      ""extensions"": {
                        ""code"": ""fail code"",
                        ""timestamp"": """ + fixedDate.ToRfc3339String() + @""",

                        ""severity"": ""CRITICAL"",
                        ""metaData"" : {
                            ""customKey1"": ""customValue1""
                        }
                      }
                    }
                  ]
                }";

            // no errors collection generated because no errors occured.
            CommonAssertions.AreEqualJsonStrings(
                expectedData,
                result);
        }
コード例 #29
0
        public async Task DefaultWriteOperation_InvalidSyntax_RendersJsonWithError()
        {
            var fixedDate = DateTimeOffset.UtcNow.UtcDateTime;

            var serverBuilder = new TestServerBuilder()
                                .AddGraphType <SimpleExecutionController>();

            serverBuilder.AddGraphQL(o =>
            {
                o.ResponseOptions.TimeStampLocalizer = (_) => fixedDate;
            });

            var server       = serverBuilder.Build();
            var queryBuilder = server.CreateQueryContextBuilder();

            queryBuilder.AddQueryText("query Operation1{  simple \n {{  simpleQueryMethod { property1} } }");

            var response = await server.ExecuteQuery(queryBuilder);

            var writer = new DefaultResponseWriter <GraphSchema>(server.Schema);
            var result = await this.WriteResponse(writer, response);

            var expectedData = @"
                {
                  ""errors"": [
                            {
                                ""message"": ""Invalid query. Expected 'NameToken' but received 'ControlToken'"",
                                ""locations"": [
                                {
                                    ""line"": 2,
                                    ""column"": 3
                                }],
                                ""extensions"": {
                                    ""code"": ""SYNTAX_ERROR"",
                                    ""timestamp"": """ + fixedDate.ToRfc3339String() + @""",
                                    ""severity"": ""CRITICAL""
                                }
                            }]
                }";

            // no errors collection generated because no errors occured.
            CommonAssertions.AreEqualJsonStrings(
                expectedData,
                result);
        }
コード例 #30
0
        public async Task IndeterminateUnionType_ShouldCallIntoUnionProxyResolveMethod_AndProduceResult()
        {
            MixedTypeUnion.TotalCallCount = 0;
            var server = new TestServerBuilder()
                         .AddGraphType <MixedReturnTypeController>()
                         .AddSchemaBuilderAction(a =>
            {
                a.Options.ResponseOptions.ExposeExceptions = true;
            })
                         .Build();

            // controller actually returns a MixedReturnTypeC, but is declared in the schema as
            // MixedUnionType (of A and B)
            // MixedC inherits from both A and B and could be either
            // the library should call into MixedUnionType and ask it to resolve the relationship
            //
            // mixedUnion should return TypeA, thus rendering field 1
            var builder = server.CreateQueryContextBuilder()
                          .AddQueryText(
                @"query  {
                    createIndeterminateReturn {
                        ... on MixedReturnTypeB {
                                field2
                        }
                        ... on MixedReturnTypeA {
                                field1
                        }
                }}");

            // the returned object should be carried forward to produce a result
            var result = await server.RenderResult(builder);

            var expectedOutput =
                @"{
                ""data"": {
                    ""createIndeterminateReturn"" : {
                        ""field1"": ""FieldValue1""
                    }
                }
            }";

            CommonAssertions.AreEqualJsonStrings(expectedOutput, result);
            Assert.AreEqual(1, MixedTypeUnion.TotalCallCount);
        }