@meldscience/meld
Version:
pipeable one-shot prompt scripting toolkit
128 lines (99 loc) • 3.73 kB
text/typescript
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { mockFs, MockAIProvider, setupMocks } from './utils';
// Setup mocks before imports
setupMocks();
// Import after mocks are setup
import { Oneshot } from '../src/oneshot';
import { ToolError } from '../src/errors';
describe('Oneshot', () => {
beforeEach(() => {
vi.clearAllMocks();
mockFs.existsSync.mockReturnValue(true);
});
test('sends basic prompt to AI provider', async () => {
const mockResponse = 'AI response';
const provider = new MockAIProvider(mockResponse);
mockFs.readFileSync.mockReturnValue('test prompt');
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md'
}, provider);
const results = await oneshot.process();
expect(results).toHaveLength(1);
expect(results[0].response).toBe(mockResponse);
expect(results[0].variation).toBeUndefined();
expect(results[0].systemPrompt).toBe('');
});
test('includes system prompt when provided', async () => {
const provider = new MockAIProvider();
mockFs.readFileSync
.mockReturnValueOnce('user prompt') // promptFile
.mockReturnValueOnce('system prompt'); // systemFile
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md',
systemFile: 'system.md'
}, provider);
const results = await oneshot.process();
expect(results[0].systemPrompt).toBe('system prompt');
});
test('handles variations', async () => {
const provider = new MockAIProvider();
mockFs.readFileSync.mockReturnValue('base prompt');
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md',
variations: ['var1', 'var2']
}, provider);
const results = await oneshot.process();
expect(results).toHaveLength(2);
expect(results[0].variation).toBe('var1');
expect(results[1].variation).toBe('var2');
});
test('handles multiple iterations', async () => {
const provider = new MockAIProvider();
mockFs.readFileSync.mockReturnValue('test prompt');
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md',
iterations: 3
}, provider);
const results = await oneshot.process();
expect(results).toHaveLength(3);
});
test('handles variations with iterations', async () => {
const provider = new MockAIProvider();
mockFs.readFileSync.mockReturnValue('test prompt');
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md',
variations: ['var1', 'var2'],
iterations: 2
}, provider);
const results = await oneshot.process();
expect(results).toHaveLength(4); // 2 variations × 2 iterations
expect(results.filter(r => r.variation === 'var1')).toHaveLength(2);
expect(results.filter(r => r.variation === 'var2')).toHaveLength(2);
});
test('throws error if prompt file does not exist', async () => {
mockFs.existsSync.mockReturnValue(false);
const provider = new MockAIProvider();
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'nonexistent.md'
}, provider);
await expect(oneshot.process()).rejects.toThrow(ToolError);
});
test('throws error if system file does not exist', async () => {
mockFs.existsSync
.mockReturnValueOnce(true) // promptFile exists
.mockReturnValueOnce(false); // systemFile doesn't exist
const provider = new MockAIProvider();
const oneshot = new Oneshot({
model: 'test-model',
promptFile: 'prompt.md',
systemFile: 'nonexistent.md'
}, provider);
await expect(oneshot.process()).rejects.toThrow(ToolError);
});
});