paginate.test.ts
Language TypeScript3.2 KB104 lines
import { describe, expect, it } from 'vitest'import {collect,fromArray,fromEnvelope,fromTeamKeyed,iterateAll,type Page,} from '../src/paginate.js'import { NinetySchemaError } from '../src/errors.js'const ctx = { endpoint: 'POST /test' }describe('fromEnvelope: Issues, KPIs', () => {it('reads items and totalCount', () => {const p = fromEnvelope<number>({ items: [1, 2, 3], totalCount: 10 }, { page: 0, pageSize: 3 }, ctx)expect(p.items).toEqual([1, 2, 3])expect(p.total).toBe(10)expect(p.hasMore).toBe(true)})it('reports hasMore false on the last page', () => {const p = fromEnvelope<number>({ items: [9, 10], totalCount: 10 }, { page: 4, pageSize: 2 }, ctx)expect(p.hasMore).toBe(false)})it('rejects a bare array', () => {expect(() => fromEnvelope([1, 2], { page: 0, pageSize: 2 }, ctx)).toThrow(NinetySchemaError)})})describe('fromArray: To-Dos, Teams', () => {it('wraps a bare array with no total', () => {const p = fromArray<number>([1, 2], { page: 0, pageSize: 5 }, ctx)expect(p.items).toEqual([1, 2])expect(p.total).toBeNull()expect(p.hasMore).toBe(false)})it('infers hasMore from a full page', () => {const p = fromArray<number>([1, 2, 3], { page: 0, pageSize: 3 }, ctx)expect(p.hasMore).toBe(true)})it('rejects an envelope', () => {expect(() => fromArray({ items: [] }, { page: 0, pageSize: 5 }, ctx)).toThrow(NinetySchemaError)})})describe('fromTeamKeyed: Rocks', () => {it('flattens and stamps teamId', () => {const raw = { teamA: [{ title: 'x' }], teamB: [{ title: 'y' }, { title: 'z' }] }const p = fromTeamKeyed<{ title: string }>(raw, { page: 0, pageSize: 50 }, ctx)expect(p.items).toHaveLength(3)expect(p.items.map((i) => i.teamId)).toEqual(['teamA', 'teamB', 'teamB'])expect(p.items[0]?.title).toBe('x')})it('rejects an array', () => {expect(() => fromTeamKeyed([], { page: 0, pageSize: 5 }, ctx)).toThrow(NinetySchemaError)})})describe('iterateAll', () => {const pageOf = (items: number[], page: number, pageSize: number, hasMore: boolean): Page<number> => ({items,total: null,pageIndex: page,pageSize,hasMore,})it('walks every page and stops when hasMore is false', async () => {const pages = [pageOf([1, 2], 0, 2, true),pageOf([3, 4], 1, 2, true),pageOf([5], 2, 2, false),]const seen: number[] = []const all = await collect(iterateAll<number>(async (req) => {seen.push(req.page)return pages[req.page]!}, { page: 0, pageSize: 2 }),)expect(all).toEqual([1, 2, 3, 4, 5])expect(seen).toEqual([0, 1, 2])})it('stops on an empty page even if hasMore lies', async () => {const all = await collect(iterateAll<number>(async (req) => pageOf([], req.page, 2, true), { page: 0, pageSize: 2 }),)expect(all).toEqual([])})it('throws at the safety cap rather than looping forever', async () => {await expect(collect(iterateAll<number>(async (req) => pageOf([1], req.page, 1, true), { page: 0, pageSize: 1 }, { maxPages: 3 }),),).rejects.toThrow(/safety cap/)})})