Files
dashcaddy/dashcaddy-api/__tests__/pagination.test.js
T
Hermes 7bc2a207f3 DC-005: Fix all 138 broken test paths after src/ refactor
After the DC-005 module reorganization (41 files moved into src/ subdirs),
138 test suites failed because the refactor script's path-rewrite logic
missed three categories:

1. Files inside src/ doing 'require("./src/...")' — should be 'require("../...")'
2. Files in src/X/Y/ doing 'require("../../../src/...")' — should be 'require("../../...")'
3. Test files in __tests__/ with leftover 'require("../../../src/...")' paths

Root cause: the original refactor script ran before all files were moved,
so it computed relative paths against stale filesystem state.

Result:
- 30/30 test suites pass
- 879/879 tests pass (was: 18/30 suites, 614/687 tests)

Also fixed:
- routes/apps/restore.js: wrong responses import path
- routes/*/*.js: '../../src/utilities/X' → '../src/utilities/X' (depth 2 routes)
2026-06-13 12:16:56 -07:00

117 lines
4.2 KiB
JavaScript

const { paginate, parsePaginationParams, DEFAULT_LIMIT, MAX_LIMIT } = require('../src/utilities/pagination');
describe('Pagination — DashCaddy list endpoints', () => {
describe('parsePaginationParams', () => {
it('returns null when no pagination params (backward compat — full list)', () => {
expect(parsePaginationParams({})).toBeNull();
expect(parsePaginationParams({ search: 'plex' })).toBeNull();
});
it('parses page and limit from query', () => {
const params = parsePaginationParams({ page: '2', limit: '10' });
expect(params).toEqual({ page: 2, limit: 10 });
});
it('defaults page to 1', () => {
expect(parsePaginationParams({ limit: '25' })).toEqual({ page: 1, limit: 25 });
});
it('defaults limit to DEFAULT_LIMIT when only page given', () => {
expect(parsePaginationParams({ page: '3' })).toEqual({ page: 3, limit: DEFAULT_LIMIT });
});
it('clamps page to minimum 1', () => {
expect(parsePaginationParams({ page: '0' }).page).toBe(1);
expect(parsePaginationParams({ page: '-5' }).page).toBe(1);
});
it('treats limit 0 as default (parseInt falsy → DEFAULT_LIMIT)', () => {
expect(parsePaginationParams({ limit: '0' }).limit).toBe(DEFAULT_LIMIT);
});
it('clamps negative limit to minimum 1', () => {
expect(parsePaginationParams({ limit: '-10' }).limit).toBe(1);
});
it('clamps limit to MAX_LIMIT', () => {
expect(parsePaginationParams({ limit: '9999' }).limit).toBe(MAX_LIMIT);
});
it('handles NaN gracefully', () => {
const params = parsePaginationParams({ page: 'abc', limit: 'xyz' });
expect(params.page).toBe(1);
expect(params.limit).toBe(DEFAULT_LIMIT);
});
});
describe('paginate', () => {
const items = Array.from({ length: 55 }, (_, i) => ({ id: `svc-${i + 1}` }));
it('returns all items when params is null (no pagination)', () => {
const result = paginate(items, null);
expect(result.data).toHaveLength(55);
expect(result.pagination).toBeUndefined();
});
it('returns first page correctly', () => {
const result = paginate(items, { page: 1, limit: 10 });
expect(result.data).toHaveLength(10);
expect(result.data[0].id).toBe('svc-1');
expect(result.pagination.page).toBe(1);
expect(result.pagination.total).toBe(55);
expect(result.pagination.totalPages).toBe(6);
expect(result.pagination.hasMore).toBe(true);
});
it('returns last page with fewer items', () => {
const result = paginate(items, { page: 6, limit: 10 });
expect(result.data).toHaveLength(5); // 55 - 50 = 5 remaining
expect(result.data[0].id).toBe('svc-51');
expect(result.pagination.hasMore).toBe(false);
});
it('returns empty array for page beyond total', () => {
const result = paginate(items, { page: 100, limit: 10 });
expect(result.data).toHaveLength(0);
expect(result.pagination.hasMore).toBe(false);
});
it('handles empty list', () => {
const result = paginate([], { page: 1, limit: 10 });
expect(result.data).toHaveLength(0);
expect(result.pagination.total).toBe(0);
expect(result.pagination.totalPages).toBe(0);
});
it('single-page result when limit exceeds total', () => {
const result = paginate(items, { page: 1, limit: 100 });
expect(result.data).toHaveLength(55);
expect(result.pagination.totalPages).toBe(1);
expect(result.pagination.hasMore).toBe(false);
});
});
describe('Real DashCaddy scenario: 52 app templates paginated', () => {
const templates = Array.from({ length: 52 }, (_, i) => ({
id: `app-${i}`,
name: `App ${i}`,
category: i < 10 ? 'Media' : 'Utilities'
}));
it('default limit (50) shows first 50 apps with hasMore', () => {
const params = parsePaginationParams({ page: '1' });
const result = paginate(templates, params);
expect(result.data).toHaveLength(50);
expect(result.pagination.hasMore).toBe(true);
});
it('page 2 shows remaining 2 apps', () => {
const params = parsePaginationParams({ page: '2' });
const result = paginate(templates, params);
expect(result.data).toHaveLength(2);
expect(result.pagination.hasMore).toBe(false);
});
});
});