import { readdirSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import { describe, expect, it } from 'vitest'; import { atmEventSchema, deterministicId, ingestBatchSchema } from '../src/index.ts'; const dir = join(import.meta.dirname, '..', 'fixtures', 'protocol'); describe('protocol v1', () => { it('every fixture validates', () => { const files = readdirSync(dir).filter((f) => f.endsWith('.json')); expect(files.length).toBe(11); for (const f of files) { const parsed = atmEventSchema.parse(JSON.parse(readFileSync(join(dir, f), 'utf8'))); expect(parsed.type).toBe(f.replace('.json', '')); } }); it('rejects unknown type', () => { const r = atmEventSchema.safeParse({ id: '0199d6a0-0000-7000-8000-000000000001', type: 'nope', ts: 1 }); expect(r.success).toBe(false); }); it('rejects batch with 501 events', () => { const ev = JSON.parse(readFileSync(join(dir, 'server_stop.json'), 'utf8')); const r = ingestBatchSchema.safeParse({ protocol: 1, events: Array.from({ length: 501 }, () => ev) }); expect(r.success).toBe(false); }); it('deterministicId is stable', () => { expect(deterministicId('a')).toBe(deterministicId('a')); expect(deterministicId('a')).not.toBe(deterministicId('b')); expect(deterministicId('a')).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/); }); });