UNPKG

meld

Version:

Meld: A template language for LLM prompts

164 lines (139 loc) 5.54 kB
import { describe, it, expect, beforeEach } from 'vitest'; import { StateService } from './StateService.js'; import { migrateState, validateMigration } from './migration.js'; import type { MeldNode } from 'meld-spec'; import type { StateNode } from './types.js'; describe('State Migration', () => { let oldState: StateService; beforeEach(() => { oldState = new StateService(); }); describe('basic migration', () => { it('should migrate empty state', () => { const result = migrateState(oldState, { validate: false }); expect(result.success).toBe(true); expect(result.warnings).toHaveLength(0); expect(result.state.variables.text.size).toBe(0); expect(result.state.variables.data.size).toBe(0); expect(result.state.variables.path.size).toBe(0); expect(result.state.commands.size).toBe(0); expect(result.state.imports.size).toBe(0); expect(result.state.nodes.length).toBe(0); }); it('should migrate state with variables', () => { // Set up old state oldState.setTextVar('text', 'value'); oldState.setDataVar('data', { key: 'value' }); oldState.setPathVar('path', '/test/path'); const result = migrateState(oldState, { validate: false }); expect(result.success).toBe(true); expect(result.warnings).toHaveLength(0); // Verify text variables expect(result.state.variables.text.get('text')).toBe('value'); // Verify data variables expect(result.state.variables.data.get('data')).toEqual({ key: 'value' }); // Verify path variables expect(result.state.variables.path.get('path')).toBe('/test/path'); }); it('should migrate state with commands', () => { // Set up old state oldState.setCommand('test', 'echo test'); oldState.setCommand('complex', { command: 'test', options: { silent: true } }); const result = migrateState(oldState, { validate: false }); expect(result.success).toBe(true); expect(result.warnings).toHaveLength(0); // Verify commands expect(result.state.commands.get('test')).toEqual({ command: 'echo test' }); expect(result.state.commands.get('complex')).toEqual({ command: 'test', options: { silent: true } }); }); it('should migrate state with imports', () => { // Set up old state oldState.addImport('test1.md'); oldState.addImport('test2.md'); const result = migrateState(oldState, { validate: false }); expect(result.success).toBe(true); expect(result.warnings).toHaveLength(0); // Verify imports expect(result.state.imports.has('test1.md')).toBe(true); expect(result.state.imports.has('test2.md')).toBe(true); }); it('should migrate state with nodes', () => { // Set up old state const node: MeldNode = { type: 'text', value: 'test', location: { start: { line: 1, column: 1 }, end: { line: 1, column: 4 } } }; oldState.addNode(node); const result = migrateState(oldState, { validate: false }); expect(result.success).toBe(true); expect(result.warnings).toHaveLength(0); // Verify nodes expect(result.state.nodes).toHaveLength(1); expect(result.state.nodes[0]).toEqual(node); }); }); describe('validation', () => { it('should detect mismatched text variables', () => { // Create a state that will be different after migration oldState.setTextVar('test', 'value'); // Create a mismatched state manually const mismatchedState: StateNode = { variables: { text: new Map([['test', 'different']]), data: new Map(), path: new Map() }, commands: new Map(), imports: new Set(), nodes: [], }; // Validate the mismatched state const warnings: string[] = []; validateMigration(oldState, mismatchedState, warnings); expect(warnings).toContain('Text variable mismatch: test'); }); it('should fail strictly with validation errors', () => { oldState.setTextVar('test', 'value'); // Create a mismatched state to force validation error const mismatchedState: StateNode = { variables: { text: new Map([['test', 'different']]), data: new Map(), path: new Map() }, commands: new Map(), imports: new Set(), nodes: [], }; expect(() => { const warnings: string[] = []; validateMigration(oldState, mismatchedState, warnings); if (warnings.length > 0) { throw new Error('Migration validation failed:\n' + warnings.join('\n')); } }).toThrow('Migration validation failed'); }); }); describe('error handling', () => { it('should handle migration errors gracefully', () => { // Create an invalid state that will cause migration to fail const invalidState = { getAllTextVars: () => { throw new Error('Test error'); }, getAllDataVars: () => new Map(), getAllPathVars: () => new Map(), getAllCommands: () => new Map(), getImports: () => new Set(), getNodes: () => [], getCurrentFilePath: () => null } as unknown as StateService; const result = migrateState(invalidState); expect(result.success).toBe(false); expect(result.warnings).toContain('Error: Test error'); expect(result.state.variables.text.size).toBe(0); }); }); });