diff --git a/README.md b/README.md index 193db736..cfbb05f1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A .netstandard NuGet package for use with the Zendesk v2 API. #### The deprecation and replacement of Status API endpoints -More detailed information on the exact changes and motivation can be found [here](https://support.zendesk.com/hc/en-us/articles/5414949730842). +More detailed information on the exact changes and motivation can be found [here](https://support.zendesk.com/hc/en-us/articles/5414949730842). For the sake of this library, it means the following methods have been removed: @@ -50,6 +50,7 @@ Groups: Help Center: - GET api/v2/help_center/articles - GET api/v2/help_center/categories +- GET api/v2/help_center/sections Organization: - GET /api/v2/organization_fields @@ -63,11 +64,19 @@ Tickets: - GET /api/v2/tickets - GET /api/v2/tickets/{ticketId}/comments - GET /api/v2/ticket_fields -- GET /api/v2/ticket_audits - [Cursor Variant](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket_audits/#pagination) +- GET /api/v2/ticket_audits +- GET Satisfaction ratings: - GET /api/v2/satisfaction_ratings +Requests +- GET /api/v2/requests +- GET /api/v2/requests/{requestId}/comments + +Job Statuses +- GET /api/v2/job_statuses + [Further reading on Zendesk Pagination changes](https://support.zendesk.com/hc/en-us/articles/4402610093338-Introducing-Pagination-Changes-Zendesk-API) ## 3.x.x @@ -126,6 +135,43 @@ await client.Search.SearchAsync(q => ); ``` +## Using Cursor Based Pagination +You can use the `CursorPaginatedIterator` to loop through multiple pages as shown below: +```c# + +var services = new ServiceCollection(); +services.AddZendeskClientWithHttpClientFactory("https://yoursubomain.zendesk.com", "your@email.com", "your_token_"); +var serviceProvider = services.BuildServiceProvider(); +var client = serviceProvider.GetRequiredService(); + +var ticketCursorResponse = await client.Tickets.GetAllAsync(new CursorPager { Size = 5 }); // low page number to force pagination + +var iteratorFactory = serviceProvider.GetRequiredService(); +// creates the iterator with the response object of the first request +var iterator = iteratorFactory.Create(ticketCursorResponse); + +foreach (var ticket in iterator) +{ + Console.WriteLine("the id of this ticket is:" + ticket.Id); +} // this loop will stop at the first page + +while (iterator.HasMore()) // to loop through all pages +{ + await iterator.NextPage(); + foreach (var ticket in iterator) + { + Console.WriteLine("the id of this ticket is:" + ticket.Id); + } +} + +// alternatively you can use .All() from the iterator +await foreach (var ticket in iterator.All()) +{ + Console.WriteLine("the id of this ticket is:" + ticket.Id); +} + +``` + ## The Zendesk API The zendesk api documentation is available at http://developer.zendesk.com/documentation/rest_api/introduction.html diff --git a/src/ZendeskApi.Build/ZendeskApi.Commons.props b/src/ZendeskApi.Build/ZendeskApi.Commons.props index 8c512508..9456e83e 100644 --- a/src/ZendeskApi.Build/ZendeskApi.Commons.props +++ b/src/ZendeskApi.Build/ZendeskApi.Commons.props @@ -23,7 +23,7 @@ 7 0 - 6 + 7 $(Major).$(Minor).$(Revision) diff --git a/src/ZendeskApi.Client/Extensions/ServiceCollectionExtensions.cs b/src/ZendeskApi.Client/Extensions/ServiceCollectionExtensions.cs index 2cdd386e..d4382c01 100644 --- a/src/ZendeskApi.Client/Extensions/ServiceCollectionExtensions.cs +++ b/src/ZendeskApi.Client/Extensions/ServiceCollectionExtensions.cs @@ -1,7 +1,9 @@ using System; using System.Net.Http; using Microsoft.Extensions.DependencyInjection; +using ZendeskApi.Client.Models; using ZendeskApi.Client.Options; +using ZendeskApi.Client.Pagination; #pragma warning disable 618 namespace ZendeskApi.Client.Extensions @@ -33,6 +35,7 @@ public static IServiceCollection AddZendeskClientWithHttpClientFactory(this ISer { services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddHttpClient("zendeskApiClient", c => { diff --git a/src/ZendeskApi.Client/IZendeskClient.cs b/src/ZendeskApi.Client/IZendeskClient.cs index 88507495..f6d2fa76 100644 --- a/src/ZendeskApi.Client/IZendeskClient.cs +++ b/src/ZendeskApi.Client/IZendeskClient.cs @@ -29,4 +29,4 @@ public interface IZendeskClient ILocaleResource Locales { get; } ITagsResource Tags { get; } } -} \ No newline at end of file +} diff --git a/src/ZendeskApi.Client/Pagination/CursorPaginatedIterator.cs b/src/ZendeskApi.Client/Pagination/CursorPaginatedIterator.cs new file mode 100644 index 00000000..6fa075d5 --- /dev/null +++ b/src/ZendeskApi.Client/Pagination/CursorPaginatedIterator.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using Newtonsoft.Json; +using ZendeskApi.Client.Responses; + +namespace ZendeskApi.Client.Pagination; +public class CursorPaginatedIterator : IEnumerable +{ + + public ICursorPagination Response { get; set; } + + private IZendeskApiClient client; + + + private string ResponseType { get; } + + public CursorPaginatedIterator(ICursorPagination response, IZendeskApiClient client) + { + Response = response; + this.client = client; + ResponseType = response.GetType().FullName; + } + + public bool HasMore() => Response.Meta.HasMore; + + public IEnumerator GetEnumerator() + { + return Response.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return Response.GetEnumerator(); + } + + + public async Task NextPage() + { + await ExecuteRequest(Response.Links.Next); + } + + public async Task PrevPage() + { + await ExecuteRequest(Response.Links.Prev); + } + + public async IAsyncEnumerable All() + { + foreach (var item in Response) + { + yield return item; + } + while (HasMore()) + { + await NextPage(); + foreach (var item in Response) + { + yield return item; + } + } + yield break; + } + + private async Task ExecuteRequest(string requestUrl) + { + var httpResponseMessage = await client.CreateClient().GetAsync(requestUrl); + var responseBody = await httpResponseMessage.Content.ReadAsStringAsync(); + Response = (ICursorPagination)JsonConvert.DeserializeObject(responseBody, Type.GetType(ResponseType)); + } + +} diff --git a/src/ZendeskApi.Client/Pagination/CursorPaginatedIteratorFactory.cs b/src/ZendeskApi.Client/Pagination/CursorPaginatedIteratorFactory.cs new file mode 100644 index 00000000..53a5723c --- /dev/null +++ b/src/ZendeskApi.Client/Pagination/CursorPaginatedIteratorFactory.cs @@ -0,0 +1,25 @@ +using ZendeskApi.Client.Responses; + +namespace ZendeskApi.Client.Pagination +{ + public interface ICursorPaginatedIteratorFactory + { + CursorPaginatedIterator Create(ICursorPagination response); + } + + public class CursorPaginatedIteratorFactory : ICursorPaginatedIteratorFactory + { + private readonly IZendeskApiClient zendeskApiClient; + + public CursorPaginatedIteratorFactory(IZendeskApiClient _zendeskApiClient) + { + zendeskApiClient = _zendeskApiClient; + } + + public CursorPaginatedIterator Create(ICursorPagination response) + { + return new CursorPaginatedIterator(response, zendeskApiClient); + } + } +} + diff --git a/src/ZendeskApi.Client/Resources/Interfaces/IJobStatusResource.cs b/src/ZendeskApi.Client/Resources/Interfaces/IJobStatusResource.cs index 3508f885..07105386 100644 --- a/src/ZendeskApi.Client/Resources/Interfaces/IJobStatusResource.cs +++ b/src/ZendeskApi.Client/Resources/Interfaces/IJobStatusResource.cs @@ -13,7 +13,7 @@ public interface IJobStatusResource /// /// Shows the current statuses for background jobs running. /// - [Obsolete("Use `GetAllAsync` instead.")] + [Obsolete("Use `GetAllAsync` with CursorPager instead.")] Task> ListAsync( PagerParameters pagerParameters = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -21,10 +21,14 @@ Task> ListAsync( /// /// Shows the current statuses for background jobs running. /// + [Obsolete("Use `GetAllAsync` with CursorPager instead.")] Task> GetAllAsync( PagerParameters pagerParameters = null, CancellationToken cancellationToken = default(CancellationToken)); + Task> GetAllAsync( + CursorPager pagerParameters = null, + CancellationToken cancellationToken = default(CancellationToken)); #endregion #region Show diff --git a/src/ZendeskApi.Client/Resources/Interfaces/IRequestsResource.cs b/src/ZendeskApi.Client/Resources/Interfaces/IRequestsResource.cs index 561633c7..6d13cdbf 100644 --- a/src/ZendeskApi.Client/Resources/Interfaces/IRequestsResource.cs +++ b/src/ZendeskApi.Client/Resources/Interfaces/IRequestsResource.cs @@ -14,6 +14,10 @@ Task> GetAllAsync( PagerParameters pager = null, CancellationToken cancellationToken = default); + Task> GetAllAsync( + CursorPager pager, + CancellationToken cancellationToken = default); + Task GetAsync( long requestId, CancellationToken cancellationToken = default); @@ -29,6 +33,11 @@ Task> GetAllComments( PagerParameters pager = null, CancellationToken cancellationToken = default); + Task> GetAllComments( + long requestId, + CursorPager pager, + CancellationToken cancellationToken = default); + Task GetTicketCommentAsync( long requestId, long commentId, diff --git a/src/ZendeskApi.Client/Resources/Interfaces/Ticket/ITicketAuditResource.cs b/src/ZendeskApi.Client/Resources/Interfaces/Ticket/ITicketAuditResource.cs index 39a8f84d..bf2a342c 100644 --- a/src/ZendeskApi.Client/Resources/Interfaces/Ticket/ITicketAuditResource.cs +++ b/src/ZendeskApi.Client/Resources/Interfaces/Ticket/ITicketAuditResource.cs @@ -8,6 +8,7 @@ namespace ZendeskApi.Client.Resources public interface ITicketAuditResource { Task GetAllAsync(CursorPagerVariant pager = null, CancellationToken cancellationToken = default); + Task GetAllAsync(CursorPager pager, CancellationToken cancellationToken = default); Task GetAllByTicketAsync(long ticketId, CancellationToken cancellationToken = default); Task Get(int ticketId, int auditId, CancellationToken cancellationToken = default); } diff --git a/src/ZendeskApi.Client/Resources/JobStatusResource.cs b/src/ZendeskApi.Client/Resources/JobStatusResource.cs index da69f854..f711185e 100644 --- a/src/ZendeskApi.Client/Resources/JobStatusResource.cs +++ b/src/ZendeskApi.Client/Resources/JobStatusResource.cs @@ -19,7 +19,7 @@ public JobStatusResource( : base(apiClient, logger, "job_statuses") { } - [Obsolete("Use `GetAllAsync` instead.")] + [Obsolete("Use `GetAllAsync` with CursorPager instead.")] public async Task> ListAsync( PagerParameters pagerParameters = null, CancellationToken cancellationToken = default(CancellationToken)) @@ -29,6 +29,18 @@ public async Task> ListAsync( cancellationToken); } + public async Task> GetAllAsync(CursorPager pagerParameters, CancellationToken cancellationToken = default) + { + return await GetAsync( + ResourceUri, + "list-job-statuses", + "ListAsync", + pagerParameters, + null, + cancellationToken: cancellationToken); + } + + [Obsolete("Use `GetAllAsync` with CursorPager instead.")] public async Task> GetAllAsync( PagerParameters pagerParameters = null, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/ZendeskApi.Client/Resources/RequestsResource.cs b/src/ZendeskApi.Client/Resources/RequestsResource.cs index e86c34e7..159df405 100644 --- a/src/ZendeskApi.Client/Resources/RequestsResource.cs +++ b/src/ZendeskApi.Client/Resources/RequestsResource.cs @@ -34,6 +34,18 @@ public async Task> GetAllAsync( cancellationToken: cancellationToken); } + public async Task> GetAllAsync( + CursorPager pager, + CancellationToken cancellationToken = default) + { + return await GetAsync( + ResourceUri, + "list-requests", + "GetAllAsync", + pager, + cancellationToken: cancellationToken); + } + public async Task GetAsync( long requestId, @@ -79,6 +91,17 @@ public async Task> GetAllComments( cancellationToken); } + public async Task> GetAllComments(long requestId, CursorPager pager, CancellationToken cancellationToken = default) + { + return await GetWithNotFoundCheckAsync( + string.Format(CommentsResourceUri, requestId), + "getting-comments", + $"GetAllComments({requestId})", + $"Could not find any comments for request {requestId} as request was not found", + pager, + cancellationToken); + } + public async Task GetTicketCommentAsync( long requestId, long commentId, @@ -121,5 +144,6 @@ public async Task UpdateAsync( return response? .Request; } + } } diff --git a/src/ZendeskApi.Client/Resources/Ticket/TicketAuditResource.cs b/src/ZendeskApi.Client/Resources/Ticket/TicketAuditResource.cs index 5169c792..5f687ebd 100644 --- a/src/ZendeskApi.Client/Resources/Ticket/TicketAuditResource.cs +++ b/src/ZendeskApi.Client/Resources/Ticket/TicketAuditResource.cs @@ -1,3 +1,4 @@ +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -17,6 +18,7 @@ public TicketAuditResource(IZendeskApiClient apiClient, ILogger logger) : base(a { } + [Obsolete("Use `GetAllAsync` with CursorPager parameter instead.")] public async Task GetAllAsync(CursorPagerVariant pager = null, CancellationToken cancellationToken = default) { return await GetAsync( @@ -27,6 +29,17 @@ public async Task GetAllAsync(CursorPagerVariant pager = nu cancellationToken); } + public async Task GetAllAsync(CursorPager pager, CancellationToken cancellationToken = default) + { + return await GetAsync( + ResourceUri, + "list-all-ticket-audits", + "GetAllAsync", + pager, + null, + cancellationToken); + } + public async Task GetAllByTicketAsync(long ticketId, CancellationToken cancellationToken = default) { return await GetAsync( diff --git a/src/ZendeskApi.Client/Responses/ICursorPaginationResponse.cs b/src/ZendeskApi.Client/Responses/ICursorPaginationResponse.cs index 4c3b7078..1a00f91c 100644 --- a/src/ZendeskApi.Client/Responses/ICursorPaginationResponse.cs +++ b/src/ZendeskApi.Client/Responses/ICursorPaginationResponse.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/src/ZendeskApi.Client/Responses/JobStatus/JobStatusListCursorResponse.cs b/src/ZendeskApi.Client/Responses/JobStatus/JobStatusListCursorResponse.cs new file mode 100644 index 00000000..0ab75d09 --- /dev/null +++ b/src/ZendeskApi.Client/Responses/JobStatus/JobStatusListCursorResponse.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using ZendeskApi.Client.Models; + +namespace ZendeskApi.Client.Responses +{ + [JsonObject] + public class JobStatusListCursorResponse : CursorPaginationResponse + { + [JsonProperty("job_statuses")] + public IEnumerable JobStatuses { get; set; } + + protected override IEnumerable Enumerable => JobStatuses; + } +} \ No newline at end of file diff --git a/src/ZendeskApi.Client/Responses/Request/RequestsCursorResponse.cs b/src/ZendeskApi.Client/Responses/Request/RequestsCursorResponse.cs new file mode 100644 index 00000000..d6868573 --- /dev/null +++ b/src/ZendeskApi.Client/Responses/Request/RequestsCursorResponse.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using ZendeskApi.Client.Models; + +namespace ZendeskApi.Client.Responses +{ + [JsonObject] + public class RequestsCursorResponse : CursorPaginationResponse + { + [JsonProperty("requests")] + public IEnumerable Requests { get; set; } + + protected override IEnumerable Enumerable => Requests; + } +} \ No newline at end of file diff --git a/src/ZendeskApi.Client/Responses/Ticket/TicketAuditCursorResponse.cs b/src/ZendeskApi.Client/Responses/Ticket/TicketAuditCursorResponse.cs new file mode 100644 index 00000000..a3be0fe2 --- /dev/null +++ b/src/ZendeskApi.Client/Responses/Ticket/TicketAuditCursorResponse.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using ZendeskApi.Client.Models; + +namespace ZendeskApi.Client.Responses +{ + [JsonObject] + public class TicketAuditCursorResponse : CursorPaginationResponse + { + [JsonProperty("audits")] + public IEnumerable Audits { get; set; } + + protected override IEnumerable Enumerable => Audits; + } +} diff --git a/src/ZendeskApi.Client/ZendeskApi.Client.csproj b/src/ZendeskApi.Client/ZendeskApi.Client.csproj index e0816341..4818fc22 100644 --- a/src/ZendeskApi.Client/ZendeskApi.Client.csproj +++ b/src/ZendeskApi.Client/ZendeskApi.Client.csproj @@ -1,7 +1,7 @@ - + - + netstandard2.0;net6.0 A Zendesk Api Client for use with the ZendeskApi v2 diff --git a/test/ZendeskApi.Client.IntegrationTests/CBPSupport/CBPSupportTests.cs b/test/ZendeskApi.Client.IntegrationTests/CBPSupport/CBPSupportTests.cs new file mode 100644 index 00000000..bca9ff07 --- /dev/null +++ b/test/ZendeskApi.Client.IntegrationTests/CBPSupport/CBPSupportTests.cs @@ -0,0 +1,65 @@ +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using ZendeskApi.Client.IntegrationTests.Factories; +using ZendeskApi.Client.Models; +using CursorPaginatedIteratorFactory = ZendeskApi.Client.IntegrationTests.Factories.CursorPaginatedIteratorFactory; + +namespace ZendeskApi.Client.IntegrationTests.CBPSupport +{ + public class CBPSupportTests : IClassFixture + { + private readonly ZendeskClientFactory clientFactory; + private readonly CursorPaginatedIteratorFactory cursorPaginatedIteratorFactory; + + public CBPSupportTests( + ZendeskClientFactory _clientFactory) + { + clientFactory = _clientFactory; + cursorPaginatedIteratorFactory = new Factories.CursorPaginatedIteratorFactory(clientFactory); + } + + [Fact] + public async Task GetAllAsync_WhenCalledWithCursorPagination_ShouldBePaginatableByReplacingTheCursor() + { + var client = clientFactory.GetClient(); + + var cursorPager = new CursorPager { Size = 5 }; + var ticketsPageOne = await client + .Tickets.GetAllAsync(cursorPager); + + Assert.NotNull(ticketsPageOne); + Assert.Equal(5, ticketsPageOne.Count()); + Assert.True(ticketsPageOne.Meta.HasMore); + + cursorPager.AfterCursor = ticketsPageOne.Meta.AfterCursor; + + var ticketsPageTwo = await client.Tickets.GetAllAsync(cursorPager); + Assert.NotNull(ticketsPageTwo); + Assert.Equal(5, ticketsPageTwo.Count()); + + var ticketIdsPageOne = ticketsPageOne.Select(ticket => ticket.Id).ToList(); + var ticketIdsPageTwo = ticketsPageTwo.Select(ticket => ticket.Id).ToList(); + Assert.NotEqual(ticketIdsPageOne, ticketIdsPageTwo); + } + + [Fact] + public async Task CursorPaginatedIterator_ShouldBePaginatableByCallingNextPage() + { + var client = clientFactory.GetClient(); + + var cursorPager = new CursorPager { Size = 2 }; + var ticketsResponse = await client + .Tickets.GetAllAsync(cursorPager); + + var iterator = cursorPaginatedIteratorFactory.Create(ticketsResponse); + Assert.True(iterator.HasMore()); + Assert.Equal(2, iterator.Count()); + var ticketIdsPageOne = iterator.Select(ticket => ticket.Id).ToList(); + await iterator.NextPage(); + Assert.Equal(2, iterator.Count()); + var ticketIdsPageTwo = iterator.Select(ticket => ticket.Id).ToList(); + Assert.NotEqual(ticketIdsPageOne, ticketIdsPageTwo); + } + } +} diff --git a/test/ZendeskApi.Client.IntegrationTests/Factories/CursorPaginatedIteratorFactory.cs b/test/ZendeskApi.Client.IntegrationTests/Factories/CursorPaginatedIteratorFactory.cs new file mode 100644 index 00000000..bc1684ed --- /dev/null +++ b/test/ZendeskApi.Client.IntegrationTests/Factories/CursorPaginatedIteratorFactory.cs @@ -0,0 +1,21 @@ +using System; +using ZendeskApi.Client.Pagination; +using ZendeskApi.Client.Responses; + +namespace ZendeskApi.Client.IntegrationTests.Factories +{ + public class CursorPaginatedIteratorFactory + { + private readonly ZendeskClientFactory zendeskClientFactory; + public CursorPaginatedIteratorFactory(ZendeskClientFactory _zendeskClientFactory) + { + zendeskClientFactory = _zendeskClientFactory; + } + + public CursorPaginatedIterator Create(ICursorPagination response) + { + return new CursorPaginatedIterator(response, zendeskClientFactory.GetApiClient()); + } + } +} + diff --git a/test/ZendeskApi.Client.IntegrationTests/Factories/ZendeskClientFactory.cs b/test/ZendeskApi.Client.IntegrationTests/Factories/ZendeskClientFactory.cs index 5ae20f19..78667cc2 100644 --- a/test/ZendeskApi.Client.IntegrationTests/Factories/ZendeskClientFactory.cs +++ b/test/ZendeskApi.Client.IntegrationTests/Factories/ZendeskClientFactory.cs @@ -7,20 +7,26 @@ namespace ZendeskApi.Client.IntegrationTests.Factories { public class ZendeskClientFactory { + public static IZendeskClient zendeskClient; public IZendeskClient GetClient() { - var settings = new ZendeskSettings(); + zendeskClient ??= new ZendeskClient(GetApiClient()); + return zendeskClient; + } - return new ZendeskClient( - new ZendeskApiClient( + public static ZendeskApiClient apiClient; + public ZendeskApiClient GetApiClient() + { + var settings = new ZendeskSettings(); + apiClient ??= new ZendeskApiClient( new OptionsWrapper(new ZendeskOptions { EndpointUri = settings.Url, Username = settings.Username, Token = settings.Token }) - ) - ); + ); + return apiClient; } } } diff --git a/test/ZendeskApi.Client.IntegrationTests/Resources/JobStatusResourceTests.cs b/test/ZendeskApi.Client.IntegrationTests/Resources/JobStatusResourceTests.cs new file mode 100644 index 00000000..df8f1f08 --- /dev/null +++ b/test/ZendeskApi.Client.IntegrationTests/Resources/JobStatusResourceTests.cs @@ -0,0 +1,41 @@ +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using ZendeskApi.Client.IntegrationTests.Factories; +using ZendeskApi.Client.Models; + +namespace ZendeskApi.Client.IntegrationTests.Resources +{ + public class JobStatusResourceTests : IClassFixture + { + private readonly ZendeskClientFactory clientFactory; + private readonly CursorPaginatedIteratorFactory cursorPaginatedIteratorFactory; + public JobStatusResourceTests( + ZendeskClientFactory _clientFactory) + { + clientFactory = _clientFactory; + cursorPaginatedIteratorFactory = new CursorPaginatedIteratorFactory(clientFactory); + } + + + [Fact] + public async Task GetAllAsync_WhenCalledWithCursorPagination_ShouldBePaginatable() + { + var client = clientFactory.GetClient(); + + var results = await client + .JobStatuses.GetAllAsync(new CursorPager() + { + Size = 2 + }); + var iterator = cursorPaginatedIteratorFactory.Create(results); + + Assert.NotNull(results); + Assert.Equal(2, iterator.Count()); + + await iterator.NextPage(); + Assert.True(iterator.Count() <= 2); + } + + } +} diff --git a/test/ZendeskApi.Client.IntegrationTests/Resources/RequestsResourceTests.cs b/test/ZendeskApi.Client.IntegrationTests/Resources/RequestsResourceTests.cs index 55352495..ba025307 100644 --- a/test/ZendeskApi.Client.IntegrationTests/Resources/RequestsResourceTests.cs +++ b/test/ZendeskApi.Client.IntegrationTests/Resources/RequestsResourceTests.cs @@ -12,6 +12,7 @@ public class RequestsResourceTests : IClassFixture { private readonly ITestOutputHelper _output; private readonly ZendeskClientFactory _clientFactory; + private readonly CursorPaginatedIteratorFactory cursorPaginatedIteratorFactory; public RequestsResourceTests( ITestOutputHelper output, @@ -19,6 +20,7 @@ public RequestsResourceTests( { _output = output; _clientFactory = clientFactory; + cursorPaginatedIteratorFactory = new CursorPaginatedIteratorFactory(clientFactory); } [Fact] @@ -244,5 +246,25 @@ public async Task UpdateAsync_WhenCalled_ShouldUpdateRequest() comments, comment => comment.Body.Contains($"ZendeskApi.Client.IntegrationTests {updatedId}")); } + + [Fact] + public async Task GetAllAsync_And_GetAllComments_ShouldBePaginatable() + { + var client = _clientFactory.GetClient(); + var cursor = new CursorPager { Size = 1 }; + var requestsResponse = await client.Requests.GetAllAsync(cursor); + + var requestsIterator = cursorPaginatedIteratorFactory.Create(requestsResponse); + Assert.Equal(1, requestsIterator.Count()); + + var commentsResponse = await client.Requests.GetAllComments((long)requestsIterator.First().Id, cursor); + Assert.Equal(1, commentsResponse.Count()); + + await requestsIterator.NextPage(); + Assert.Equal(1, requestsIterator.Count()); + commentsResponse = await client.Requests.GetAllComments((long)requestsIterator.First().Id, cursor); + Assert.Equal(1, commentsResponse.Count()); + } + } } diff --git a/test/ZendeskApi.Client.IntegrationTests/Resources/TicketAuditResourceTests.cs b/test/ZendeskApi.Client.IntegrationTests/Resources/TicketAuditResourceTests.cs index 64e39447..0019197f 100644 --- a/test/ZendeskApi.Client.IntegrationTests/Resources/TicketAuditResourceTests.cs +++ b/test/ZendeskApi.Client.IntegrationTests/Resources/TicketAuditResourceTests.cs @@ -27,5 +27,29 @@ public async Task GetAllAsync_WhenCalledWithCursorVariantPagination_ShouldReturn Assert.NotNull(results); Assert.Equal(100, results.Count()); } + + [Fact] + public async Task GetAllAsync_WhenCalledWithCursorPagination_ShouldBePaginatable() + { + var client = _clientFactory.GetClient(); + + var cursorPager = new CursorPager { Size = 2 }; + var auditsPageOne = await client + .TicketAudits.GetAllAsync(cursorPager); + + Assert.NotNull(auditsPageOne); + Assert.Equal(2, auditsPageOne.Count()); + Assert.True(auditsPageOne.Meta.HasMore); + + cursorPager.AfterCursor = auditsPageOne.Meta.AfterCursor; + + var auditsPageTwo = await client.TicketAudits.GetAllAsync(cursorPager); + Assert.NotNull(auditsPageTwo); + Assert.Equal(2, auditsPageTwo.Count()); + + var auditIdsPageOne = auditsPageOne.Select(tag => tag.Id).ToList(); + var auditIdsPageTwo = auditsPageTwo.Select(tag => tag.Id).ToList(); + Assert.NotEqual(auditIdsPageOne, auditIdsPageTwo); + } } } \ No newline at end of file diff --git a/test/ZendeskApi.Client.Tests/Resources/TicketAuditResourceTests.cs b/test/ZendeskApi.Client.Tests/Resources/TicketAuditResourceTests.cs index 03971c7e..7233520c 100644 --- a/test/ZendeskApi.Client.Tests/Resources/TicketAuditResourceTests.cs +++ b/test/ZendeskApi.Client.Tests/Resources/TicketAuditResourceTests.cs @@ -21,6 +21,7 @@ public TicketAuditResourceTests() } [Fact] + [Obsolete] public async Task GetAllAsync_WhenCalled_ShouldGetAllTicketAudits() { var results = await _resource.GetAllAsync(); @@ -29,6 +30,7 @@ public async Task GetAllAsync_WhenCalled_ShouldGetAllTicketAudits() } [Fact] + [Obsolete] public async Task GetAllAsync_WhenCalledAndLimitSet_ShouldGetAllTicketAudits() { var results = await _resource.GetAllAsync(new CursorPagerVariant