Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions WireMock.Net Solution.sln
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.ConsoleApp.Usi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Tests.UsingNuGet", "test\WireMock.Net.Tests.UsingNuGet\WireMock.Net.Tests.UsingNuGet.csproj", "{BBA332C6-28A9-42E7-9C4D-A0816E52A198}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.GraphQL", "src\WireMock.Net.GraphQL\WireMock.Net.GraphQL.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A45}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -326,6 +328,10 @@ Global
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.Build.0 = Release|Any CPU
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -379,6 +385,7 @@ Global
{BFEF8990-65B3-4274-310F-7355F0B84035} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{1F80A6E6-D146-4E40-9EA8-49DB8494239F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{BBA332C6-28A9-42E7-9C4D-A0816E52A198} = {0BB8B634-407A-4610-A91F-11586990767A}
{B6269AAC-170A-4346-8B9A-444DED3D9A45} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
Expand Down
5 changes: 5 additions & 0 deletions src/WireMock.Net.Abstractions/Models/GraphQL/ISchemaData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright © WireMock.Net

namespace WireMock.Models.GraphQL;

public interface ISchemaData;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net

#if GRAPHQL
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
Expand All @@ -14,17 +13,18 @@
using Stef.Validation;
using WireMock.Exceptions;
using WireMock.Extensions;
using WireMock.Matchers.Models;
using WireMock.GraphQL.Models;
using WireMock.Models;
using WireMock.Util;
using WireMock.Models.GraphQL;
using WireMock.Utils;

namespace WireMock.Matchers;

/// <summary>
/// GrapQLMatcher Schema Matcher
/// </summary>
/// <inheritdoc cref="IStringMatcher"/>
public class GraphQLMatcher : IStringMatcher
public class GraphQLMatcher : IGraphQLMatcher
{
private sealed class GraphQLRequest
{
Expand Down Expand Up @@ -54,7 +54,7 @@ private sealed class GraphQLRequest
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
public GraphQLMatcher(
AnyOf<string, StringPattern, ISchema> schema,
AnyOf<string, StringPattern, ISchemaData> schema,
MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch,
MatchOperator matchOperator = MatchOperator.Or
) : this(schema, null, matchBehaviour, matchOperator)
Expand All @@ -69,7 +69,7 @@ public GraphQLMatcher(
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
public GraphQLMatcher(
AnyOf<string, StringPattern, ISchema> schema,
AnyOf<string, StringPattern, ISchemaData> schema,
IDictionary<string, Type>? customScalars,
MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch,
MatchOperator matchOperator = MatchOperator.Or
Expand All @@ -94,7 +94,7 @@ public GraphQLMatcher(
break;

case AnyOfType.Third:
_schema = schema.Third;
_schema = ((SchemaDataWrapper)schema.Third).Schema;
break;

default:
Expand Down Expand Up @@ -201,13 +201,12 @@ private ISchema BuildSchema(string typeDefinitions)
throw new WireMockException($"The GraphQL Scalar type '{scalarTypeDefinitionName}' is not defined in the CustomScalars dictionary.");
}

// Create a this custom Scalar GraphType (extending the WireMockCustomScalarGraphType<{clrType}> class)
// Create a custom Scalar GraphType (extending the WireMockCustomScalarGraphType<{clrType}> class)
var customScalarGraphType = ReflectionUtils.CreateGenericType(customScalarGraphTypeName, typeof(WireMockCustomScalarGraphType<>), clrType);
schema.RegisterType(customScalarGraphType);
}
}

return schema;
}
}
#endif
}
18 changes: 18 additions & 0 deletions src/WireMock.Net.GraphQL/Models/SchemaDataWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright © WireMock.Net

using GraphQL.Types;
using WireMock.Models.GraphQL;

namespace WireMock.Models;

