Skip to content

Commit

Permalink
Projection attributes should change type (#2562)
Browse files Browse the repository at this point in the history
  • Loading branch information
PascalSenn committed Nov 17, 2020
1 parent 19eada8 commit f73cdfa
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 0 deletions.
Expand Up @@ -55,6 +55,7 @@ public static class SingleOrDefaultObjectFieldDescriptorExtensions
Type selectionType = typeInfo.NamedType;
definition.ResultType = selectionType;
definition.Type = context.TypeInspector.GetTypeRef(selectionType);
ILazyTypeConfiguration lazyConfiguration =
LazyTypeConfigurationBuilder
Expand Down
Expand Up @@ -14,4 +14,5 @@
<ItemGroup>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

</Project>
@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using HotChocolate.Types;
using Snapshooter.Xunit;
using Xunit;

namespace HotChocolate.Data
{
public class ProjectionAttributeTests
{
[Fact]
public void FirstOrDefault_Attribute()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<FirstOrDefaultQuery>()
.AddProjections()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

[Fact]
public void SingleOrDefault_Attribute()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<SingleOrDefaultQuery>()
.AddProjections()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

[Fact]
public void FirstOrDefault_Attribute_CustomType()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<FirstOrDefaultQuery>()
.AddType<FooType>()
.AddProjections()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

[Fact]
public void SingleOrDefault_Attribute_CustomType()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<SingleOrDefaultQuery>()
.AddType<FooType>()
.AddProjections()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

public class FooType : ObjectType<Foo>
{
protected override void Configure(IObjectTypeDescriptor<Foo> descriptor)
{
descriptor.Name("Renamed");
descriptor.Field(x => x.Bar).Name("renamed");
}
}

public class FirstOrDefaultQuery
{
[UseFirstOrDefault]
[UseProjection]
public IQueryable<Foo> GetFooQueryable() => throw new NotImplementedException();

[UseFirstOrDefault]
[UseProjection]
public IEnumerable<Foo> GetFooEnumerable() => throw new NotImplementedException();
}

public class SingleOrDefaultQuery
{
[UseFirstOrDefault]
[UseProjection]
public IQueryable<Foo> GetFooQueryable() => throw new NotImplementedException();

[UseFirstOrDefault]
[UseProjection]
public IEnumerable<Foo> GetFooEnumerable() => throw new NotImplementedException();
}

public class Foo
{
public string Bar { get; set; }
}
}
}
@@ -0,0 +1,27 @@
schema {
query: FirstOrDefaultQuery
}

type FirstOrDefaultQuery {
fooQueryable: Foo
fooEnumerable: Foo
}

type Foo {
bar: String!
}

"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

"The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values."
directive @deprecated("Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark)." reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE

"Directs the executor to include this field or fragment only when the `if` argument is true."
directive @include("Included when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"Directs the executor to skip this field or fragment when the `if` argument is true."
directive @skip("Skipped when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean!) on FIELD
@@ -0,0 +1,27 @@
schema {
query: FirstOrDefaultQuery
}

type FirstOrDefaultQuery {
fooQueryable: Renamed
fooEnumerable: Renamed
}

type Renamed {
renamed: String!
}

"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

"The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values."
directive @deprecated("Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark)." reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE

"Directs the executor to include this field or fragment only when the `if` argument is true."
directive @include("Included when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"Directs the executor to skip this field or fragment when the `if` argument is true."
directive @skip("Skipped when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean!) on FIELD
@@ -0,0 +1,27 @@
schema {
query: SingleOrDefaultQuery
}

type Foo {
bar: String!
}

type SingleOrDefaultQuery {
fooQueryable: Foo
fooEnumerable: Foo
}

"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

"The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values."
directive @deprecated("Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark)." reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE

"Directs the executor to include this field or fragment only when the `if` argument is true."
directive @include("Included when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"Directs the executor to skip this field or fragment when the `if` argument is true."
directive @skip("Skipped when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean!) on FIELD
@@ -0,0 +1,27 @@
schema {
query: SingleOrDefaultQuery
}

type Renamed {
renamed: String!
}

type SingleOrDefaultQuery {
fooQueryable: Renamed
fooEnumerable: Renamed
}

"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

"The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values."
directive @deprecated("Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark)." reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE

"Directs the executor to include this field or fragment only when the `if` argument is true."
directive @include("Included when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"Directs the executor to skip this field or fragment when the `if` argument is true."
directive @skip("Skipped when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean!) on FIELD

0 comments on commit f73cdfa

Please sign in to comment.