Adds a test for parse-prd.
This commit is contained in:
@@ -3,17 +3,63 @@
|
||||
*/
|
||||
|
||||
import { jest } from '@jest/globals';
|
||||
import { findNextTask } from '../../scripts/modules/task-manager.js';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('fs');
|
||||
jest.mock('path');
|
||||
jest.mock('@anthropic-ai/sdk');
|
||||
jest.mock('cli-table3');
|
||||
jest.mock('../../scripts/modules/ui.js');
|
||||
jest.mock('../../scripts/modules/ai-services.js');
|
||||
jest.mock('../../scripts/modules/dependency-manager.js');
|
||||
jest.mock('../../scripts/modules/utils.js');
|
||||
// Mock implementations
|
||||
const mockReadFileSync = jest.fn();
|
||||
const mockExistsSync = jest.fn();
|
||||
const mockMkdirSync = jest.fn();
|
||||
const mockDirname = jest.fn();
|
||||
const mockCallClaude = jest.fn();
|
||||
const mockWriteJSON = jest.fn();
|
||||
const mockGenerateTaskFiles = jest.fn();
|
||||
|
||||
// Mock fs module
|
||||
jest.mock('fs', () => ({
|
||||
readFileSync: mockReadFileSync,
|
||||
existsSync: mockExistsSync,
|
||||
mkdirSync: mockMkdirSync
|
||||
}));
|
||||
|
||||
// Mock path module
|
||||
jest.mock('path', () => ({
|
||||
dirname: mockDirname
|
||||
}));
|
||||
|
||||
// Mock AI services
|
||||
jest.mock('../../scripts/modules/ai-services.js', () => ({
|
||||
callClaude: mockCallClaude
|
||||
}));
|
||||
|
||||
// Mock utils
|
||||
jest.mock('../../scripts/modules/utils.js', () => ({
|
||||
writeJSON: mockWriteJSON,
|
||||
log: jest.fn()
|
||||
}));
|
||||
|
||||
// Create a simplified version of parsePRD for testing
|
||||
const testParsePRD = async (prdPath, outputPath, numTasks) => {
|
||||
try {
|
||||
const prdContent = mockReadFileSync(prdPath, 'utf8');
|
||||
const tasks = await mockCallClaude(prdContent, prdPath, numTasks);
|
||||
const dir = mockDirname(outputPath);
|
||||
|
||||
if (!mockExistsSync(dir)) {
|
||||
mockMkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
mockWriteJSON(outputPath, tasks);
|
||||
await mockGenerateTaskFiles(outputPath, dir);
|
||||
|
||||
return tasks;
|
||||
} catch (error) {
|
||||
console.error(`Error parsing PRD: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Import after mocks
|
||||
import { findNextTask } from '../../scripts/modules/task-manager.js';
|
||||
import { sampleClaudeResponse } from '../fixtures/sample-claude-response.js';
|
||||
|
||||
describe('Task Manager Module', () => {
|
||||
beforeEach(() => {
|
||||
@@ -182,4 +228,81 @@ describe('Task Manager Module', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parsePRD function', () => {
|
||||
// Mock the sample PRD content
|
||||
const samplePRDContent = '# Sample PRD for Testing';
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset all mocks
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Set up mocks for fs, path and other modules
|
||||
mockReadFileSync.mockReturnValue(samplePRDContent);
|
||||
mockExistsSync.mockReturnValue(true);
|
||||
mockDirname.mockReturnValue('tasks');
|
||||
mockCallClaude.mockResolvedValue(sampleClaudeResponse);
|
||||
mockGenerateTaskFiles.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
test('should parse a PRD file and generate tasks', async () => {
|
||||
// Call the test version of parsePRD
|
||||
await testParsePRD('path/to/prd.txt', 'tasks/tasks.json', 3);
|
||||
|
||||
// Verify fs.readFileSync was called with the correct arguments
|
||||
expect(mockReadFileSync).toHaveBeenCalledWith('path/to/prd.txt', 'utf8');
|
||||
|
||||
// Verify callClaude was called with the correct arguments
|
||||
expect(mockCallClaude).toHaveBeenCalledWith(samplePRDContent, 'path/to/prd.txt', 3);
|
||||
|
||||
// Verify directory check
|
||||
expect(mockExistsSync).toHaveBeenCalledWith('tasks');
|
||||
|
||||
// Verify writeJSON was called with the correct arguments
|
||||
expect(mockWriteJSON).toHaveBeenCalledWith('tasks/tasks.json', sampleClaudeResponse);
|
||||
|
||||
// Verify generateTaskFiles was called
|
||||
expect(mockGenerateTaskFiles).toHaveBeenCalledWith('tasks/tasks.json', 'tasks');
|
||||
});
|
||||
|
||||
test('should create the tasks directory if it does not exist', async () => {
|
||||
// Mock existsSync to return false to simulate directory doesn't exist
|
||||
mockExistsSync.mockReturnValueOnce(false);
|
||||
|
||||
// Call the function
|
||||
await testParsePRD('path/to/prd.txt', 'tasks/tasks.json', 3);
|
||||
|
||||
// Verify mkdir was called
|
||||
expect(mockMkdirSync).toHaveBeenCalledWith('tasks', { recursive: true });
|
||||
});
|
||||
|
||||
test('should handle errors in the PRD parsing process', async () => {
|
||||
// Mock an error in callClaude
|
||||
const testError = new Error('Test error in Claude API call');
|
||||
mockCallClaude.mockRejectedValueOnce(testError);
|
||||
|
||||
// Mock console.error and process.exit
|
||||
const mockConsoleError = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
|
||||
// Call the function
|
||||
await testParsePRD('path/to/prd.txt', 'tasks/tasks.json', 3);
|
||||
|
||||
// Verify error handling
|
||||
expect(mockConsoleError).toHaveBeenCalled();
|
||||
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
||||
|
||||
// Restore mocks
|
||||
mockConsoleError.mockRestore();
|
||||
mockProcessExit.mockRestore();
|
||||
});
|
||||
|
||||
test('should generate individual task files after creating tasks.json', async () => {
|
||||
// Call the function
|
||||
await testParsePRD('path/to/prd.txt', 'tasks/tasks.json', 3);
|
||||
|
||||
// Verify generateTaskFiles was called
|
||||
expect(mockGenerateTaskFiles).toHaveBeenCalledWith('tasks/tasks.json', 'tasks');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user