Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion src/GraphQL.FluentValidation/ArgumentValidation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ static ValidationContext BuildValidationContext(object? instance, object userCon
validationContext.RootContextData.Add("UserContext", userContext);
return validationContext;
}
}
}
12 changes: 0 additions & 12 deletions src/GraphQL.FluentValidation/FluentValidationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using FluentValidation;
using GraphQL.FluentValidation;
using GraphQL.Types;

namespace GraphQL
{
Expand All @@ -9,17 +8,6 @@ namespace GraphQL
/// </summary>
public static partial class FluentValidationExtensions
{
/// <summary>
/// Validate an instance against the current cached validators defined by <see cref="ValidatorTypeCache"/>.
/// </summary>
public static void ValidateInstance<TSource, TInstance>(this ResolveFieldContext<TSource> context, TInstance input)
{
Guard.AgainstNull(context, nameof(context));
Guard.AgainstNull(input, nameof(input));
var type = input!.GetType();
ArgumentValidation.Validate(ArgumentTypeCacheBag.GetCache(context), type, input, context.UserContext);
}

/// <summary>
/// Adds a FieldMiddleware to the GraphQL pipeline that converts a <see cref="ValidationException"/> to <see cref="ExecutionError"/>s./>
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Tests/Arguments/AsyncComplexInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public class AsyncComplexInput
{
public ComplexInputInner? Inner { get; set; }
}
10 changes: 10 additions & 0 deletions src/Tests/Arguments/AsyncComplexInputGraph.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using GraphQL.Types;

public class AsyncComplexInputGraph :
InputObjectGraphType
{
public AsyncComplexInputGraph()
{
Field<ComplexInputInnerGraph>("inner");
}
}
16 changes: 16 additions & 0 deletions src/Tests/Arguments/AsyncComplexInputValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using FluentValidation;
using System.Threading.Tasks;

public class AsyncComplexInputValidator :
AbstractValidator<AsyncComplexInput>
{
public AsyncComplexInputValidator()
{
RuleFor(_ => _.Inner!)
.NotEmpty()
.MustAsync((o, token) => {
return Task.FromResult(o != null && !string.IsNullOrWhiteSpace(o.Content));
}).WithMessage("Inner async test failed msg.")
.SetValidator(new ComplexInputInnerValidator());
}
}
6 changes: 5 additions & 1 deletion src/Tests/Arguments/ComplexInput.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
public class ComplexInput
using System.Collections.Generic;

public class ComplexInput
{
public ComplexInputInner? Inner { get; set; }

public List<ComplexInputListItem>? Items { get; set; }
}
2 changes: 2 additions & 0 deletions src/Tests/Arguments/ComplexInputGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ public class ComplexInputGraph :
public ComplexInputGraph()
{
Field<ComplexInputInnerGraph>("inner");

Field<ListGraphType<NonNullGraphType<ComplexInputListItemGraph>>>("items");
}
}
5 changes: 5 additions & 0 deletions src/Tests/Arguments/ComplexInputListItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class ComplexInputListItem
{
public int Id { get; set; }
public string? Content { get; set; }
}
16 changes: 16 additions & 0 deletions src/Tests/Arguments/ComplexInputListItemGraph.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using GraphQL.Types;

public class ComplexInputListItemGraph :
InputObjectGraphType<ComplexInputListItem>
{
public ComplexInputListItemGraph()
{
Field<NonNullGraphType<IntGraphType>>()
.Name("id")
.Resolve(ctx => ctx.Source.Id);

Field<StringGraphType, string?>()
.Name("content")
.Resolve(ctx => ctx.Source.Content);
}
}
14 changes: 14 additions & 0 deletions src/Tests/Arguments/ComplexInputListItemValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using FluentValidation;

public class ComplexInputListItemValidator :
AbstractValidator<ComplexInputListItem>
{
public ComplexInputListItemValidator()
{
RuleFor(_ => _.Id)
.NotEmpty();

RuleFor(_ => _.Content)
.NotEmpty();
}
}
4 changes: 4 additions & 0 deletions src/Tests/Arguments/ComplexInputValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ public ComplexInputValidator()
RuleFor(_ => _.Inner!)
.NotEmpty()
.SetValidator(new ComplexInputInnerValidator());

RuleFor(_ => _.Items)
.NotEmpty()
.ForEach(i => i.SetValidator(new ComplexInputListItemValidator()));
}
}
13 changes: 13 additions & 0 deletions src/Tests/IntegrationTests.AsyncComplexInvalid.approved.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
data: {
asyncComplexInputQuery: null
},
errors: [
{
message: 'Inner: Inner async test failed msg.'
},
{
message: 'Inner.Content: \'Content\' must not be empty.'
}
]
}
7 changes: 7 additions & 0 deletions src/Tests/IntegrationTests.AsyncComplexValid.approved.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
data: {
asyncComplexInputQuery: {
data: 'TheContent'
}
}
}
3 changes: 3 additions & 0 deletions src/Tests/IntegrationTests.ComplexInvalid.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
errors: [
{
message: 'Inner.Content: \'Content\' must not be empty.'
},
{
message: 'Items: \'Items\' must not be empty.'
}
]
}
3 changes: 3 additions & 0 deletions src/Tests/IntegrationTests.ComplexInvalid2.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
errors: [
{
message: 'Inner: \'Inner\' must not be empty.'
},
{
message: 'Items: \'Items\' must not be empty.'
}
]
}
2 changes: 1 addition & 1 deletion src/Tests/IntegrationTests.ComplexValid.approved.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
data: {
complexInputQuery: {
data: 'TheContent'
data: '{"Inner":{"Content":"TheContent"},"Items":[{"Id":1,"Content":"Some content 1"},{"Id":2,"Content":"Some content 2"}]}'
}
}
}
60 changes: 57 additions & 3 deletions src/Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ public async Task ComplexValid()
input: {
inner: {
content: ""TheContent""
}
},
items: [
{ id: 1, content: ""Some content 1"" },
{ id: 2, content: ""Some content 2"" }
]
}
)
{
Expand All @@ -121,7 +125,8 @@ public async Task ComplexInvalid()
input: {
inner: {
content: """"
}
},
items: []
}
)
{
Expand All @@ -140,7 +145,8 @@ public async Task ComplexInvalid2()
complexInputQuery
(
input: {
inner: null
inner: null,
items: null
}
)
{
Expand All @@ -151,6 +157,54 @@ public async Task ComplexInvalid2()
ObjectApprover.Verify(result);
}

[Fact]
public async Task AsyncComplexValid()
{
var queryString = @"
{
asyncComplexInputQuery
(
input: {
inner: {
content: ""TheContent""
},
items: [
{ id: 1, content: ""Some content 1"" },
{ id: 2, content: ""Some content 2"" }
]
}
)
{
data
}
}";
var result = await QueryExecutor.ExecuteQuery(queryString, null, typeCache);
ObjectApprover.Verify(result);
}

[Fact]
public async Task AsyncComplexInvalid()
{
var queryString = @"
{
asyncComplexInputQuery
(
input: {
inner: {
content: """"
},
items: null
}
)
{
data
}
}";
var result = await QueryExecutor.ExecuteQuery(queryString, null, typeCache);
ObjectApprover.Verify(result);
}


public IntegrationTests(ITestOutputHelper output) :
base(output)
{
Expand Down
20 changes: 18 additions & 2 deletions src/Tests/Query.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GraphQL;
using GraphQL;
using GraphQL.Types;
using Newtonsoft.Json;

public class Query :
ObjectGraphType
Expand Down Expand Up @@ -31,7 +32,7 @@ public Query()
var input = context.GetValidatedArgument<ComplexInput>("input");
return new Result
{
Data = input.Inner!.Content
Data = JsonConvert.SerializeObject(input)
};
}
);
Expand All @@ -50,6 +51,21 @@ public Query()
};
}
);

FieldAsync<ResultGraph>(
"asyncComplexInputQuery",
arguments: new QueryArguments(
new QueryArgument<ComplexInputGraph> { Name = "input", }
),
resolve: async context =>
{
var input = await context.GetValidatedArgumentAsync<AsyncComplexInput>("input");
return new Result
{
Data = input.Inner!.Content
};
}
);
}

}