// Copyright © WireMock.Net //#if GRAPHQL using System; using System.Collections.Generic; using FluentAssertions; using GraphQLParser.Exceptions; using WireMock.Exceptions; using WireMock.Matchers; using WireMock.Models; using Xunit; namespace WireMock.Net.Tests.Matchers; public class GraphQLMatcherTests { private const string TestSchema = @" scalar DateTime input MessageInput { date: DateTime content: String author: String } type Message { id: ID! content: String author: String } type Mutation { createMessage(input: MessageInput): Message createAnotherMessage(date: DateTime, content: String, author: String): Message updateMessage(id: ID!, input: MessageInput): Message } type Query { greeting: String students: [Student] studentById(id: ID!):Student } type Student { id: ID! firstName: String lastName: String fullName: String }"; [Fact] public void GraphQLMatcher_For_ValidSchema_And_CorrectQuery_IsMatch() { // Arrange var input = "{\"query\":\"{\\r\\n students {\\r\\n fullName\\r\\n id\\r\\n }\\r\\n}\"}"; // Act var matcher = new GraphQLMatcher(TestSchema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(TestSchema); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_CorrectGraphQL_Query_IsMatch() { // Arrange var input = @"{ ""query"": ""query ($sid: ID!)\r\n{\r\n studentById(id: $sid) {\r\n fullName\r\n id\r\n }\r\n}"", ""variables"": { ""sid"": ""1"" } }"; // Act var matcher = new GraphQLMatcher(TestSchema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(TestSchema); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_CorrectGraphQL_Mutation_IsMatch() { // Arrange var input = @"{ ""query"": ""mutation CreateAnotherMessage($date: DateTime!, $content: String!, $author: String!) { createAnotherMessage(date: $date, content: $content, author: $author) { id } }"", ""variables"": { ""date"": ""2007-12-03T10:15:30Z"", ""content"": ""--content--"", ""author"": ""--author--"" } }"; // Act var matcher = new GraphQLMatcher(TestSchema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(TestSchema); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_CorrectGraphQL_UsingCustomType_Mutation_IsMatch() { // Arrange // Query is provided here: https://stackoverflow.com/questions/59608833/apollo-graphql-error-query-root-type-must-be-provided const string testSchema = """ scalar DateTime scalar MyCustomScalar type Query { _empty: String } type Message { id: ID! } type Mutation { createMessage(x: MyCustomScalar, dt: DateTime): Message } """; const string input = """ { "query": "mutation CreateMessage($x: MyCustomScalar!, $dt: DateTime!) { createMessage(x: $x, dt: $dt) { id } }", "variables": { "x": 100, "dt": "2007-12-03T10:15:30Z" } } """; var customScalars = new Dictionary { { "MyCustomScalar", typeof(int) } }; // Act var matcher = new GraphQLMatcher(testSchema, customScalars); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(testSchema); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_CorrectGraphQL_UsingCustomType_But_NoDefinedCustomScalars_Mutation_IsNoMatch() { // Arrange const string testSchema = @" scalar DateTime scalar MyCustomScalar type Message { id: ID! } type Mutation { createMessage(x: MyCustomScalar, dt: DateTime): Message }"; // Act Action action = () => _ = new GraphQLMatcher(testSchema); // Assert action.Should().Throw().WithMessage("The GraphQL Scalar type 'MyCustomScalar' is not defined in the CustomScalars dictionary."); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_IncorrectQuery_IsMismatch() { // Arrange var input = @" { students { fullName id abc } }"; // Act var matcher = new GraphQLMatcher(TestSchema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Mismatch); } [Fact] public void GraphQLMatcher_For_ValidSchemaAsStringPattern_And_CorrectQuery_IsMatch() { // Arrange var input = "{\"query\":\"{\\r\\n students {\\r\\n fullName\\r\\n id\\r\\n }\\r\\n}\"}"; var schema = new StringPattern { Pattern = TestSchema }; // Act var matcher = new GraphQLMatcher(schema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Perfect); } [Fact] public void GraphQLMatcher_For_ValidSchema_And_IncorrectQueryWithError_WithThrowExceptionTrue_ReturnsError() { // Arrange var input = "{\"query\":\"{\\r\\n studentsX {\\r\\n fullName\\r\\n X\\r\\n }\\r\\n}\"}"; // Act var matcher = new GraphQLMatcher(TestSchema); var result = matcher.IsMatch(input); // Assert result.Score.Should().Be(MatchScores.Mismatch); result.Exception!.Message.Should().StartWith("Cannot query field 'studentsX' on type 'Query'"); } [Fact] public void GraphQLMatcher_For_InvalidSchema_ThrowsGraphQLSyntaxErrorException() { // Act // ReSharper disable once ObjectCreationAsStatement Action action = () => _ = new GraphQLMatcher("in va lid"); // Assert action.Should().Throw(); } } //#endif