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
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ private static IValueNode CoerceInputLiteral(
continue;
}

// like the input parser, we keep the first occurrence of a repeated property.
if (processed[field.Index])
{
continue;
}

processed[field.Index] = true;

if (property.Value.ValueKind is JsonValueKind.Null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,42 @@ public void Coerce_Enum_Should_Reuse_Literal_Across_Coercions()
Assert.Same(literal, second["episode"].ValueLiteral);
}

[Fact]
public void CoerceVariableValues_Should_KeepFirstOccurrence_When_PropertyIsRepeated()
{
// arrange
var schema = SchemaBuilder.New().AddStarWarsTypes().Create();

var variableDefinitions = new List<VariableDefinitionNode>
{
new VariableDefinitionNode(
null,
new VariableNode("review"),
description: null,
new NonNullTypeNode(new NamedTypeNode("ReviewInput")),
null,
Array.Empty<DirectiveNode>())
};

using var variableValues = JsonDocument.Parse(
"""{"review":{"stars":1,"stars":2,"st\u0061rs":null,"commentary":"a"}}""");

var coercedValues = new Dictionary<string, VariableValue>();
var featureProvider = new MockFeatureProvider();
var helper = new VariableCoercionHelper(new());

// act
helper.CoerceVariableValues(
schema, variableDefinitions, variableValues.RootElement, coercedValues, featureProvider);

// assert
Assert.Equal(1, Assert.IsType<Review>(coercedValues["review"].RuntimeValue).Stars);
coercedValues["review"].ValueLiteral.ToString().MatchInlineSnapshot(
"""
{ stars: 1, commentary: "a" }
""");
}

private class MockFeatureProvider : IFeatureProvider
{
public IFeatureCollection Features { get; } = new FeatureCollection();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ private bool TryParseInputObject(
return false;
}

// we keep the first occurrence of a repeated property.
if (processed[fieldDefinition.Index])
{
continue;
}

if (oneOf && property.Value.ValueKind is JsonValueKind.Null)
{
value = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,92 @@ input SearchInput {
""");
}

[Fact]
public void TryCoerceVariableValues_Should_KeepFirstOccurrence_When_PropertyIsRepeated()
{
// arrange
var schema = ComposeSchema(
"""
type Query {
field(input: ItemInput!): String
}

input ItemInput {
id: Int!
name: String
}
""");
var variableDefinition = CreateVariableDefinition(
"input",
new NonNullTypeNode(new NamedTypeNode("ItemInput")));
using var variableValues = JsonDocument.Parse(
"""{"input":{"id":1,"id":2,"\u0069d":3,"name":"a"}}""");

// act
var success = VariableCoercionHelper.TryCoerceVariableValues(
new MockFeatureProvider(),
schema,
[variableDefinition],
variableValues.RootElement,
ignoreAdditionalInputFields: false,
out var coercedVariableValues,
out var error);

// assert
Assert.True(success, error?.Message);
Assert.NotNull(coercedVariableValues);
coercedVariableValues["input"].Value.ToString().MatchInlineSnapshot(
"""
{ id: 1, name: "a" }
""");
}

[Fact]
public void TryCoerceVariableValues_Should_StillRequireDefinedFields_When_PropertyIsRepeated()
{
// arrange
var schema = ComposeSchema(
"""
type Query {
field(input: ItemInput!): String
}

input ItemInput {
id: Int!
name: String
}
""");
var variableDefinition = CreateVariableDefinition(
"input",
new NonNullTypeNode(new NamedTypeNode("ItemInput")));

// act
var error = CoerceError(
schema,
variableDefinition,
"""{"input":{"name":"a","name":"b"}}""",
ignoreAdditionalInputFields: false);

// assert
new[] { error.WithException(null) }
.ToList()
.MatchInlineSnapshot(
"""
"errors": [
{
"message": "The required input field `id` is missing.",
"path": [
"input",
"id"
],
"extensions": {
"field": "ItemInput.id"
}
}
]
""");
}

[Fact]
public void TryCoerceVariableValues_Should_StillRequireDefinedFields_When_AdditionalInputFieldsAreIgnored()
{
Expand Down
Loading