UNPKG

cmte

Version:

Design by Committee™ except it's just you and LLMs

222 lines (193 loc) 6.71 kB
import { describe, it, expect, beforeEach } from 'vitest'; import { VariableResolver } from '../VariableResolver'; import { ValidationError } from '../errors'; import { Workflow, IterationContext } from '../types'; describe('VariableResolver', () => { let workflow: Workflow; let resolver: VariableResolver; beforeEach(() => { workflow = { variables: { globalVar: 'global-value', config: { key: 'value' } }, objectsForIteration: { services: { auth: { code: 'auth.ts' }, user: { code: 'user.ts' } }, set1: { auth: { output: 'auth-result' }, user: { output: 'user-result' } }, subSet: { config: { output: 'config-result' }, data: { output: 'data-result' } } } }; resolver = new VariableResolver(workflow); }); describe('resolve', () => { it('should resolve global variables', () => { expect(resolver.resolve('globalVar')).toBe('global-value'); expect(resolver.resolve('config')).toEqual({ key: 'value' }); }); it('should throw on invalid global variables', () => { expect(() => { resolver.resolve('invalidVar'); }).toThrow(ValidationError); }); it('should resolve output paths', () => { resolver.registerOutput('phase1.set1.output', 'result'); expect(resolver.resolve('$phase1.set1.output')).toBe('result'); }); it('should throw on invalid output paths', () => { expect(() => { resolver.resolve('$invalid.path'); }).toThrow(ValidationError); }); it('should resolve humanInputRequired paths', () => { resolver.registerOutput('phase1.services[auth]', { code: 'auth-code' }, { currentIteration: 'auth', parentIterations: ['services'] }); expect(resolver.resolve('$phase1.services[auth]')).toEqual({ code: 'auth-code' }); }); it('should resolve humanInputRequired paths with $this', () => { resolver.registerOutput('phase1.services[$this]', { code: 'auth-code' }, { currentIteration: 'auth', parentIterations: ['services'] }); expect( resolver.resolve('$phase1.services[$this]', { currentIteration: 'auth', parentIterations: ['services'] }) ).toEqual({ code: 'auth-code' }); }); it('should resolve humanInputRequired paths with .all', () => { resolver.registerOutput('phase1.services[auth]', { code: 'auth-code' }, { currentIteration: 'auth', parentIterations: ['services'] }); resolver.registerOutput('phase1.services[user]', { code: 'user-code' }, { currentIteration: 'user', parentIterations: ['services'] }); expect(resolver.resolve('$phase1.services.all')).toEqual([ { code: 'auth-code' }, { code: 'user-code' } ]); }); }); describe('registerOutput', () => { const context: IterationContext = { currentIteration: 'auth', parentIterations: ['services'] }; it('should register simple outputs', () => { resolver.registerOutput('phase1.set1.output', 'result'); expect(resolver.getPhaseOutputs('phase1')).toEqual({ set1: { output: 'result' } }); }); it('should register nested outputs', () => { resolver.registerOutput('phase1.set1[auth].output', 'auth-result', context); resolver.registerOutput('phase1.set1[user].output', 'user-result', context); expect(resolver.getPhaseOutputs('phase1')).toEqual({ set1: { auth: { output: 'auth-result' }, user: { output: 'user-result' } } }); }); it('should handle $this in output paths', () => { resolver.registerOutput('phase1.set1[$this].output', 'auth-result', context); expect(resolver.getPhaseOutputs('phase1')).toEqual({ set1: { auth: { output: 'auth-result' } } }); }); it('should create intermediate objects as needed', () => { resolver.registerOutput('phase1.set1[auth].nested.deep.output', 'result', context); expect(resolver.getPhaseOutputs('phase1')).toEqual({ set1: { auth: { nested: { deep: { output: 'result' } } } } }); }); }); describe('getPhaseOutputs', () => { it('should return undefined for unknown phases', () => { expect(resolver.getPhaseOutputs('unknown')).toBeUndefined(); }); it('should return all outputs for a phase', () => { resolver.registerOutput('phase1.set1.output1', 'result1'); resolver.registerOutput('phase1.set2.output2', 'result2'); expect(resolver.getPhaseOutputs('phase1')).toEqual({ set1: { output1: 'result1' }, set2: { output2: 'result2' } }); }); }); describe('clearOutputs', () => { it('should clear all registered outputs', () => { resolver.registerOutput('phase1.set1.output', 'result'); resolver.clearOutputs(); expect(resolver.getPhaseOutputs('phase1')).toBeUndefined(); }); }); describe('complex scenarios', () => { const context: IterationContext = { currentIteration: 'auth', parentIterations: ['services'] }; it('should handle deeply nested iterations', () => { // Register outputs for nested iterations resolver.registerOutput( 'phase1.set1[$this].subSet[config].output', 'auth-config-result', context ); // Try resolving with different contexts expect( resolver.resolve('$phase1.set1[auth].subSet[config].output', context) ).toBe('auth-config-result'); }); it('should collect all outputs correctly', () => { // Register multiple outputs resolver.registerOutput('phase1.set1[auth].output', 'auth-result', context); resolver.registerOutput('phase1.set1[user].output', 'user-result', context); // Collect all outputs const allResults = resolver.resolve('$phase1.set1.all', context); expect(allResults).toEqual([ { output: 'auth-result' }, { output: 'user-result' } ]); }); it('should validate against objectsForIteration consistently', () => { // Should work with valid service resolver.registerOutput('phase1.services[auth].output', 'result', context); // Should fail with invalid service expect(() => { resolver.registerOutput( 'phase1.services[invalid].output', 'result', context ); }).toThrow(ValidationError); }); }); });