import { AuditAction } from './entities/audit-log.entity'; import { INTENTIONALLY_UNEMITTED_ACTIONS } from './intentionally-unemitted-actions'; import { readFileSync, readdirSync } from 'node:fs'; import { join } from 'node:path'; /** * Structural gate: every `AuditAction` enum member must either be emitted somewhere in * `src/` (an `AuditAction.` literal at a real call site) or be registered in * `INTENTIONALLY_UNEMITTED_ACTIONS` with a reason. This keeps the audit vocabulary honest — * an enum value that implies an audited event cannot silently exist with no emission site, * and new values cannot be added without either wiring them or documenting why they are held back. */ const SRC_DIR = join(__dirname, '..', '..'); function listTsFiles(dir: string, out: string[] = []): string[] { for (const ent of readdirSync(dir, { withFileTypes: true })) { if (ent.name === 'node_modules') continue; const full = join(dir, ent.name); if (ent.isDirectory()) { listTsFiles(full, out); } else if (ent.name.endsWith('.ts')) { out.push(full); } } return out; } const isExcluded = (file: string): boolean => file.endsWith('.spec.ts') || file.endsWith('.test.ts') || file.endsWith('audit-coverage.spec.ts') || file.endsWith('audit-log.entity.ts') || file.endsWith('intentionally-unemitted-actions.ts'); const sourceBodies = listTsFiles(SRC_DIR) .filter(file => !isExcluded(file)) .map(file => readFileSync(file, 'utf8')); const memberKeys = Object.keys(AuditAction) as (keyof typeof AuditAction)[]; const isEmitted = (key: keyof typeof AuditAction | undefined): boolean => key !== undefined && sourceBodies.some(body => body.includes(`AuditAction.${key}`)); const memberKeyForValue = (value: string): keyof typeof AuditAction | undefined => memberKeys.find(k => AuditAction[k] === (value as AuditAction)); describe('audit action emit coverage', () => { it.each(memberKeys)('AuditAction.%s is emitted somewhere in src/ or registered as intentionally unemitted', key => { const registered = Boolean(INTENTIONALLY_UNEMITTED_ACTIONS[AuditAction[key]]); expect(isEmitted(key) || registered).toBe(true); }); it('intentionally-unemitted registry has no stale entries (none is actually emitted)', () => { const stale = Object.keys(INTENTIONALLY_UNEMITTED_ACTIONS) .map(value => memberKeyForValue(value)) .filter((key): key is keyof typeof AuditAction => Boolean(key) && isEmitted(key)); expect(stale).toEqual([]); }); it('intentionally-unemitted registry entries each carry a non-empty reason', () => { const empties = Object.entries(INTENTIONALLY_UNEMITTED_ACTIONS) .filter(([, reason]) => typeof reason !== 'string' || reason.trim().length === 0) .map(([value]) => value); expect(empties).toEqual([]); }); });