Skip to content

Commit

Permalink
Validation Rules (#176)
Browse files Browse the repository at this point in the history
- All Variables Used #130
- All Variable Uses Defined #129
- Directives Are In Valid Locations #125
- Directives Are Unique Per Location #126
- Variables Are Input Types #128
- Field Selection Merging #109
  • Loading branch information
michaelstaib authored Jul 24, 2018
1 parent c242d42 commit 600cafb
Show file tree
Hide file tree
Showing 80 changed files with 3,037 additions and 195 deletions.
1 change: 0 additions & 1 deletion src/AspNetCore.Tests/AspNetCore.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>HotChocolate.AspNetCore.Tests</AssemblyName>
<RootNamespace>HotChocolate.AspNetCore</RootNamespace>

<IsPackable>false</IsPackable>
</PropertyGroup>

Expand Down
1 change: 0 additions & 1 deletion src/Benchmark.Tests/Benchmark.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>HotChocolate.Benchmark.Tests</RootNamespace>

<IsPackable>false</IsPackable>
</PropertyGroup>

Expand Down
1 change: 0 additions & 1 deletion src/Core.Tests/Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>HotChocolate.Core.Tests</AssemblyName>
<RootNamespace>HotChocolate</RootNamespace>

<IsPackable>false</IsPackable>
</PropertyGroup>

Expand Down
8 changes: 4 additions & 4 deletions src/Core.Tests/Execution/QueryExecuterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public async Task ExecuteWithNonNullVariableNull_Error()
Dictionary<string, IValueNode> variableValues =
new Dictionary<string, IValueNode>()
{
{ "a", new NullValueNode() }
{ "a", NullValueNode.Default }
};

Schema schema = CreateSchema();
Expand Down Expand Up @@ -176,7 +176,7 @@ public async Task ExecuteQueryWith2OperationsAndNoOperationName_Error()
Schema schema = CreateSchema();
QueryExecuter executer = new QueryExecuter(schema);
QueryRequest request = new QueryRequest(
"query a { a } query b { b }");
"query a { a } query b { a }");

// act
IExecutionResult result = await executer.ExecuteAsync(request);
Expand All @@ -193,7 +193,7 @@ public async Task ExecuteQueryWith2OperationsAndOperationName_NoErrors()
Schema schema = CreateSchema();
QueryExecuter executer = new QueryExecuter(schema);
QueryRequest request = new QueryRequest(
"query a { a } query b { b }", "a");
"query a { a } query b { a }", "a");

// act
IExecutionResult result = await executer.ExecuteAsync(request);
Expand All @@ -210,7 +210,7 @@ public async Task ExecuteQueryWith2OperationsAndInvalidOperationName_Error()
Schema schema = CreateSchema();
QueryExecuter executer = new QueryExecuter(schema);
QueryRequest request = new QueryRequest(
"query a { a } query b { b }", "c");
"query a { a } query b { a }", "c");

// act
IExecutionResult result = await executer.ExecuteAsync(request);
Expand Down
4 changes: 2 additions & 2 deletions src/Core.Tests/Execution/VariableValueBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void QueryWithNonNullVariableAndDefaultWhereValueWasNotProvided()
"query test($test: String! = \"foo\") { a }");
Dictionary<string, IValueNode> variableValues =
new Dictionary<string, IValueNode>();
variableValues.Add("test", new NullValueNode(null));
variableValues.Add("test", NullValueNode.Default);

// act
VariableValueBuilder resolver =
Expand Down Expand Up @@ -81,7 +81,7 @@ public void QueryWithNullableVariableAndNoDefaultWhereNoValueWasProvided()
"query test($test: String) { a }");
Dictionary<string, IValueNode> variableValues =
new Dictionary<string, IValueNode>();
variableValues.Add("test", new NullValueNode(null));
variableValues.Add("test", NullValueNode.Default);

// act
VariableValueBuilder resolver =
Expand Down
2 changes: 1 addition & 1 deletion src/Core.Tests/Types/BooleanTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void IsInstanceOfType()
// arrange
BooleanValueNode boolLiteral = new BooleanValueNode(null, true);
StringValueNode stringLiteral = new StringValueNode(null, "12345", false);
NullValueNode nullLiteral = new NullValueNode(null);
NullValueNode nullLiteral = NullValueNode.Default;

