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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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)]); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } }
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); }
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); }
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); }
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); }