diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpGetSchemaMiddlewareTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpGetSchemaMiddlewareTests.cs index b9f9b6efa05..bf8eb8d0f57 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpGetSchemaMiddlewareTests.cs +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpGetSchemaMiddlewareTests.cs @@ -57,6 +57,33 @@ public async Task Download_GraphQL_Schema(string path) response.MatchMarkdownSnapshot(); } + [Theory] + [InlineData("/graphql?sdl")] + [InlineData("/graphql/schema/")] + [InlineData("/graphql/schema.graphql")] + [InlineData("/graphql/schema")] + public async Task Download_GraphQL_Schema_Slicing_Args_Enabled(string path) + { + // arrange + var server = CreateStarWarsServer( + configureServices: sp => + sp + .RemoveAll() + .AddSingleton() + .AddGraphQL() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true)); + var url = TestServerExtensions.CreateUrl(path); + var request = new HttpRequestMessage(HttpMethod.Get, url); + + // act + var response = await server.CreateClient().SendAsync(request); + + // assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + response.MatchMarkdownSnapshot(); + } + [Theory] [InlineData("/graphql/?sdl")] [InlineData("/graphql/schema/")] diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap index 55d348a047b..b2a1cda45f1 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap @@ -17,7 +17,7 @@ type Droid implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) height(unit: Unit): Float primaryFunction: String traits: JSON @@ -45,7 +45,7 @@ type Human implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) otherHuman: Human height(unit: Unit): Float homePlanet: String diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap index 55d348a047b..b2a1cda45f1 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap @@ -17,7 +17,7 @@ type Droid implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) height(unit: Unit): Float primaryFunction: String traits: JSON @@ -45,7 +45,7 @@ type Human implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) otherHuman: Human height(unit: Unit): Float homePlanet: String diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap index 55d348a047b..b2a1cda45f1 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap @@ -17,7 +17,7 @@ type Droid implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) height(unit: Unit): Float primaryFunction: String traits: JSON @@ -45,7 +45,7 @@ type Human implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) otherHuman: Human height(unit: Unit): Float homePlanet: String diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema.md b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema.md index dfc6d91a00d..d6d500a0681 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema.md +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema.md @@ -2,12 +2,12 @@ ```text Headers: -ETag: "1-B2t9cwf/BRF8NYIpFDtJE4DLg8FfD5d5HdAF9KObaUc=" +ETag: "1-LzuFZZrknIre5etJZHfNRC1e/vj+qW9tAf9pYpS8bQM=" Cache-Control: public, must-revalidate, max-age=3600 Content-Type: application/graphql; charset=utf-8 Content-Disposition: attachment; filename="schema.graphql" Last-Modified: Fri, 01 Jan 2021 00:00:00 GMT -Content-Length: 7193 +Content-Length: 7261 --------------------------> Status Code: OK --------------------------> @@ -30,7 +30,7 @@ type Droid implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) height(unit: Unit): Float primaryFunction: String traits: JSON @@ -58,7 +58,7 @@ type Human implements Character { id: ID! name: String! appearsIn: [Episode] - friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ], requireOneSlicingArgument: false) otherHuman: Human height(unit: Unit): Float homePlanet: String diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema_Slicing_Args_Enabled.md b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema_Slicing_Args_Enabled.md new file mode 100644 index 00000000000..a92a5395df1 --- /dev/null +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Schema_Slicing_Args_Enabled.md @@ -0,0 +1,151 @@ +# Download_GraphQL_Schema_Slicing_Args_Enabled + +```text +Headers: +ETag: "1-B2t9cwf/BRF8NYIpFDtJE4DLg8FfD5d5HdAF9KObaUc=" +Cache-Control: public, must-revalidate, max-age=3600 +Content-Type: application/graphql; charset=utf-8 +Content-Disposition: attachment; filename="schema.graphql" +Last-Modified: Fri, 01 Jan 2021 00:00:00 GMT +Content-Length: 7193 +--------------------------> +Status Code: OK +--------------------------> +schema { + query: Query + mutation: Mutation + subscription: Subscription +} + +interface Character { + id: ID! + name: String! + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection + appearsIn: [Episode] + traits: JSON + height(unit: Unit): Float +} + +type Droid implements Character { + id: ID! + name: String! + appearsIn: [Episode] + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + height(unit: Unit): Float + primaryFunction: String + traits: JSON +} + +"A connection to a list of items." +type FriendsConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [FriendsEdge!] + "A flattened list of the nodes." + nodes: [Character] +} + +"An edge in a connection." +type FriendsEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: Character +} + +type Human implements Character { + id: ID! + name: String! + appearsIn: [Episode] + friends("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): FriendsConnection @listSize(assumedSize: 50, slicingArguments: [ "first", "last" ], sizedFields: [ "edges", "nodes" ]) + otherHuman: Human + height(unit: Unit): Float + homePlanet: String + traits: JSON +} + +type Mutation { + createReview(episode: Episode! review: ReviewInput!): Review! @cost(weight: "10") + complete(episode: Episode!): Boolean! @cost(weight: "10") +} + +"Information about pagination in a connection." +type PageInfo { + "Indicates whether more edges exist following the set defined by the clients arguments." + hasNextPage: Boolean! + "Indicates whether more edges exist prior the set defined by the clients arguments." + hasPreviousPage: Boolean! + "When paginating backwards, the cursor to continue." + startCursor: String + "When paginating forwards, the cursor to continue." + endCursor: String +} + +type Query { + hero(episode: Episode! = NEW_HOPE): Character + heroByTraits(traits: JSON!): Character + heroes(episodes: [Episode!]!): [Character!] + character(characterIds: [String!]!): [Character!]! @cost(weight: "10") + search(text: String!): [SearchResult] + human(id: String!): Human + droid(id: String!): Droid + time: Long! + evict: Boolean! + wait(m: Int!): Boolean! @cost(weight: "10") + someDeprecatedField(deprecatedArg: String! = "foo" @deprecated(reason: "use something else")): String! @deprecated(reason: "use something else") +} + +type Review { + commentary: String @cost(weight: "10") + stars: Int! +} + +type Starship { + id: ID! + name: String! + length(unit: Unit): Float! +} + +type Subscription { + onReview(episode: Episode!): Review! + onNext: String! @cost(weight: "10") + onException: String! @cost(weight: "10") + delay(delay: Int! count: Int!): String! @cost(weight: "10") +} + +union SearchResult = Starship | Human | Droid + +input ReviewInput { + stars: Int! + commentary: String +} + +enum Episode { + NEW_HOPE + EMPIRE + JEDI +} + +enum Unit { + FOOT + METERS +} + +"The purpose of the `cost` directive is to define a `weight` for GraphQL types, fields, and arguments. Static analysis can use these weights when calculating the overall cost of a query or response." +directive @cost("The `weight` argument defines what value to add to the overall cost for every appearance, or possible appearance, of a type, field, argument, etc." weight: String!) on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | ENUM | INPUT_FIELD_DEFINITION + +"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 purpose of the `@listSize` directive is to either inform the static analysis about the size of returned lists (if that information is statically available), or to point the analysis to where to find that information." +directive @listSize("The `assumedSize` argument can be used to statically define the maximum length of a list returned by a field." assumedSize: Int "The `slicingArguments` argument can be used to define which of the field's arguments with numeric type are slicing arguments, so that their value determines the size of the list returned by that field. It may specify a list of multiple slicing arguments." slicingArguments: [String!] "The `sizedFields` argument can be used to define that the value of the `assumedSize` argument or of a slicing argument does not affect the size of a list returned by a field itself, but that of a list returned by one of its sub-fields." sizedFields: [String!] "The `requireOneSlicingArgument` argument can be used to inform the static analysis that it should expect that exactly one of the defined slicing arguments is present in a query. If that is not the case (i.e., if none or multiple slicing arguments are present), the static analysis may throw an error." requireOneSlicingArgument: Boolean! = true) on FIELD_DEFINITION + +"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! = 0 "Streamed when true." if: Boolean) on FIELD + +scalar JSON + +"The `Long` scalar type represents non-fractional signed whole 64-bit numeric values. Long can represent values between -(2^63) and 2^63 - 1." +scalar Long +``` diff --git a/src/HotChocolate/CostAnalysis/src/CostAnalysis/CostTypeInterceptor.cs b/src/HotChocolate/CostAnalysis/src/CostAnalysis/CostTypeInterceptor.cs index 559dbbea3bd..9b179f602ba 100644 --- a/src/HotChocolate/CostAnalysis/src/CostAnalysis/CostTypeInterceptor.cs +++ b/src/HotChocolate/CostAnalysis/src/CostAnalysis/CostTypeInterceptor.cs @@ -72,8 +72,12 @@ public override void OnAfterCompleteName(ITypeCompletionContext completionContex // https://ibm.github.io/graphql-specs/cost-spec.html#sec-requireOneSlicingArgument // Per default, requireOneSlicingArgument is enabled, // and has to be explicitly disabled if not desired for a field. + // However, we have found that users turn the whole cost feature of because of this setting + // which leads to less overall security for the deployed GraphQL server. + // For this reason we have decided to disable slicing arguments by default. var requirePagingBoundaries = - slicingArgs.Length > 0 && (options.RequirePagingBoundaries ?? true); + slicingArgs.Length > 0 + && (options.RequirePagingBoundaries ?? false); fieldDef.AddDirective( new ListSizeDirective( diff --git a/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/PagingTests.cs b/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/PagingTests.cs index 949f3ab7e1a..2bbf4ca8415 100644 --- a/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/PagingTests.cs +++ b/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/PagingTests.cs @@ -21,6 +21,7 @@ public async Task Ensure_Paging_Defaults_Are_Applied() .AddQueryType() .AddFiltering() .AddSorting() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .BuildSchemaAsync(); schema.MatchSnapshot(); @@ -109,6 +110,7 @@ public async Task Require_Paging_Boundaries_By_Default_With_Connections() .AddQueryType() .AddFiltering() .AddSorting() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .BuildRequestExecutorAsync(); // act @@ -277,6 +279,7 @@ public async Task Require_Paging_Boundaries_Two_Boundaries_Mixed() .AddQueryType() .AddFiltering() .AddSorting() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .BuildRequestExecutorAsync(); // act @@ -324,6 +327,7 @@ public async Task Require_Paging_Nested_Boundaries() .AddQueryType() .AddFiltering() .AddSorting() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .BuildRequestExecutorAsync(); // act diff --git a/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/SlicingArgumentsTests.cs b/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/SlicingArgumentsTests.cs index ecb42312c96..2a89c84c4c4 100644 --- a/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/SlicingArgumentsTests.cs +++ b/src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/SlicingArgumentsTests.cs @@ -14,6 +14,7 @@ public async Task SlicingArguments_Non_Specified() await new ServiceCollection() .AddGraphQLServer() .AddQueryType() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .ExecuteRequestAsync( """ { @@ -54,6 +55,7 @@ public async Task SlicingArguments_Set_To_Null() await new ServiceCollection() .AddGraphQLServer() .AddQueryType() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .ExecuteRequestAsync( """ { @@ -94,6 +96,7 @@ public async Task SlicingArguments_Set_First_To_Null_And_Last_To_Null() await new ServiceCollection() .AddGraphQLServer() .AddQueryType() + .ModifyPagingOptions(o => o.RequirePagingBoundaries = true) .ExecuteRequestAsync( """ { diff --git a/src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbAggregateFluentTests.cs b/src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbAggregateFluentTests.cs index 37e8940ce79..697f525b540 100644 --- a/src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbAggregateFluentTests.cs +++ b/src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbAggregateFluentTests.cs @@ -57,10 +57,10 @@ public async Task BsonElement_Rename() .Build()); // assert - await SnapshotExtensions.AddResult( - SnapshotExtensions.AddResult( - Snapshot - .Create(), res1, "true"), res2, "false") + await Snapshot + .Create() + .AddResult(res1, "true") + .AddResult(res2, "false") .MatchAsync(); } diff --git a/src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingFindFluentTests.cs b/src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingFindFluentTests.cs index a0abc295c4d..5fb788549ca 100644 --- a/src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingFindFluentTests.cs +++ b/src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingFindFluentTests.cs @@ -32,7 +32,7 @@ public MongoDbCursorPagingFindFluentTests(MongoResource resource) public async Task Simple_StringList_Default_Items() { // arrange - var executor = await CreateSchemaAsync(); + var executor = await CreateSchemaAsync(requiresPagingBoundaries: false); // act var result = await executor.ExecuteAsync( @@ -57,9 +57,9 @@ public async Task Simple_StringList_Default_Items() }"); // assert - await SnapshotExtensions.AddResult( - Snapshot - .Create(), result) + await Snapshot + .Create() + .AddResult(result) .MatchAsync(); } @@ -92,9 +92,9 @@ public async Task Simple_StringList_First_2() }"); // assert - await SnapshotExtensions.AddResult( - Snapshot - .Create(), result) + await Snapshot + .Create() + .AddResult(result) .MatchAsync(); } @@ -172,7 +172,7 @@ await SnapshotExtensions.AddResult( public async Task Simple_StringList_Global_DefaultItem_2() { // arrange - var executor = await CreateSchemaAsync(); + var executor = await CreateSchemaAsync(requiresPagingBoundaries: false); // act var result = await executor.ExecuteAsync( @@ -197,9 +197,9 @@ public async Task Simple_StringList_Global_DefaultItem_2() }"); // assert - await SnapshotExtensions.AddResult( - Snapshot - .Create(), result) + await Snapshot + .Create() + .AddResult(result) .MatchAsync(); } @@ -207,7 +207,7 @@ await SnapshotExtensions.AddResult( public async Task JustTotalCount() { // arrange - var executor = await CreateSchemaAsync(); + var executor = await CreateSchemaAsync(requiresPagingBoundaries: false); // act var result = await executor.ExecuteAsync( @@ -218,9 +218,9 @@ public async Task JustTotalCount() }"); // assert - await SnapshotExtensions.AddResult( - Snapshot - .Create(), result) + await Snapshot + .Create() + .AddResult(result) .MatchAsync(); } @@ -239,9 +239,9 @@ public async Task TotalCount_AndFirst() }"); // assert - await SnapshotExtensions.AddResult( - Snapshot - .Create(), result) + await Snapshot + .Create() + .AddResult(result) .MatchAsync(); } @@ -266,7 +266,7 @@ private Func> BuildResolv return ctx => collection.AsExecutable(); } - private ValueTask CreateSchemaAsync() + private ValueTask CreateSchemaAsync(bool requiresPagingBoundaries = true) { return new ServiceCollection() .AddGraphQL() @@ -305,6 +305,7 @@ private ValueTask CreateSchemaAsync() } }) .ModifyRequestOptions(x => x.IncludeExceptionDetails = true) + .ModifyPagingOptions(o => o.RequirePagingBoundaries = requiresPagingBoundaries) .UseDefaultPipeline() .Services .BuildServiceProvider() diff --git a/src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbAggregateFluentTests.cs b/src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbAggregateFluentTests.cs index bc7b7437460..57516c35654 100644 --- a/src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbAggregateFluentTests.cs +++ b/src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbAggregateFluentTests.cs @@ -39,9 +39,7 @@ public async Task BsonElement_Rename() var tester = CreateSchema( () => { - var collection = - _resource.CreateCollection("data_" + Guid.NewGuid().ToString("N")); - + var collection = _resource.CreateCollection("data_" + Guid.NewGuid().ToString("N")); collection.InsertMany(_fooEntities); return collection.Aggregate().AsExecutable(); }); @@ -58,10 +56,10 @@ public async Task BsonElement_Rename() .Build()); // assert - await SnapshotExtensions.AddResult( - SnapshotExtensions.AddResult( - Snapshot - .Create(), res1, "ASC"), res2, "DESC") + await Snapshot + .Create() + .AddResult(res1, "ASC") + .AddResult(res2, "DESC") .MatchAsync(); }