Skip to content

Commit 0863dee

Browse files
fix(pagination): guard against division by zero when Size is 0 (#59)
- Clamp pagination.Size to minimum of 1 before division operations - Add regression tests for Size=0 edge case
1 parent 9fb463d commit 0863dee

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

JsonApiToolkit.Tests/Extensions/QueryableExtensionTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,32 @@ public async Task Issue_Scenario_PageTwoOfOneTotal_ReturnsLastPageDataAsync()
371371
Assert.Equal(1, result.First().Id);
372372
}
373373

374+
[Fact]
375+
public void ApplyPagination_WithSizeZero_TreatsAsSize1()
376+
{
377+
var query = GetTestData();
378+
var pagination = new PaginationParameters { Number = 1, Size = 0 };
379+
380+
var result = query.ApplyPagination(pagination).ToList();
381+
382+
Assert.Single(result);
383+
Assert.Equal(1, result[0].Id);
384+
}
385+
386+
[Fact]
387+
public async Task CreatePaginationMetaAsync_WithSizeZero_TreatsAsSize1Async()
388+
{
389+
var query = GetTestData();
390+
var pagination = new PaginationParameters { Number = 1, Size = 0 };
391+
392+
var meta = await query.CreatePaginationMetaAsync(pagination);
393+
394+
Assert.Equal(5, meta.TotalResources);
395+
Assert.Equal(5, meta.TotalPages); // 5 items / size 1 = 5 pages
396+
Assert.Equal(1, meta.CurrentPage);
397+
Assert.Equal(1, meta.PageSize); // Clamped to 1
398+
}
399+
374400
[Fact]
375401
public void ApplyFilters_WithInFilter_FiltersCorrectly()
376402
{

JsonApiToolkit/Extensions/Querying/Handlers/PaginationHandler.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ public static IQueryable<T> ApplyPagination<T>(
1818
PaginationParameters pagination
1919
)
2020
{
21+
int size = Math.Max(1, pagination.Size);
2122
int totalCount = query.Count();
22-
int totalPages = (int)Math.Ceiling(totalCount / (double)pagination.Size);
23+
int totalPages = (int)Math.Ceiling(totalCount / (double)size);
2324
int effectivePage = Math.Max(1, Math.Min(pagination.Number, Math.Max(totalPages, 1)));
2425

25-
int skip = (effectivePage - 1) * pagination.Size;
26-
return query.Skip(skip).Take(pagination.Size);
26+
int skip = (effectivePage - 1) * size;
27+
return query.Skip(skip).Take(size);
2728
}
2829

2930
/// <summary>
@@ -44,15 +45,16 @@ PaginationParameters pagination
4445
totalCount = query.Count(); // Fallback for in-memory queryables
4546
}
4647

47-
int totalPages = (int)Math.Ceiling(totalCount / (double)pagination.Size);
48+
int size = Math.Max(1, pagination.Size);
49+
int totalPages = (int)Math.Ceiling(totalCount / (double)size);
4850
int effectivePage = Math.Max(1, Math.Min(pagination.Number, Math.Max(totalPages, 1)));
4951

5052
return new PaginationMeta
5153
{
5254
TotalResources = totalCount,
5355
TotalPages = totalPages,
5456
CurrentPage = effectivePage,
55-
PageSize = pagination.Size,
57+
PageSize = size,
5658
};
5759
}
5860
}

0 commit comments

Comments
 (0)