/// <summary>
/// Represents a wrapper for schema data, providing access to the associated schema.
/// </summary>
/// <param name="schema"></param>
public class SchemaDataWrapper(ISchema schema) : ISchemaData
{
/// <summary>
/// Gets the schema associated with the current instance.
/// </summary>
public ISchema Schema { get; } = schema;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright © WireMock.Net

#if GRAPHQL
using System;
using GraphQL.Types;

namespace WireMock.Matchers.Models;
// ReSharper disable once CheckNamespace
namespace WireMock.GraphQL.Models;

/// <inheritdoc />
public abstract class WireMockCustomScalarGraphType<T> : ScalarGraphType
Expand All @@ -28,5 +28,4 @@ public abstract class WireMockCustomScalarGraphType<T> : ScalarGraphType

return (T)Convert.ChangeType(value, typeof(T));
}
}
#endif
}
8 changes: 8 additions & 0 deletions src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright © WireMock.Net

using System.Runtime.CompilerServices;

// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]

// Needed for Moq in the UnitTest project
// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright © WireMock.Net

using System;
using System.Collections.Generic;
using GraphQL.Types;
using Stef.Validation;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.Models.GraphQL;

namespace WireMock.RequestBuilders;

/// <summary>
/// IRequestBuilderExtensions extensions for GraphQL.
/// </summary>
// ReSharper disable once InconsistentNaming
public static class IRequestBuilderExtensions
{
/// <summary>
/// WithBodyAsGraphQL: The GraphQL body as a string.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
}

/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a string.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, string schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars));
}

/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a <see cref="ISchema"/>.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, new SchemaDataWrapper(schema)));
}

/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a <see cref="ISchema"/>.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, ISchema schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, new SchemaDataWrapper(schema), customScalars));
}

/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a <see cref="ISchemaData"/>.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, ISchemaData schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
}

/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a <see cref="ISchemaData"/>.
/// </summary>
/// <param name="requestBuilder">The <see cref="IRequestBuilder"/>.</param>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, ISchemaData schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Guard.NotNull(requestBuilder).Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Reflection;
using System.Reflection.Emit;

namespace WireMock.Util;
namespace WireMock.Utils;

internal static class ReflectionUtils
{
Expand Down
47 changes: 47 additions & 0 deletions src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>GraphQL support for WireMock.Net</Description>
<AssemblyTitle>WireMock.Net.Matchers.GraphQL</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;graphql</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-444DED3D9A45}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GraphQL.NewtonsoftJson" Version="8.2.1" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Shared\WireMock.Net.Shared.csproj" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
11 changes: 6 additions & 5 deletions src/WireMock.Net.Minimal/Models/GraphQLSchemaDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using AnyOfTypes;
using Newtonsoft.Json;
using WireMock.Models.GraphQL;

namespace WireMock.Models;

Expand All @@ -24,15 +25,15 @@ public class GraphQLSchemaDetails

#if GRAPHQL
/// <summary>
/// The GraphQL schema as a <seealso cref="GraphQL.Types.ISchema"/>.
/// The GraphQL schema as a <seealso cref="ISchemaData"/>.
/// </summary>
public GraphQL.Types.ISchema? SchemaAsISchema { get; set; }
public ISchemaData? SchemaAsISchemaData { get; set; }

/// <summary>
/// The GraphQL Schema.
/// </summary>
[JsonIgnore]
public AnyOf<string, StringPattern, GraphQL.Types.ISchema>? Schema
public AnyOf<string, StringPattern, ISchemaData>? Schema
{
get
{
Expand All @@ -46,9 +47,9 @@ public class GraphQLSchemaDetails
return SchemaAsStringPattern;
}

if (SchemaAsISchema != null)
if (SchemaAsISchemaData != null)
{
return new AnyOf<string, StringPattern, GraphQL.Types.ISchema>(SchemaAsISchema);
return new AnyOf<string, StringPattern, ISchemaData>(SchemaAsISchemaData);
}

return null;
Expand Down
Loading
Loading