import { describe, it, expect } from 'vitest'; import { readFileSync } from 'node:fs'; import { buildDependencyGraph, topoOrder, findHoles } from './coverage-machine.mjs'; const A8 = ['owasp-zap', 'nuclei', 'ward', 'pdn-152fz-audit', 'threat-model', 'security-go-live']; const load = (slug) => JSON.parse(readFileSync(`docs/registry/contracts/${slug}.contract.json`, 'utf8')); describe('A8 coverage prototype — единый словарь оживляет автомат', () => { const contracts = A8.map(load); it('граф непуст: ≥5 рёбер сходятся в security-go-live', () => { const { edges } = buildDependencyGraph(contracts); const toGoLive = edges.filter((e) => e.to === 'security-go-live'); expect(toGoLive.length).toBeGreaterThanOrEqual(5); }); it('topoOrder: security-go-live идёт последним', () => { const { order } = topoOrder(contracts); expect(order).not.toBeNull(); expect(order[order.length - 1]).toBe('security-go-live'); }); it('findHoles: при объявленных initialInputs дыр нет (без constraints)', () => { const initialInputs = ['running-portal', 'laravel-config', 'pii-inventory-task', 'portal-pre-launch']; const holes = findHoles(contracts, { initialInputs, includeConstraints: false }); expect(holes).toEqual([]); }); });