import { describe, it, expect } from 'vitest'; import { pageCount, clampPage, offsetFor, pageInfo, pageWindow } from '@/lib/pagination'; describe('pageCount', () => { it('is at least 1', () => { expect(pageCount(0, 50)).toBe(1); expect(pageCount(-5, 50)).toBe(1); expect(pageCount(Number.NaN, 50)).toBe(1); }); it('rounds up', () => { expect(pageCount(50, 50)).toBe(1); expect(pageCount(51, 50)).toBe(2); expect(pageCount(405, 50)).toBe(9); expect(pageCount(3000, 50)).toBe(60); }); it('guards against a zero page size', () => { expect(pageCount(10, 0)).toBe(10); }); }); describe('clampPage', () => { it('clamps into [1, pageCount]', () => { expect(clampPage(0, 405, 50)).toBe(1); expect(clampPage(-3, 405, 50)).toBe(1); expect(clampPage(9, 405, 50)).toBe(9); expect(clampPage(10, 405, 50)).toBe(9); expect(clampPage(99999, 405, 50)).toBe(9); expect(clampPage(Number.NaN, 405, 50)).toBe(1); expect(clampPage(2.7, 405, 50)).toBe(2); }); it('is 1 when there are no rows', () => { expect(clampPage(7, 0, 50)).toBe(1); }); }); describe('offsetFor', () => { it('computes SQL offsets', () => { expect(offsetFor(1, 50)).toBe(0); expect(offsetFor(2, 50)).toBe(50); expect(offsetFor(9, 25)).toBe(200); expect(offsetFor(0, 50)).toBe(0); }); }); describe('pageInfo', () => { it('describes a middle page', () => { const p = pageInfo(3, 50, 405); expect(p).toMatchObject({ page: 3, pageSize: 50, total: 405, pageCount: 9, offset: 100, from: 101, to: 150, hasPrev: true, hasNext: true }); }); it('describes the last, partial page', () => { const p = pageInfo(9, 50, 405); expect(p).toMatchObject({ page: 9, offset: 400, from: 401, to: 405, hasPrev: true, hasNext: false }); }); it('clamps an out-of-range request to the last page (never an empty page)', () => { const p = pageInfo(50, 50, 405); expect(p.page).toBe(9); expect(p.offset).toBe(400); }); it('handles an empty result', () => { const p = pageInfo(1, 50, 0); expect(p).toMatchObject({ page: 1, pageCount: 1, offset: 0, from: 0, to: 0, hasPrev: false, hasNext: false }); }); it('handles a single page', () => { const p = pageInfo(1, 25, 12); expect(p).toMatchObject({ page: 1, pageCount: 1, from: 1, to: 12, hasPrev: false, hasNext: false }); }); }); describe('pageWindow', () => { it('collapses to [1] for one page', () => { expect(pageWindow(1, 1)).toEqual([1]); }); it('shows first, last and neighbours with gaps', () => { expect(pageWindow(7, 20)).toEqual([1, null, 6, 7, 8, null, 20]); }); it('fills a gap of exactly one page instead of an ellipsis', () => { expect(pageWindow(3, 20)).toEqual([1, 2, 3, 4, null, 20]); expect(pageWindow(18, 20)).toEqual([1, null, 17, 18, 19, 20]); }); it('lists every page when there are few', () => { expect(pageWindow(2, 4)).toEqual([1, 2, 3, 4]); expect(pageWindow(1, 2)).toEqual([1, 2]); }); it('honours a wider radius', () => { expect(pageWindow(10, 30, 2)).toEqual([1, null, 8, 9, 10, 11, 12, null, 30]); }); });