Skip to content

Commit

Permalink
Added CollectionSegment<T> (#3597)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-tengler committed Apr 26, 2021
1 parent 89a07cf commit 1285f1c
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace HotChocolate.Types.Pagination
{
/// <summary>
/// The collection segment represents one page of a pagebale data set / collection.
/// The collection segment represents one page of a pageable dataset / collection.
/// </summary>
public class CollectionSegment : IPage
{
Expand All @@ -31,7 +31,8 @@ public class CollectionSegment : IPage
{
Items = items ??
throw new ArgumentNullException(nameof(items));
Info = info;
Info = info ??
throw new ArgumentNullException(nameof(info));
_getTotalCount = getTotalCount ??
throw new ArgumentNullException(nameof(getTotalCount));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace HotChocolate.Types.Pagination
{
/// <inheritdoc />
public class CollectionSegment<T> : CollectionSegment
where T : class
{
/// <summary>
/// Initializes <see cref="CollectionSegment" />.
/// </summary>
/// <param name="items">
/// The items that belong to this page.
/// </param>
/// <param name="info">
/// Additional information about this page.
/// </param>
/// <param name="getTotalCount">
/// A delegate to request the the total count.
/// </param>
public CollectionSegment(
IReadOnlyCollection<T> items,
CollectionSegmentInfo info,
Func<CancellationToken, ValueTask<int>> getTotalCount)
: base(items, info, getTotalCount)
{
Items = items;
}

/// <summary>
/// The items that belong to this page.
/// </summary>
public new IReadOnlyCollection<T> Items { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using Xunit;

namespace HotChocolate.Types.Pagination
{
public class CollectionSegmentTests
{
[Fact]
public void CreateCollectionSegment_PageInfoAndItems_PassedCorrectly()
{
// arrange
var pageInfo = new CollectionSegmentInfo(true, true);
var items = new List<string>();

// act
var collection = new CollectionSegment(
items,
pageInfo,
ct => throw new NotSupportedException());

// assert
Assert.Equal(pageInfo, collection.Info);
Assert.Equal(items, collection.Items);
}

[Fact]
public void CreateCollectionSegment_PageInfoNull_ArgumentNullException()
{
// arrange
var items = new List<string>();

// act
Action a = () => new CollectionSegment<string>(
items, null, ct => throw new NotSupportedException());

// assert
Assert.Throws<ArgumentNullException>(a);
}

[Fact]
public void CreateCollectionSegment_ItemsNull_ArgumentNullException()
{
// arrange
var pageInfo = new CollectionSegmentInfo(true, true);

// act
Action a = () => new CollectionSegment<string>(
null, pageInfo, ct => throw new NotSupportedException());

// assert
Assert.Throws<ArgumentNullException>(a);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Threading.Tasks;
using HotChocolate.Execution;
using HotChocolate.Tests;
using Snapshooter.Xunit;
using Xunit;

namespace HotChocolate.Types.Pagination
{
public class CustomCollectionSegmentHandlerTests
{
[Fact]
public void Infer_Schema_Correctly_When_CollectionSegment_IsUsed()
{
SchemaBuilder.New()
.AddQueryType<Query>()
.Create()
.Print()
.MatchSnapshot();
}

[Fact]
public async Task Use_Resolver_Result_If_It_Is_A_Page()
{
// arrange
Snapshot.FullName();

IReadOnlyQueryRequest request =
QueryRequestBuilder.New()
.SetQuery("{ items { items } }")
.Create();

// act
// assert
await SchemaBuilder.New()
.AddQueryType<Query>()
.Create()
.MakeExecutable()
.ExecuteAsync(request)
.MatchSnapshotAsync();
}

public class Query
{
[UseOffsetPaging]
public CollectionSegment<string> GetItems(int skip, int take)
{
return new CollectionSegment<string>(
new[] { "hello", "abc" },
new CollectionSegmentInfo(false, false),
ct => throw new NotImplementedException());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
schema {
query: Query
}

"Information about the offset pagination."
type CollectionSegmentInfo {
"Indicates whether more items exist following the set defined by the clients arguments."
hasNextPage: Boolean!
"Indicates whether more items exist prior the set defined by the clients arguments."
hasPreviousPage: Boolean!
}

type Query {
items(skip: Int take: Int): StringCollectionSegment
}

type StringCollectionSegment {
items: [String]
"Information to aid in pagination."
pageInfo: CollectionSegmentInfo!
}

"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 `@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
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"data": {
"items": {
"items": [
"hello",
"abc"
]
}
}
}

0 comments on commit 1285f1c

Please sign in to comment.