import { describe, it, expect } from 'vitest';
import { topoSort, incomingEdges } from './topo';

const e = (source: string, target: string) => ({ id: `${source}-${target}`, source, target });

describe('topoSort', () => {
  it('orders a linear chain', () => {
    expect(topoSort(['a', 'b', 'c'], [e('a', 'b'), e('b', 'c')])).toEqual(['a', 'b', 'c']);
  });

  it('places a dependency before its dependents in a diamond', () => {
    const order = topoSort(['a', 'b', 'c', 'd'], [e('a', 'b'), e('a', 'c'), e('b', 'd'), e('c', 'd')]);
    expect(order.indexOf('a')).toBeLessThan(order.indexOf('b'));
    expect(order.indexOf('b')).toBeLessThan(order.indexOf('d'));
    expect(order.indexOf('c')).toBeLessThan(order.indexOf('d'));
  });

  it('throws on a cycle', () => {
    expect(() => topoSort(['a', 'b'], [e('a', 'b'), e('b', 'a')])).toThrow(/Cycle/);
  });

  it('finds incoming edges for a node', () => {
    expect(incomingEdges('d', [e('b', 'd'), e('c', 'd'), e('a', 'b')]).map((x) => x.source)).toEqual(['b', 'c']);
  });
});
