-
-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GraphQL Schema validation with custom scalars #984
Comments
Can you please provide your full GraphQL schema + how those 'MyCustomScalar' and 'MyMutation' are defined? |
scalar DateTime
input MessageInput {
date: DateTime
author: String
}
type Message {
id: ID!
content: String
author: String
}
type Mutation {
createMessage(input: MessageInput): Message
} Schema taken from the documentation and modified slightly. Here is the query I'm sending through Postman: {
"query": "mutation { createMessage($date: DateTime!, $name: String!) { createMessage(input: { date: $date author: $name }) { id } } }",
"variables": { "date": "aDate", "name": "aName" }
} Exception: {"Unable to resolve reference to type 'DateTime' on 'MessageInput'"} I was able to find a workaround by loading the Schema myself and manually adding class definitions implementing ScalarGraphType, something like internal class ScalarDateTime : ScalarGraphType
{
public ScalarDateTime()
{
Name = "DateTime";
}
public override object? ParseValue(object? value) => throw new NotImplementedException();
} and its registration: GraphQL.Types.ISchema schema = GraphQL.Types.Schema.For(TestSchema);
schema.RegisterType(typeof(ScalarDateTime)); Since the exceptions are caught, I would always get an No mapping exists error message, which wasn't very helpful until I compiled the lib and used the pdbs to debug and looked at what was happening in the matcher. The error message at the exception level were pretty helpful to find this workaround. |
On a side note: even when registering scalar types, if the schema indicates a non-nullable response, it seems like the matcher will always throw. Not sure if its something that can be handled or not |
Thanks for the detailed description. I need some time to think on this and what to change in WireMock. About |
On that point, it becomes a bit problematic, because if you have multiple matchers, then which exception are you supposed to throw? In my case, I have a global matcher which returns Unauthorized if my authorization header was missing, then 1 matcher per specific request I was handling. Since it is mocking a GraphQL server, then 2 matchers out of the 3 would have thrown. I just don't know the right way to have access to the right information to be able to troubleshoot. I know the GraphQL support was added very recently, but I noticed if a schema also includes interfaces, it really doesn't like that (I couldn't get it to work at all if an interface was present). It was easy to remove the mention of the |
1️⃣ I'm currently rewriting some logic when an exception occurs in a matcher. The path I'm following now is that I catch these exception(s) and write these exceptions to the logging like this:
Would this be a solution for you? 2️⃣ About fixing the root-cause: I did not have time yet to investigate that. Probably a way to solve this is to expose some interface on the mapper and the json mapping to support adding extra types like you do: GraphQL.Types.ISchema schema = GraphQL.Types.Schema.For(TestSchema);
schema.RegisterType(typeof(ScalarDateTime)); |
1- It looks very promising. What would it look like if you have multiple matchers configured? |
2] But when I change the code to below, your example works. private static ISchema BuildSchema(string typeDefinitions)
{
var schema = Schema.For(typeDefinitions);
// #984
schema.RegisterTypes(schema.BuiltInTypeMappings.Select(x => x.graphType).ToArray());
return schema;
} |
You can try preview version 1.5.39-ci-17839 which supports default scalars like DateTime. (https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) |
Hi Stef, I'm currently testing out the CI build and wanted to confirm with you which behavior this addresses. Does this fix only target built-in scalar types like DateTime from the GraphQL lib or custom scalar types as well defined directly in the schema string? If its also the latter, it does not seem like it is working. |
Currently only scalars in the schema. Custom scalars will be implemented in another PR. |
In that case, everything still seems to be working fine with the CI build |
I've built some code to get all custom scalars from a schema. However, I also need to know what the C# Type is for that custom scalar. Else there is no check if a value is having the correct type which means that the matcher will not work as intended. So a mapping must be provided like:
With this mapping I can dynamically create these MyCustomScalar and AnotherScalar and provide these to the schema so that resolving works. Also the ParseValue should be implemented so that when you pass a value "true" to the MyCustomScalar, an exception should be thrown. |
@jflevesque-genetec like: var customScalars = new Dictionary<string, Type> { { "MyCustomScalar", typeof(int) } };
var matcher = new GraphQLMatcher(testSchema, customScalars); Can you test this? |
Hi Stef, Side note: there isn't a way at the moment to add a matcher to the IRequestBuilder. So I'm a bit unsure how I'm supposed to test this. |
Hello @jflevesque-genetec , I missed your update in your last comment. But using the RequestBuilder can be done like this (if this is what you mean)... private const string TestSchema = @"
scalar DateTime
scalar MyCustomScalar
input MessageInput {
content: String
author: String
}
type Message {
id: ID!
content: String
author: String
}
type Mutation {
createMessage(input: MessageInput): Message
createAnotherMessage(x: MyCustomScalar, dt: DateTime): 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
}";
var customScalars = new Dictionary<string, Type> { { "MyCustomScalar", typeof(int) } };
server
.Given(Request.Create()
.WithPath("/graphql")
.UsingPost()
.WithGraphQLSchema(TestSchema, customScalars)
)
.RespondWith(Response.Create()
.WithBody("GraphQL is ok")
); |
That would actually be great. Easy to add the custom scalar types for the schema using the existing request builder. It would fill my needs perfectly. |
If you have time. Please test it |
@jflevesque-genetec |
@jflevesque-genetec |
Hi @StefH, |
@jflevesque-genetec |
Hi Stef, |
@jflevesque-genetec I've triggered a new build for that branch, and the preview version number is |
Hi Stef, |
Thanks. I'll merge the branch to main and a new official version will be released shortly. |
I've been trying to get the validation to work when using WithGraphQLSchema and can't seem to get it to work. By debugging the lib, I can see that I get an exception because my scalar type cannot be resolved:
"Unable to resolve reference to type 'MyCustomScalar' on 'MyMutation'"
I'm curious to know if this is something supported at the moment or if there's a way to define/specify the custom scalar inside the schema? At the moment, I had simply specified it using "scalar MyCustomScalar" inside the schema before my type, but clearly that isn't working.
Any inputs are well appreciated.
The text was updated successfully, but these errors were encountered: