import { describe, it, expect } from 'vitest'; import { buildNodeGraph } from './node-graph.mjs'; import { missingContracts, emptyCards, unresolvedConflicts, asymmetricConflicts } from './card-coverage.mjs'; const reg = (nodes) => ({ nodes, chains: {} }); describe('card-coverage — покрытие узел↔карточка', () => { it('missingContracts: узел без карточки (skill≠slug) попадает в список', () => { const nodes = [{ id: '#1', slug: 'a' }, { id: '#2', slug: 'b' }]; const contracts = [{ skill: 'a' }]; expect(missingContracts(nodes, contracts)).toEqual(['#2']); }); it('emptyCards: needs[] и produces[] пусты → карточка пустая', () => { const contracts = [ { skill: 'a', needs: [], produces: [] }, { skill: 'b', needs: ['x'], produces: [] }, { skill: 'c', needs: [], produces: ['y'] }, ]; expect(emptyCards(contracts)).toEqual(['a']); }); }); describe('card-coverage — конфликт-рёбра', () => { it('unresolvedConflicts: ссылка в никуда ловится', () => { const g = buildNodeGraph(reg([ { id: '#1', slug: 'a', attributes: { conflicts_with: ['nope'] } }, ])); expect(unresolvedConflicts(g)).toEqual([{ from: '#1', ref: 'nope' }]); }); it('asymmetricConflicts: A→B без B→A ловится', () => { const g = buildNodeGraph(reg([ { id: '#1', slug: 'a', attributes: { conflicts_with: ['b'] } }, { id: '#2', slug: 'b', attributes: { conflicts_with: [] } }, ])); expect(asymmetricConflicts(g)).toEqual([{ from: '#1', to: '#2' }]); }); it('симметричная пара A↔B → ни unresolved, ни asymmetric', () => { const g = buildNodeGraph(reg([ { id: '#1', slug: 'a', attributes: { conflicts_with: ['b'] } }, { id: '#2', slug: 'b', attributes: { conflicts_with: ['a'] } }, ])); expect(unresolvedConflicts(g)).toEqual([]); expect(asymmetricConflicts(g)).toEqual([]); }); });