import { describe, it, expect } from 'vitest'; import { statSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { loadRegistry, clearCache } from './registry-load.mjs'; import { buildNodeGraph, resolveNode, twinsOf, checkGraphFreshness } from './node-graph.mjs'; const here = dirname(fileURLToPath(import.meta.url)); const registryPath = join(here, '..', 'docs', 'registry', 'nodes.yaml'); describe('Машина 3-B — граф на реальном реестре', () => { it('граф строится из nodes.yaml и резолвит известные узлы', () => { clearCache(); const reg = loadRegistry({ registryPath, useCache: false }); const g = buildNodeGraph(reg); expect(g.nodes.length).toBeGreaterThan(50); expect(resolveNode(g, '#36a')).not.toBe(null); // adr-kit:adr by id (#36 развёрнут в #36a/#36b) expect(resolveNode(g, 'mermaid')).not.toBe(null); // by slug expect(resolveNode(g, 'totally-made-up-skill')).toBe(null); // выдумка }); it('близнецы architecture-tooling включают друг друга', () => { clearCache(); const reg = loadRegistry({ registryPath, useCache: false }); const g = buildNodeGraph(reg); const adr = resolveNode(g, 'adr-kit'); if (adr && adr.subcategory) { const twinSlugs = twinsOf(g, adr.id).map((n) => n.slug); expect(twinSlugs.length).toBeGreaterThanOrEqual(1); } }); it('freshness против реальной mtime реестра работает', () => { const mtime = statSync(registryPath).mtimeMs; expect(checkGraphFreshness({ registryMtimeMs: mtime, builtAtMs: mtime + 1000 }).fresh).toBe(true); expect(checkGraphFreshness({ registryMtimeMs: mtime, builtAtMs: mtime - 1000 }).stale).toBe(true); }); });