UNPKG

meld

Version:

Meld: A template language for LLM prompts

205 lines (181 loc) 7.06 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import * as debugTransformModule from './debug-transform.js'; import { container } from 'tsyringe'; import { StateService } from '@services/state/StateService/StateService.js'; import { FileSystemService } from '@services/fs/FileSystemService/FileSystemService.js'; import { ParserService } from '@services/pipeline/ParserService/ParserService.js'; import { DirectiveService } from '@services/pipeline/DirectiveService/DirectiveService.js'; import { InterpreterService } from '@services/pipeline/InterpreterService/InterpreterService.js'; import { PathOperationsService } from '@services/fs/FileSystemService/PathOperationsService.js'; import { NodeFileSystem } from '@services/fs/FileSystemService/NodeFileSystem.js'; import { StateEventService } from '@services/state/StateEventService/StateEventService.js'; // Mock the services vi.mock('@services/state/StateService/StateService.js'); vi.mock('@services/fs/FileSystemService/FileSystemService.js'); vi.mock('@services/pipeline/ParserService/ParserService.js'); vi.mock('@services/pipeline/DirectiveService/DirectiveService.js'); vi.mock('@services/pipeline/InterpreterService/InterpreterService.js'); vi.mock('@services/fs/FileSystemService/PathOperationsService.js'); vi.mock('@services/fs/FileSystemService/NodeFileSystem.js'); vi.mock('@services/state/StateEventService/StateEventService.js'); // Mock fs vi.mock('fs/promises', () => ({ readFile: vi.fn().mockResolvedValue('Test content'), writeFile: vi.fn().mockResolvedValue(undefined) })); // Save original console methods const originalConsoleLog = console.log; const originalConsoleError = console.error; describe('debugTransformCommand', () => { let mockStateService; let mockFileSystemService; let mockParserService; let mockDirectiveService; let mockInterpreterService; beforeEach(() => { vi.resetAllMocks(); // Create mock services mockStateService = { getState: vi.fn().mockReturnValue({ variables: { text: { greeting: 'Hello' }, data: {} } }), getTextVar: vi.fn().mockReturnValue('Hello'), getDataVar: vi.fn().mockReturnValue({}), getPathVar: vi.fn().mockReturnValue('/test/path'), setTextVar: vi.fn(), setDataVar: vi.fn(), setPathVar: vi.fn(), setCurrentFilePath: vi.fn(), createState: vi.fn().mockReturnValue({ getId: vi.fn().mockReturnValue('test-state-id'), setFilePath: vi.fn() }) }; mockFileSystemService = { readFile: vi.fn().mockResolvedValue('Test content'), writeFile: vi.fn().mockResolvedValue(undefined), exists: vi.fn().mockResolvedValue(true), resolvePath: vi.fn().mockResolvedValue('/test/project/test.meld'), initialize: vi.fn() }; mockParserService = { parse: vi.fn().mockReturnValue({ type: 'document', children: [ { type: 'directive', name: 'text', value: 'greeting = "Hello"', location: { line: 1, column: 1 }, directive: { kind: 'text' } } ] }), parseWithLocations: vi.fn().mockReturnValue([ { type: 'directive', name: 'text', value: 'greeting = "Hello"', location: { line: 1, column: 1, filePath: 'test.meld' }, directive: { kind: 'text' } } ]) }; mockDirectiveService = { processDirective: vi.fn().mockResolvedValue({ replacement: { type: 'text', value: 'Hello', location: { line: 1, column: 1 }, transformed: true } }), initialize: vi.fn() }; mockInterpreterService = { interpret: vi.fn().mockResolvedValue({ type: 'document', children: [ { type: 'text', value: 'Hello', location: { line: 1, column: 1 }, transformed: true, interpreted: true } ] }), canHandleTransformations: vi.fn().mockReturnValue(true) }; // Mock needed dependencies const mockPathOps = { isAbsolute: vi.fn().mockReturnValue(true), join: vi.fn().mockImplementation((...args) => args.join('/')), resolve: vi.fn().mockImplementation((...args) => args.join('/')) }; const mockNodeFs = { readFile: vi.fn().mockResolvedValue('Test content'), writeFile: vi.fn().mockResolvedValue(undefined), exists: vi.fn().mockResolvedValue(true) }; // Register mock services with the container container.register('StateService', { useValue: mockStateService }); container.register('FileSystemService', { useValue: mockFileSystemService }); container.register('ParserService', { useValue: mockParserService }); container.register('DirectiveService', { useValue: mockDirectiveService }); container.register('InterpreterService', { useValue: mockInterpreterService }); container.register('PathOperationsService', { useValue: mockPathOps }); container.register('NodeFileSystem', { useValue: mockNodeFs }); // Mock console methods console.log = vi.fn(); console.error = vi.fn(); }); afterEach(() => { // Restore console methods console.log = originalConsoleLog; console.error = originalConsoleError; // Clear container container.clearInstances(); }); it('should debug transformations for a file', async () => { // Call the command await debugTransformModule.debugTransformCommand({ filePath: 'test.meld', outputFormat: 'json', includeContent: true }); // Verify services were called expect(mockFileSystemService.readFile).toHaveBeenCalledWith('test.meld'); expect(mockParserService.parse).toHaveBeenCalled(); expect(mockInterpreterService.interpret).toHaveBeenCalled(); // Verify output was generated expect(console.log).toHaveBeenCalled(); }); it('should filter by directive type when specified', async () => { // Call the command with directive type filter await debugTransformModule.debugTransformCommand({ filePath: 'test.meld', outputFormat: 'json', includeContent: true, directiveType: 'text' }); // Verify output was generated with filter expect(console.log).toHaveBeenCalled(); }); it('should handle errors gracefully', async () => { // Make the interpreter not support transformations mockInterpreterService.canHandleTransformations.mockReturnValue(false); // Call the command await debugTransformModule.debugTransformCommand({ filePath: 'test.meld', outputFormat: 'json' }); // Verify error was logged expect(console.error).toHaveBeenCalled(); const errorOutput = vi.mocked(console.error).mock.calls.flat().join('\n'); expect(errorOutput).toContain('This interpreter does not support transformations'); }); });