From a4ff3644e010d6b62e09cc3ec024788387c011ca Mon Sep 17 00:00:00 2001 From: berce <75228263+bercedev@users.noreply.github.com> Date: Wed, 21 Oct 2026 20:21:26 +0300 Subject: [PATCH] feat(query): add Skip() and Top() to QuickbaseQueryBuilder Build() sets Options only when one of them was called, and skip and top are left out of the JSON at their default, so Skip(100) alone doesn't also send top: 0. --- .../Tests/QuickbaseQueryBuilderTests.cs | 43 +++++++++++++++++++ QuickbaseNet/Helpers/QuickbaseQueryBuilder.cs | 29 ++++++++++++- QuickbaseNet/Models/Options.cs | 4 +- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 QuickbaseNet.UnitTests/Tests/QuickbaseQueryBuilderTests.cs diff --git a/QuickbaseNet.UnitTests/Tests/QuickbaseQueryBuilderTests.cs b/QuickbaseNet.UnitTests/Tests/QuickbaseQueryBuilderTests.cs new file mode 100644 index 0000000..101278c --- /dev/null +++ b/QuickbaseNet.UnitTests/Tests/QuickbaseQueryBuilderTests.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json; +using QuickbaseNet.Helpers; + +namespace QuickbaseNet.UnitTests.Tests; + +public class QuickbaseQueryBuilderTests +{ + [Fact] + public void Build_SetsSkipAndTop_WhenBothAreCalled() + { + // Act + var request = new QuickbaseQueryBuilder().From("bck7").Skip(100).Top(50).Build(); + + // Assert + Assert.NotNull(request.Options); + Assert.Equal(100, request.Options.Skip); + Assert.Equal(50, request.Options.Top); + } + + [Fact] + public void Build_LeavesOptionsNull_WhenNeitherIsCalled() + { + // Act + var request = new QuickbaseQueryBuilder().From("bck7").Select(3, 6).Build(); + + // Assert + Assert.Null(request.Options); + } + + [Fact] + public void Serialize_SendsSkipWithoutTop_WhenOnlySkipIsCalled() + { + // Arrange + var request = new QuickbaseQueryBuilder().From("bck7").Skip(100).Build(); + + // Act + var json = JsonConvert.SerializeObject(request); + + // Assert + Assert.Contains("\"skip\":100", json); + Assert.DoesNotContain("\"top\"", json); + } +} diff --git a/QuickbaseNet/Helpers/QuickbaseQueryBuilder.cs b/QuickbaseNet/Helpers/QuickbaseQueryBuilder.cs index c7684b9..edcb8ef 100644 --- a/QuickbaseNet/Helpers/QuickbaseQueryBuilder.cs +++ b/QuickbaseNet/Helpers/QuickbaseQueryBuilder.cs @@ -15,6 +15,8 @@ public class QuickbaseQueryBuilder private string _where; private List _sortBy; private List _groupBy; + private int? _skip; + private int? _top; /// /// Specifies the table to query. @@ -79,6 +81,28 @@ public QuickbaseQueryBuilder GroupBy(int fieldId, string grouping) return this; } + /// + /// Skips the given number of records at the start of the result set, for paging. + /// + /// The number of records to skip. + /// The current instance of QuickbaseQueryBuilder. + public QuickbaseQueryBuilder Skip(int count) + { + _skip = count; + return this; + } + + /// + /// Returns at most the given number of records, for paging. + /// + /// The maximum number of records to return. + /// The current instance of QuickbaseQueryBuilder. + public QuickbaseQueryBuilder Top(int count) + { + _top = count; + return this; + } + /// /// Builds the query. /// @@ -91,7 +115,10 @@ public QuickbaseQueryRequest Build() Select = _select, Where = _where, SortBy = _sortBy, - GroupBy = _groupBy + GroupBy = _groupBy, + Options = _skip == null && _top == null + ? null + : new Options { Skip = _skip ?? 0, Top = _top ?? 0 } }; } } diff --git a/QuickbaseNet/Models/Options.cs b/QuickbaseNet/Models/Options.cs index 19a4029..4ba454e 100644 --- a/QuickbaseNet/Models/Options.cs +++ b/QuickbaseNet/Models/Options.cs @@ -10,13 +10,13 @@ public class Options /// /// Gets or sets the number of records to skip in the result set. /// - [JsonProperty("skip")] + [JsonProperty("skip", DefaultValueHandling = DefaultValueHandling.Ignore)] public int Skip { get; set; } /// /// Gets or sets the maximum number of records to return in the result set. /// - [JsonProperty("top")] + [JsonProperty("top", DefaultValueHandling = DefaultValueHandling.Ignore)] public int Top { get; set; } ///