UNPKG

meld

Version:

Meld: A template language for LLM prompts

173 lines (138 loc) 6.29 kB
import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { DirectiveService } from './DirectiveService.js'; import { TestContext } from '@tests/utils/TestContext.js'; import { DirectiveError, DirectiveErrorCode } from './errors/DirectiveError.js'; import type { DirectiveNode } from 'meld-spec'; describe('DirectiveService', () => { let context: TestContext; let service: DirectiveService; beforeEach(async () => { // Initialize test context context = new TestContext(); await context.initialize(); // Create service instance service = new DirectiveService(); // Initialize with real services from context service.initialize( context.services.validation, context.services.state, context.services.path, context.services.filesystem, context.services.parser, context.services.interpreter, context.services.circularity, context.services.resolution ); // Load test fixtures await context.fixtures.load('directiveTestProject'); }); afterEach(async () => { await context.cleanup(); }); describe('Service initialization', () => { it('should initialize with all required services', () => { expect(service.getSupportedDirectives()).toContain('text'); expect(service.getSupportedDirectives()).toContain('data'); expect(service.getSupportedDirectives()).toContain('path'); }); it('should throw if used before initialization', async () => { const uninitializedService = new DirectiveService(); const node = context.factory.createTextDirective('test', '"value"', context.factory.createLocation(1, 1)); const execContext = { currentFilePath: 'test.meld', state: context.services.state }; await expect(uninitializedService.processDirective(node, execContext)) .rejects.toThrow('DirectiveService must be initialized before use'); }); }); describe('Directive processing', () => { describe('Text directives', () => { it('should process basic text directive', async () => { // Verify file exists const exists = await context.fs.exists('test.meld'); console.log('test.meld exists:', exists); // Parse the fixture file const content = await context.fs.readFile('test.meld'); console.log('test.meld content:', content); const nodes = await context.services.parser.parse(content); console.log('Parsed nodes:', nodes); const node = nodes[0] as DirectiveNode; // Create execution context const execContext = { currentFilePath: 'test.meld', state: context.services.state }; // Process the directive const result = await service.processDirective(node, execContext); // Verify the result expect(result.getTextVar('greeting')).toBe('Hello'); }); it('should process text directive with variable interpolation', async () => { // Set up initial state with a variable const state = context.services.state; state.setTextVar('name', 'World'); // Parse and process const content = await context.fs.readFile('test-interpolation.meld'); const nodes = await context.services.parser.parse(content); const node = nodes[0] as DirectiveNode; const result = await service.processDirective(node, { currentFilePath: 'test-interpolation.meld', state }); expect(result.getTextVar('greeting')).toBe('Hello World'); }); }); describe('Data directives', () => { it('should process data directive with object value', async () => { const content = await context.fs.readFile('test-data.meld'); const nodes = await context.services.parser.parse(content); const node = nodes[0] as DirectiveNode; const result = await service.processDirective(node, { currentFilePath: 'test-data.meld', state: context.services.state }); expect(result.getDataVar('config')).toEqual({ key: 'value' }); }); it('should process data directive with variable interpolation', async () => { // Set up initial state const state = context.services.state; state.setTextVar('user', 'Alice'); const content = await context.fs.readFile('test-data-interpolation.meld'); const nodes = await context.services.parser.parse(content); const node = nodes[0] as DirectiveNode; const result = await service.processDirective(node, { currentFilePath: 'test-data-interpolation.meld', state }); expect(result.getDataVar('config')).toEqual({ greeting: 'Hello Alice' }); }); }); describe('Import directives', () => { it('should process basic import', async () => { // Create import directive node with value property const node = context.factory.createImportDirective('module.meld', context.factory.createLocation(1, 1)); const result = await service.processDirective(node, { currentFilePath: 'main.meld', state: context.services.state }); expect(result.getTextVar('greeting')).toBe('Hello'); }); it('should handle nested imports', async () => { // Create import directive node with value property const node = context.factory.createImportDirective('inner.meld', context.factory.createLocation(1, 1)); const result = await service.processDirective(node, { currentFilePath: 'middle.meld', state: context.services.state }); expect(result.getTextVar('greeting')).toBe('Hello'); }); it('should detect circular imports', async () => { // Create import directive node with value property const node = context.factory.createImportDirective('b.meld', context.factory.createLocation(1, 1)); await expect(service.processDirective(node, { currentFilePath: 'a.meld', state: context.services.state })).rejects.toThrow(DirectiveError); }); }); // ... continue with other directive types and error cases }); });