/** * update-snapshot — unit + writer/reader round-trip. * * The round-trip test is the important one: it proves the hashes WRITTEN by * update-snapshot are byte-identical to the hashes compute-page-diff READS, so * a snapshot taken right after a run reports every page as `unchanged`. Any * drift between the two scanners would surface here as false `modified`. */ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { execute } from '../execute.js' import { computeDiff } from '../../compute-page-diff/compute-diff.js' import { canonicalHash } from '../../../../lib/canonical-hash.js' import { SNAPSHOT_FILENAME } from '../../compute-page-diff/scan-pagespecs.js' const SPEC_A = { screenCode: 'SCR-A-001', entity: 'TypeAffaire', view: 'list', columns: [{ key: 'code' }] } const SPEC_B = { screenCode: 'SCR-B-001', entity: 'TypeAffaire', view: 'form', fields: ['code'] } describe('update-snapshot execute', () => { let moduleRoot: string beforeEach(() => { moduleRoot = mkdtempSync(join(tmpdir(), 'update-snapshot-')) mkdirSync(join(moduleRoot, 'pagespecs'), { recursive: true }) }) afterEach(() => rmSync(moduleRoot, { recursive: true, force: true })) function writePagespec(name: string, spec: object): void { writeFileSync(join(moduleRoot, 'pagespecs', name), '```json\n' + JSON.stringify(spec) + '\n```\n', 'utf8') } it('writes a snapshot with the canonical hash of every pagespec', () => { writePagespec('TypeAffaire.list.md', SPEC_A) writePagespec('TypeAffaire.form.md', SPEC_B) const report = execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' }) expect(report.pageCount).toBe(2) expect(report.lastRun).toBe('2026-05-29T00:00:00Z') const written = JSON.parse(readFileSync(join(moduleRoot, SNAPSHOT_FILENAME), 'utf8')) expect(written.lastRun).toBe('2026-05-29T00:00:00Z') expect(written.pages).toEqual({ 'TypeAffaire.list': canonicalHash(SPEC_A), 'TypeAffaire.form': canonicalHash(SPEC_B), }) }) it('round-trips: a diff taken right after update-snapshot is all-unchanged', () => { writePagespec('TypeAffaire.list.md', SPEC_A) writePagespec('TypeAffaire.form.md', SPEC_B) execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' }) const diff = computeDiff({ moduleRoot }) expect(diff.snapshotFound).toBe(true) expect(diff.diff.unchanged).toEqual(['TypeAffaire.form', 'TypeAffaire.list']) expect(diff.toRegenerate).toEqual([]) }) it('overwrites a stale snapshot so a later edit reads as modified', () => { writePagespec('TypeAffaire.list.md', SPEC_A) execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' }) // Edit the pagespec, then diff WITHOUT re-snapshotting → modified. writePagespec('TypeAffaire.list.md', { ...SPEC_A, columns: [{ key: 'code' }, { key: 'libelle' }] }) const diff = computeDiff({ moduleRoot }) expect(diff.diff.modified.map((m) => m.key)).toEqual(['TypeAffaire.list']) // Re-snapshot → diff is clean again. execute({ moduleRoot, timestamp: '2026-05-29T01:00:00Z' }) expect(computeDiff({ moduleRoot }).toRegenerate).toEqual([]) }) })