Skip to content

Commit

Permalink
Fixed and issue where the connection type was registered twice. (#842)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Jun 15, 2019
1 parent ce67a7c commit 0d82d59
Show file tree
Hide file tree
Showing 14 changed files with 266 additions and 36 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Subscription now uses pipeline API to abstract sockets. [#807](https://github.com/ChilliCream/hotchocolate/pull/807)
- Improved parser performance. [#806](https://github.com/ChilliCream/hotchocolate/pull/806)

## [9.0.4] - 2019-06-16

### Fixed

- Fixed paging flaws that in some cases lead to the connection type being registered twice. [#842](https://github.com/ChilliCream/hotchocolate/pull/842)

## [9.0.3] - 2019-06-13

### Fixed

- Fixed issues where the type initializer would swallow schema errors.

## [9.0.2] - 2019-06-12

### Fixed
Expand Down
34 changes: 34 additions & 0 deletions examples/AspNetCore.StarWars/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/netcoreapp2.1/AspNetCore.StarWars.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
17 changes: 17 additions & 0 deletions examples/AspNetCore.StarWars/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet build",
"type": "shell",
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/CharacterType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;

namespace StarWars.Types
Expand All @@ -17,7 +18,7 @@ protected override void Configure(IInterfaceTypeDescriptor<ICharacter> descripto
.Type<StringType>();

descriptor.Field(f => f.Friends)
.Type<ListType<CharacterType>>();
.UsePaging<CharacterType>();

descriptor.Field(f => f.AppearsIn)
.Type<ListType<EpisodeType>>();
Expand Down
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/DroidType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;
using StarWars.Resolvers;

Expand All @@ -18,7 +19,7 @@ protected override void Configure(IObjectTypeDescriptor<Droid> descriptor)
.Type<ListType<EpisodeType>>();

descriptor.Field<SharedResolvers>(r => r.GetCharacter(default, default))
.Type<ListType<CharacterType>>()
.UsePaging<CharacterType>()
.Name("friends");

descriptor.Field<SharedResolvers>(t => t.GetHeight(default, default))
Expand Down
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/HumanType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;
using StarWars.Resolvers;

Expand All @@ -18,7 +19,7 @@ protected override void Configure(IObjectTypeDescriptor<Human> descriptor)
.Type<ListType<EpisodeType>>();

descriptor.Field<SharedResolvers>(r => r.GetCharacter(default, default))
.Type<ListType<CharacterType>>()
.UsePaging<CharacterType>()
.Name("friends");

descriptor.Field<SharedResolvers>(t => t.GetHeight(default, default))
Expand Down
81 changes: 79 additions & 2 deletions src/Core/Types.Tests/Types/Relay/ConnectionTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void CheckFieldsAreCorrect()
},
t =>
{
Assert.Equal("items", t.Name);
Assert.Equal("nodes", t.Name);
Assert.IsType<StringType>(
Assert.IsType<ListType>(t.Type).ElementType);
},
Expand Down Expand Up @@ -104,7 +104,7 @@ public async Task UsePaging_WithNonNull_ElementType()
cursor
node
}
items
nodes
pageInfo
{
hasNextPage
Expand All @@ -122,6 +122,43 @@ public async Task UsePaging_WithNonNull_ElementType()
result.MatchSnapshot();
}

[Fact]
public async Task UsePaging_WithComplexType()
{
// arrange
ISchema schema = SchemaBuilder.New()
.AddType<FooType>()
.AddQueryType<QueryType3>()
.Create();

IQueryExecutor executor = schema.MakeExecutable();

string query = @"
{
s
{
bar {
edges {
cursor
node
}
pageInfo
{
hasNextPage
}
totalCount
}
}
}
";

// act
IExecutionResult result = await executor.ExecuteAsync(query);

// assert
result.MatchSnapshot();
}

public class QueryType
: ObjectType
{
Expand Down Expand Up @@ -152,10 +189,50 @@ protected override void Configure(IObjectTypeDescriptor descriptor)
}
}

public class QueryType3
: ObjectType
{
protected override void Configure(IObjectTypeDescriptor descriptor)
{
descriptor.Name("Query");
descriptor.Field("s")
.Resolver(ctx => new Foo());
}
}

public class Query
{
public ICollection<string> Strings { get; } =
new List<string> { "a", "b", "c", "d", "e", "f", "g" };
}

public class FooType
: ObjectType<Foo>
{
protected override void Configure(
IObjectTypeDescriptor<Foo> descriptor)
{
descriptor.Interface<FooInterfaceType>();
descriptor.Field(t => t.Bar).UsePaging<StringType>();
}
}

public class FooInterfaceType
: InterfaceType
{
protected override void Configure(
IInterfaceTypeDescriptor descriptor)
{
descriptor.Name("IFoo");
descriptor.Field("bar")
.UsePaging<StringType>();
}
}

public class Foo
{
public ICollection<string> Bar { get; } =
new List<string> { "a", "b", "c", "d", "e", "f", "g" };
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"Data": {
"s": {
"bar": {
"edges": [
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjB9",
"node": "a"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjF9",
"node": "b"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjJ9",
"node": "c"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjN9",
"node": "d"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjR9",
"node": "e"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjV9",
"node": "f"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjZ9",
"node": "g"
}
],
"pageInfo": {
"hasNextPage": false
},
"totalCount": 7
}
}
},
"Extensions": {},
"Errors": [],
"ContextData": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"node": "g"
}
],
"items": [
"nodes": [
"f",
"g"
],
Expand Down
27 changes: 1 addition & 26 deletions src/Core/Types/Types/Relay/ConnectionType.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using HotChocolate.Configuration;
using HotChocolate.Resolvers;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;

Expand Down Expand Up @@ -29,7 +28,6 @@ public ConnectionType(

public IEdgeType EdgeType { get; private set; }


protected new static void Configure(
IObjectTypeDescriptor<IConnection> descriptor)
{
Expand All @@ -50,7 +48,7 @@ public ConnectionType(
.Description("A list of edges.")
.Type<ListType<NonNullType<EdgeType<T>>>>();

descriptor.Field("items")
descriptor.Field("nodes")
.Description("A flattened list of the nodes.")
.Type<ListType<T>>()
.Resolver(ctx =>
Expand All @@ -77,28 +75,5 @@ protected override void OnCompleteType(
EdgeType = context.GetType<EdgeType<T>>(
ClrTypeReference.FromSchemaType<EdgeType<T>>());
}

public static ConnectionType<T> CreateWithTotalCount()
{
return new ConnectionType<T>(c =>
{
c.Field("totalCount")
.Type<NonNullType<IntType>>()
.Resolver(ctx => GetTotalCount(ctx));
});
}

private static IResolverResult<long> GetTotalCount(
IResolverContext context)
{
IConnection connection = context.Parent<IConnection>();
if (connection.PageInfo.TotalCount.HasValue)
{
return ResolverResult.CreateValue(
connection.PageInfo.TotalCount.Value);
}
return ResolverResult.CreateError<long>(
"The total count was not provided by the connection.");
}
}
}
46 changes: 46 additions & 0 deletions src/Core/Types/Types/Relay/ConnectionWithCountType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using HotChocolate.Resolvers;

namespace HotChocolate.Types.Relay
{
public class ConnectionWithCountType<T>
: ConnectionType<T>
where T : IOutputType
{
public ConnectionWithCountType()
: base(descriptor => Configure(descriptor))
{
}

public ConnectionWithCountType(
Action<IObjectTypeDescriptor<IConnection>> configure)
: base(descriptor =>
{
Configure(descriptor);
configure?.Invoke(descriptor);
})
{
}

protected new static void Configure(
IObjectTypeDescriptor<IConnection> descriptor)
{
descriptor.Field("totalCount")
.Type<NonNullType<IntType>>()
.Resolver(ctx => GetTotalCount(ctx));
}

private static IResolverResult<long> GetTotalCount(
IResolverContext context)
{
IConnection connection = context.Parent<IConnection>();
if (connection.PageInfo.TotalCount.HasValue)
{
return ResolverResult.CreateValue(
connection.PageInfo.TotalCount.Value);
}
return ResolverResult.CreateError<long>(
"The total count was not provided by the connection.");
}
}
}
Loading

0 comments on commit 0d82d59

Please sign in to comment.