// act
BooleanType booleanType = new BooleanType();
Expand Down
2 changes: 1 addition & 1 deletion src/Core.Tests/Types/DateTimeTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void ParseLiteral_NullValueNode()
{
// arrange
DateTimeType dateTimeType = new DateTimeType();
NullValueNode literal = new NullValueNode();
NullValueNode literal = NullValueNode.Default;

// act
object value = dateTimeType.ParseLiteral(literal);
Expand Down
2 changes: 1 addition & 1 deletion src/Core.Tests/Types/DateTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void ParseLiteral_NullValueNode()
{
// arrange
DateType dateType = new DateType();
NullValueNode literal = new NullValueNode();
NullValueNode literal = NullValueNode.Default;

// act
object value = dateType.ParseLiteral(literal);
Expand Down
2 changes: 1 addition & 1 deletion src/Core.Tests/Types/ListTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void EnsureInstanceOfIsDelegatedToInnerType()
// act
ListType type = new ListType(innerType);
bool shouldBeFalse = type.IsInstanceOfType(
new ListValueNode(new[] { new NullValueNode() }));
new ListValueNode(new[] { NullValueNode.Default }));
bool shouldBeTrue = type.IsInstanceOfType(
new ListValueNode(new[] { new StringValueNode("foo") }));

Expand Down
4 changes: 2 additions & 2 deletions src/Core.Tests/Types/NumberTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void IsInstanceOfType_NullValueNode()
{
// arrange
TType type = new TType();
NullValueNode input = new NullValueNode();
NullValueNode input = NullValueNode.Default;

// act
bool result = type.IsInstanceOfType(input);
Expand Down Expand Up @@ -131,7 +131,7 @@ public void ParseLiteral_NullValueNode()
{
// arrange
TType type = new TType();
NullValueNode input = new NullValueNode();
NullValueNode input = NullValueNode.Default;

// act
object output = type.ParseLiteral(input);
Expand Down
4 changes: 2 additions & 2 deletions src/Core.Tests/Types/StringTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void IsInstanceOfType_NullValueNode()
{
// arrange
StringType type = new StringType();
NullValueNode input = new NullValueNode();
NullValueNode input = NullValueNode.Default;

// act
bool result = type.IsInstanceOfType(input);
Expand Down Expand Up @@ -132,7 +132,7 @@ public void ParseLiteral_NullValueNode()
{
// arrange
StringType type = new StringType();
NullValueNode input = new NullValueNode();
NullValueNode input = NullValueNode.Default;

// act
object output = type.ParseLiteral(input);
Expand Down
191 changes: 191 additions & 0 deletions src/Core.Tests/Validation/AllVariablesUsedRuleTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using HotChocolate.Language;
using Xunit;

namespace HotChocolate.Validation
{
public class AllVariablesUsedRuleTests
: ValidationTestBase
{
public AllVariablesUsedRuleTests()
: base(new AllVariablesUsedRule())
{
}

[Fact]
public void VariableUnused()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode query = Parser.Default.Parse(@"
query variableUnused($atOtherHomes: Boolean) {
dog {
isHousetrained
}
}
");

// act
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.True(result.HasErrors);
Assert.Collection(result.Errors,
t => Assert.Equal(
"The following variables were not used: " +
"atOtherHomes.", t.Message));
}

[Fact]
public void VariableUsedInFragment()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode query = Parser.Default.Parse(@"
query variableUsedInFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
");

// act
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.False(result.HasErrors);
}

[Fact]
public void VariableUsedInSecondLevelFragment()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode query = Parser.Default.Parse(@"
query variableUsedInFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
...isHousetrainedFragmentLevel2
}
fragment isHousetrainedFragmentLevel2 on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
");

// act
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.False(result.HasErrors);
}

[Fact]
public void VariableUsedInDirective()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode querya = Parser.Default.Parse(@"
query variableUsedInFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained @skip(if: $atOtherHomes)
}
");

DocumentNode queryb = Parser.Default.Parse(@"
query variableUsedInFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment @skip(if: $atOtherHomes)
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained
}
");

// act
QueryValidationResult resulta = Rule.Validate(schema, querya);
QueryValidationResult resultb = Rule.Validate(schema, queryb);

// assert
Assert.False(resulta.HasErrors);
Assert.False(resultb.HasErrors);
}


[Fact]
public void VariableNotUsedWithinFragment()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode query = Parser.Default.Parse(@"
query variableNotUsedWithinFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedWithoutVariableFragment
}
}
fragment isHousetrainedWithoutVariableFragment on Dog {
isHousetrained
}
");

// act
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.True(result.HasErrors);
Assert.Collection(result.Errors,
t => Assert.Equal(
"The following variables were not used: " +
"atOtherHomes.", t.Message));
}

[Fact]
public void QueryWithExtraVar()
{
// arrange
Schema schema = ValidationUtils.CreateSchema();
DocumentNode query = Parser.Default.Parse(@"
query queryWithUsedVar($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
query queryWithExtraVar($atOtherHomes: Boolean, $extra: Int) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
");

// act
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.True(result.HasErrors);
Assert.Collection(result.Errors,
t => Assert.Equal(
"The following variables were not used: " +
"extra.", t.Message));
}
}
}
12 changes: 8 additions & 4 deletions src/Core.Tests/Validation/ArgumentUniquenessRuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
namespace HotChocolate.Validation
{
public class ArgumentUniquenessRuleTests
: ValidationTestBase
{
public ArgumentUniquenessRuleTests()
: base(new ArgumentUniquenessRule())
{
}

[Fact]
public void NoDuplicateArgument()
{
Expand All @@ -17,8 +23,7 @@ fragment goodNonNullArg on Arguments {
");

// act
var validator = new ArgumentUniquenessRule();
QueryValidationResult result = validator.Validate(schema, query);
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.False(result.HasErrors);
Expand All @@ -36,8 +41,7 @@ fragment goodNonNullArg on Arguments {
");

// act
var validator = new ArgumentUniquenessRule();
QueryValidationResult result = validator.Validate(schema, query);
QueryValidationResult result = Rule.Validate(schema, query);

// assert
Assert.True(result.HasErrors);
Expand Down
Loading

0 comments on commit 600cafb

Please sign in to comment.