spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import { describe, it, expect } from 'vitest';2import { pageCount, clampPage, offsetFor, pageInfo, pageWindow } from '@/lib/pagination';34describe('pageCount', () => {5 it('is at least 1', () => {6 expect(pageCount(0, 50)).toBe(1);7 expect(pageCount(-5, 50)).toBe(1);8 expect(pageCount(Number.NaN, 50)).toBe(1);9 });10 it('rounds up', () => {11 expect(pageCount(50, 50)).toBe(1);12 expect(pageCount(51, 50)).toBe(2);13 expect(pageCount(405, 50)).toBe(9);14 expect(pageCount(3000, 50)).toBe(60);15 });16 it('guards against a zero page size', () => {17 expect(pageCount(10, 0)).toBe(10);18 });19});2021describe('clampPage', () => {22 it('clamps into [1, pageCount]', () => {23 expect(clampPage(0, 405, 50)).toBe(1);24 expect(clampPage(-3, 405, 50)).toBe(1);25 expect(clampPage(9, 405, 50)).toBe(9);26 expect(clampPage(10, 405, 50)).toBe(9);27 expect(clampPage(99999, 405, 50)).toBe(9);28 expect(clampPage(Number.NaN, 405, 50)).toBe(1);29 expect(clampPage(2.7, 405, 50)).toBe(2);30 });31 it('is 1 when there are no rows', () => {32 expect(clampPage(7, 0, 50)).toBe(1);33 });34});3536describe('offsetFor', () => {37 it('computes SQL offsets', () => {38 expect(offsetFor(1, 50)).toBe(0);39 expect(offsetFor(2, 50)).toBe(50);40 expect(offsetFor(9, 25)).toBe(200);41 expect(offsetFor(0, 50)).toBe(0);42 });43});4445describe('pageInfo', () => {46 it('describes a middle page', () => {47 const p = pageInfo(3, 50, 405);48 expect(p).toMatchObject({ page: 3, pageSize: 50, total: 405, pageCount: 9, offset: 100, from: 101, to: 150, hasPrev: true, hasNext: true });49 });50 it('describes the last, partial page', () => {51 const p = pageInfo(9, 50, 405);52 expect(p).toMatchObject({ page: 9, offset: 400, from: 401, to: 405, hasPrev: true, hasNext: false });53 });54 it('clamps an out-of-range request to the last page (never an empty page)', () => {55 const p = pageInfo(50, 50, 405);56 expect(p.page).toBe(9);57 expect(p.offset).toBe(400);58 });59 it('handles an empty result', () => {60 const p = pageInfo(1, 50, 0);61 expect(p).toMatchObject({ page: 1, pageCount: 1, offset: 0, from: 0, to: 0, hasPrev: false, hasNext: false });62 });63 it('handles a single page', () => {64 const p = pageInfo(1, 25, 12);65 expect(p).toMatchObject({ page: 1, pageCount: 1, from: 1, to: 12, hasPrev: false, hasNext: false });66 });67});6869describe('pageWindow', () => {70 it('collapses to [1] for one page', () => {71 expect(pageWindow(1, 1)).toEqual([1]);72 });73 it('shows first, last and neighbours with gaps', () => {74 expect(pageWindow(7, 20)).toEqual([1, null, 6, 7, 8, null, 20]);75 });76 it('fills a gap of exactly one page instead of an ellipsis', () => {77 expect(pageWindow(3, 20)).toEqual([1, 2, 3, 4, null, 20]);78 expect(pageWindow(18, 20)).toEqual([1, null, 17, 18, 19, 20]);79 });80 it('lists every page when there are few', () => {81 expect(pageWindow(2, 4)).toEqual([1, 2, 3, 4]);82 expect(pageWindow(1, 2)).toEqual([1, 2]);83 });84 it('honours a wider radius', () => {85 expect(pageWindow(10, 30, 2)).toEqual([1, null, 8, 9, 10, 11, 12, null, 30]);86 });87});88