From df75cd25e0a1beb55be97d5fcb8a718806793f51 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sun, 5 Jan 2025 16:57:13 -0600 Subject: [PATCH] feat: add model to represent paged request --- src/AnthropicClient/Models/PagingRequest.cs | 80 +++++++++++++++++++ .../Unit/Models/PagingRequestTests.cs | 70 ++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/AnthropicClient/Models/PagingRequest.cs create mode 100644 tests/AnthropicClient.Tests/Unit/Models/PagingRequestTests.cs diff --git a/src/AnthropicClient/Models/PagingRequest.cs b/src/AnthropicClient/Models/PagingRequest.cs new file mode 100644 index 0000000..b7aad83 --- /dev/null +++ b/src/AnthropicClient/Models/PagingRequest.cs @@ -0,0 +1,80 @@ +using System.Text.Json.Serialization; + +namespace AnthropicClient.Models; + +/// +/// Represents a request to page through a collection of items. +/// +public class PagingRequest +{ + private const int LimitMinimum = 1; + private const int LimitMaximum = 1000; + private const int DefaultLimit = 20; + + /// + /// The ID of the item before which to start the page. + /// + [JsonPropertyName("before_id")] + public string BeforeId { get; init; } + + /// + /// The ID of the item after which to start the page. + /// + [JsonPropertyName("after_id")] + public string AfterId { get; init; } + + /// + /// The maximum number of items to return in the page. + /// + public int Limit { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The ID of the item before which to start the page. + /// The ID of the item after which to start the page. + /// The maximum number of items to return in the page. + /// Thrown when is less than 1 or greater than 1000. + /// A new instance of the class. + public PagingRequest( + string beforeId = "", + string afterId = "", + int limit = DefaultLimit + ) + { + if (limit is < LimitMinimum or > LimitMaximum) + { + throw new ArgumentOutOfRangeException(nameof(limit), $"{nameof(limit)} must be between {LimitMinimum} and {LimitMaximum}."); + } + + BeforeId = beforeId; + AfterId = afterId; + Limit = limit; + } + + /// + /// Converts the to a query string. + /// + /// The query string representation of the . + public string ToQueryParameters() + { + var parameters = new List(); + + if (string.IsNullOrEmpty(BeforeId) is false) + { + parameters.Add($"before_id={BeforeId}"); + } + + if (string.IsNullOrEmpty(AfterId) is false) + { + parameters.Add($"after_id={AfterId}"); + } + + if (Limit is not DefaultLimit) + { + parameters.Add($"limit={Limit}"); + } + + return string.Join("&", parameters); + } +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Unit/Models/PagingRequestTests.cs b/tests/AnthropicClient.Tests/Unit/Models/PagingRequestTests.cs new file mode 100644 index 0000000..54e6c8f --- /dev/null +++ b/tests/AnthropicClient.Tests/Unit/Models/PagingRequestTests.cs @@ -0,0 +1,70 @@ +namespace AnthropicClient.Tests.Unit.Models; + +public class PagingRequestTests : SerializationTest +{ + [Fact] + public void Constructor_WhenLimitIsLessThanMinimum_ItShouldThrowArgumentOutOfRangeException() + { + var act = () => new PagingRequest(limit: 0); + + act.Should().Throw().WithMessage("limit must be between 1 and 1000. (Parameter 'limit')"); + } + + [Fact] + public void Constructor_WhenLimitIsGreaterThanMaximum_ItShouldThrowArgumentOutOfRangeException() + { + var act = () => new PagingRequest(limit: 1001); + + act.Should().Throw().WithMessage("limit must be between 1 and 1000. (Parameter 'limit')"); + } + + [Fact] + public void ToQueryParameters_WhenNoPropertiesSet_ItShouldReturnEmptyString() + { + var pagingRequest = new PagingRequest(); + + var result = pagingRequest.ToQueryParameters(); + + result.Should().BeEmpty(); + } + + [Fact] + public void ToQueryParameters_WhenBeforeIdIsSet_ItShouldReturnBeforeId() + { + var pagingRequest = new PagingRequest(beforeId: "before-id"); + + var result = pagingRequest.ToQueryParameters(); + + result.Should().Be("before_id=before-id"); + } + + [Fact] + public void ToQueryParameters_WhenAfterIdIsSet_ItShouldReturnAfterId() + { + var pagingRequest = new PagingRequest(afterId: "after-id"); + + var result = pagingRequest.ToQueryParameters(); + + result.Should().Be("after_id=after-id"); + } + + [Fact] + public void ToQueryParameters_WhenLimitIsSetToNonDefaultValue_ItShouldReturnLimit() + { + var pagingRequest = new PagingRequest(limit: 10); + + var result = pagingRequest.ToQueryParameters(); + + result.Should().Be("limit=10"); + } + + [Fact] + public void ToQueryParameters_WhenAllPropertiesAreSet_ItShouldReturnAllProperties() + { + var pagingRequest = new PagingRequest(beforeId: "before-id", afterId: "after-id", limit: 10); + + var result = pagingRequest.ToQueryParameters(); + + result.Should().Be("before_id=before-id&after_id=after-id&limit=10"); + } +} \ No newline at end of file