meld
Version:
Meld: A template language for LLM prompts
159 lines (127 loc) • 5.54 kB
text/typescript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { TestContext } from './utils/TestContext.js';
import { CLIService, IPromptService } from '../services/cli/CLIService/CLIService.js';
describe('Output Filename Handling', () => {
let context: TestContext;
let cliService: CLIService;
const mockPromptService: IPromptService = {
getText: vi.fn()
};
beforeEach(async () => {
// Set up test context
context = new TestContext();
await context.initialize();
// Create sample files
const meldContent = `
@text greeting = "Hello"
@text name = "World"
{{greeting}}, {{name}}!
`;
await context.fs.writeFile('$PROJECTPATH/test.mld', meldContent);
await context.fs.writeFile('$PROJECTPATH/test.md', meldContent);
// Set up CLI service with our test context
cliService = new CLIService(
context.services.parser,
context.services.interpreter,
context.services.output,
context.services.filesystem,
context.services.path,
context.services.state,
mockPromptService
);
// Reset the mock between tests
vi.mocked(mockPromptService.getText).mockReset();
// Enable test mode for PathService
context.services.path.enableTestMode();
});
afterEach(async () => {
// Clean up
await context.cleanup();
});
it('should use .o.md extension for markdown output by default', async () => {
// Call the private method directly using type assertion
const outputPath = await (cliService as any).determineOutputPath({
input: '$PROJECTPATH/test.mld',
format: 'markdown'
});
// Should use .o.md instead of .md
expect(outputPath).toContain('test.o.md');
});
it('should use .o.xml extension for XML output by default', async () => {
// Call the private method directly using type assertion
const outputPath = await (cliService as any).determineOutputPath({
input: '$PROJECTPATH/test.mld',
format: 'xml'
});
// Should use .o.xml instead of .xml
expect(outputPath).toContain('test.o.xml');
});
it('should use .o.md extension for .md input files as well', async () => {
// Call the private method directly using type assertion
const outputPath = await (cliService as any).determineOutputPath({
input: '$PROJECTPATH/test.md',
format: 'markdown'
});
// Should use .o.md to avoid overwriting
expect(outputPath).toContain('test.o.md');
});
it('should respect explicit output path when provided', async () => {
// Call the private method directly using type assertion
const outputPath = await (cliService as any).determineOutputPath({
input: '$PROJECTPATH/test.mld',
output: '$PROJECTPATH/custom.md',
format: 'markdown'
});
// Should use the explicit path
expect(outputPath).toContain('custom.md');
});
it('should generate incremental filenames when file exists and overwrite is declined', async () => {
// Create an existing output file
await context.fs.writeFile('$PROJECTPATH/test.o.md', 'existing content');
// Call the findAvailableIncrementalFilename method directly
const result = await (cliService as any).findAvailableIncrementalFilename('$PROJECTPATH/test.o.md');
// Debug log
console.log('Result:', result);
// Should generate an incremental filename
expect(result.outputPath).toContain('test.o-1.md');
expect(result.shouldOverwrite).toBe(true);
});
it('should continue incrementing filename until available one is found', async () => {
// Create existing output files
await context.fs.writeFile('$PROJECTPATH/test.o.md', 'existing content');
await context.fs.writeFile('$PROJECTPATH/test.o-1.md', 'existing content');
await context.fs.writeFile('$PROJECTPATH/test.o-2.md', 'existing content');
// Create a spy on the fileSystemService.exists method
const existsSpy = vi.spyOn(cliService['fileSystemService'], 'exists');
// Mock the exists method to return true for the first two incremental filenames
existsSpy.mockImplementation(async (path: string) => {
console.log('Checking if exists:', path);
if (path === '$PROJECTPATH/test.o.md' ||
path === '$PROJECTPATH/test.o-1.md' ||
path === '$PROJECTPATH/test.o-2.md') {
return true;
}
return false;
});
// Call the findAvailableIncrementalFilename method directly
const result = await (cliService as any).findAvailableIncrementalFilename('$PROJECTPATH/test.o.md');
// Debug log
console.log('Result:', result);
// Should find the next available incremental filename
expect(result.outputPath).toContain('test.o-3.md');
expect(result.shouldOverwrite).toBe(true);
// Restore the spy
existsSpy.mockRestore();
});
it('should allow overwriting if user confirms', async () => {
// Create an existing output file
await context.fs.writeFile('$PROJECTPATH/test.o.md', 'existing content');
// Mock user confirming overwrite
vi.mocked(mockPromptService.getText).mockResolvedValueOnce('y');
// Call the confirmOverwrite method
const result = await (cliService as any).confirmOverwrite('$PROJECTPATH/test.o.md');
// Should keep the same filename but set shouldOverwrite to true
expect(result.outputPath).toContain('test.o.md');
expect(result.shouldOverwrite).toBe(true);
});
});