import { describe, expect, it } from 'vitest'; import { dataRelease, dedupeSources, envelope, paginate } from '../src/lib/envelope.js'; const src = (id: string, slug: string) => ({ id, slug, name: slug, license: 'CC BY 4.0', attribution: null, url: null }); describe('envelope', () => { it('wraps data with sources, dataRelease and generatedAt', () => { const out = envelope({ a: 1 }, [src('CI-SOURCE-00000001', 'oncotree')], undefined, new Date('2026-09-08T10:00:00Z')); expect(out.data).toEqual({ a: 1 }); expect(out.sources).toHaveLength(1); expect(out.dataRelease).toBe('CancerIndex 2026-09'); expect(new Date(out.generatedAt).getTime()).toBeGreaterThan(0); expect(out).not.toHaveProperty('total'); }); it('spreads pagination fields when provided', () => { const out = envelope([], [], paginate(250, 50, 200)); expect(out.total).toBe(250); expect(out.limit).toBe(50); expect(out.offset).toBe(200); expect(out.hasMore).toBe(false); expect(paginate(250, 50, 100).hasMore).toBe(true); }); it('deduplicates sources by id and sorts by slug', () => { const out = dedupeSources([src('CI-SOURCE-00000002', 'seer'), src('CI-SOURCE-00000001', 'oncotree'), src('CI-SOURCE-00000002', 'seer')]); expect(out.map((s) => s.slug)).toEqual(['oncotree', 'seer']); }); it('formats the data release as CancerIndex YYYY-MM', () => { expect(dataRelease(new Date('2025-01-31T23:59:59Z'))).toBe('CancerIndex 2025-01'); }); });