diff --git a/test-integration-output/test-prd.md b/test-integration-output/test-prd.md deleted file mode 100644 index 6b6bd686..00000000 --- a/test-integration-output/test-prd.md +++ /dev/null @@ -1,23 +0,0 @@ -# Product Requirements Document - -## Overview -We need to build a modern task management system with real-time collaboration features. - -## Key Features -1. User authentication and authorization -2. Task creation and management -3. Real-time updates via WebSockets -4. File attachments and comments -5. Advanced search and filtering - -## Technical Requirements -- Node.js backend with Express -- PostgreSQL database -- Redis for caching -- WebSocket support -- RESTful API design - -## Success Criteria -- Support 10,000+ concurrent users -- Sub-100ms API response times -- 99.9% uptime SLA \ No newline at end of file diff --git a/test-integration-output/test-tasks.json b/test-integration-output/test-tasks.json deleted file mode 100644 index 57f742e1..00000000 --- a/test-integration-output/test-tasks.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "master": { - "tasks": [ - { - "id": 1, - "title": "Setup project infrastructure", - "description": "Initialize the project with proper structure and dependencies", - "status": "done", - "dependencies": [], - "priority": "high", - "details": "Created project structure with src, tests, and docs folders", - "testStrategy": "Manual verification of folder structure", - "subtasks": [] - }, - { - "id": 2, - "title": "Implement authentication system", - "description": "Add user authentication with JWT tokens and OAuth2 support", - "status": "in-progress", - "dependencies": [1], - "priority": "high", - "details": "Need to support both OAuth2 and traditional email/password login", - "testStrategy": "Unit tests for auth logic, integration tests for endpoints", - "subtasks": [ - { - "id": 1, - "title": "Design authentication flow", - "description": "Create detailed flow diagrams for auth process", - "status": "done", - "dependencies": [] - }, - { - "id": 2, - "title": "Implement JWT token generation", - "description": "Create secure JWT token generation and validation", - "status": "pending", - "dependencies": [] - } - ] - }, - { - "id": 3, - "title": "Build RESTful API", - "description": "Create comprehensive REST API endpoints", - "status": "pending", - "dependencies": [2], - "priority": "medium", - "details": "Use Express.js with proper middleware and error handling", - "testStrategy": null, - "subtasks": [] - } - ], - "metadata": { - "created": "2025-07-21T00:27:15.668Z", - "updated": "2025-07-21T00:27:15.668Z", - "description": "Test project tasks" - } - } -} diff --git a/test-tasks.json b/test-tasks.json deleted file mode 100644 index f51ed4b8..00000000 --- a/test-tasks.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "projectName": "Test Project", - "tasks": [ - { - "id": 1, - "title": "Setup project structure", - "description": "Initialize the project with proper folder structure", - "status": "pending", - "dependencies": [], - "priority": "high", - "details": "Create folders for src, tests, docs", - "testStrategy": "Manual verification" - }, - { - "id": 2, - "title": "Implement authentication", - "description": "Add user authentication with JWT tokens", - "status": "pending", - "dependencies": [1], - "priority": "high", - "details": null, - "testStrategy": null - } - ] -} diff --git a/tests/integration/commands/all-commands.test.js b/tests/integration/commands/all-commands.test.js deleted file mode 100644 index 69e198eb..00000000 --- a/tests/integration/commands/all-commands.test.js +++ /dev/null @@ -1,448 +0,0 @@ -/** - * Comprehensive integration test suite for all generateObject-migrated commands - * Tests end-to-end command execution with real AI service calls - */ -import fs from 'fs'; -import path from 'path'; -import { jest } from '@jest/globals'; - -// Import all commands -import analyzeTaskComplexity from '../../../scripts/modules/task-manager/analyze-task-complexity.js'; -import updateTaskById from '../../../scripts/modules/task-manager/update-task-by-id.js'; -import expandTask from '../../../scripts/modules/task-manager/expand-task.js'; -import updateTasks from '../../../scripts/modules/task-manager/update-tasks.js'; -import addTask from '../../../scripts/modules/task-manager/add-task.js'; -import parsePRD from '../../../scripts/modules/task-manager/parse-prd.js'; - -describe('GenerateObject Migration - Comprehensive Integration Tests', () => { - const testDir = path.join(process.cwd(), 'test-integration-output'); - const testTasksFile = path.join(testDir, 'test-tasks.json'); - const testPrdFile = path.join(testDir, 'test-prd.md'); - - beforeAll(() => { - // Create test directory - if (!fs.existsSync(testDir)) { - fs.mkdirSync(testDir, { recursive: true }); - } - }); - - beforeEach(() => { - // Create initial test data - const initialTasks = { - master: { - tasks: [ - { - id: 1, - title: 'Setup project infrastructure', - description: - 'Initialize the project with proper structure and dependencies', - status: 'done', - dependencies: [], - priority: 'high', - details: - 'Created project structure with src, tests, and docs folders', - testStrategy: 'Manual verification of folder structure', - subtasks: [] - }, - { - id: 2, - title: 'Implement authentication system', - description: - 'Add user authentication with JWT tokens and OAuth2 support', - status: 'in-progress', - dependencies: [1], - priority: 'high', - details: - 'Need to support both OAuth2 and traditional email/password login', - testStrategy: - 'Unit tests for auth logic, integration tests for endpoints', - subtasks: [ - { - id: 1, - title: 'Design authentication flow', - description: 'Create detailed flow diagrams for auth process', - status: 'done', - dependencies: [] - }, - { - id: 2, - title: 'Implement JWT token generation', - description: - 'Create secure JWT token generation and validation', - status: 'pending', - dependencies: [] - } - ] - }, - { - id: 3, - title: 'Build RESTful API', - description: 'Create comprehensive REST API endpoints', - status: 'pending', - dependencies: [2], - priority: 'medium', - details: 'Use Express.js with proper middleware and error handling', - testStrategy: null, - subtasks: [] - } - ], - metadata: { - created: new Date().toISOString(), - updated: new Date().toISOString(), - description: 'Test project tasks' - } - } - }; - - fs.writeFileSync(testTasksFile, JSON.stringify(initialTasks, null, 2)); - - // Create test PRD file - const testPrd = `# Product Requirements Document - -## Overview -We need to build a modern task management system with real-time collaboration features. - -## Key Features -1. User authentication and authorization -2. Task creation and management -3. Real-time updates via WebSockets -4. File attachments and comments -5. Advanced search and filtering - -## Technical Requirements -- Node.js backend with Express -- PostgreSQL database -- Redis for caching -- WebSocket support -- RESTful API design - -## Success Criteria -- Support 10,000+ concurrent users -- Sub-100ms API response times -- 99.9% uptime SLA`; - - fs.writeFileSync(testPrdFile, testPrd); - }); - - afterEach(() => { - // Clean up test files - if (fs.existsSync(testTasksFile)) { - fs.unlinkSync(testTasksFile); - } - if (fs.existsSync(testPrdFile)) { - fs.unlinkSync(testPrdFile); - } - }); - - afterAll(() => { - // Clean up test directory - if (fs.existsSync(testDir)) { - fs.rmSync(testDir, { recursive: true }); - } - }); - - describe('analyze-complexity command', () => { - test('should analyze task complexity with structured output', async () => { - const result = await analyzeTaskComplexity( - testTasksFile, - 2, // Analyze task ID 2 - false, // Don't use research mode - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json' // JSON output format - ); - - expect(result).toBeDefined(); - expect(result.complexityAnalysis).toBeDefined(); - expect(result.complexityAnalysis.overallComplexity).toMatch( - /low|medium|high|very high/i - ); - expect(result.complexityAnalysis.factors).toBeDefined(); - expect(Array.isArray(result.complexityAnalysis.factors)).toBe(true); - expect(result.complexityAnalysis.timeEstimate).toBeDefined(); - expect(result.complexityAnalysis.riskAssessment).toBeDefined(); - expect(result.telemetryData).toBeDefined(); - }, 30000); - }); - - describe('add-task command', () => { - test('should add a new task with structured output', async () => { - const result = await addTask( - testTasksFile, - 'Implement caching layer with Redis for improved performance', - [2], // Depends on task 2 - 'medium', - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json', - null, // No manual task data - false // Don't use research mode - ); - - expect(result).toBeDefined(); - expect(result.newTaskId).toBe(4); // Should be the next ID - expect(result.telemetryData).toBeDefined(); - - // Verify task was added - const updatedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const newTask = updatedData.master.tasks.find((t) => t.id === 4); - expect(newTask).toBeDefined(); - expect(newTask.title).toContain('caching'); - expect(newTask.priority).toBe('medium'); - expect(newTask.dependencies).toContain(2); - }, 30000); - }); - - describe('expand-task command', () => { - test('should expand task into subtasks with structured output', async () => { - const result = await expandTask( - testTasksFile, - 3, // Expand task ID 3 - 5, // Generate 5 subtasks - false, // Don't use research mode - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json' - ); - - expect(result).toBeDefined(); - expect(result.expandedTask).toBeDefined(); - expect(result.generatedSubtasks).toBeDefined(); - expect(Array.isArray(result.generatedSubtasks)).toBe(true); - expect(result.generatedSubtasks.length).toBeGreaterThan(0); - expect(result.generatedSubtasks.length).toBeLessThanOrEqual(5); - - // Verify subtasks were added - const updatedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const task3 = updatedData.master.tasks.find((t) => t.id === 3); - expect(task3.subtasks).toBeDefined(); - expect(task3.subtasks.length).toBeGreaterThan(0); - }, 30000); - }); - - describe('update-task-by-id command', () => { - test('should update task with structured output (full update mode)', async () => { - const result = await updateTaskById( - testTasksFile, - 3, // Update task ID 3 - 'Add GraphQL support alongside REST API for more flexible queries', - false, // Append mode off (full update) - false, // Don't use research mode - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json' - ); - - expect(result).toBeDefined(); - expect(result.updatedTask).toBeDefined(); - expect(result.updatedTask.id).toBe(3); - expect(result.updatedTask.description.toLowerCase()).toContain('graphql'); - expect(result.telemetryData).toBeDefined(); - }, 30000); - - test('should append to task details (append mode)', async () => { - const result = await updateTaskById( - testTasksFile, - 2, // Update task ID 2 - 'Add support for multi-factor authentication', - true, // Append mode on - false, // Don't use research mode - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json' - ); - - expect(result).toBeDefined(); - expect(result.updatedTask).toBeDefined(); - expect(result.updatedTask.details).toContain( - 'multi-factor authentication' - ); - expect(result.telemetryData).toBeDefined(); - }, 30000); - }); - - describe('update-tasks command', () => { - test('should update multiple tasks with structured output', async () => { - const result = await updateTasks( - testTasksFile, - 2, // Update from task ID 2 onwards - 'Migrate to microservices architecture for better scalability', - false, // Don't use research mode - { - projectRoot: process.cwd(), - tag: 'master' - }, - 'json' - ); - - expect(result).toBeDefined(); - expect(result.success).toBe(true); - expect(result.updatedTasks).toBeDefined(); - expect(Array.isArray(result.updatedTasks)).toBe(true); - expect(result.updatedTasks.length).toBeGreaterThan(0); - - // Tasks 2 and 3 should be updated (not done) - const task2 = result.updatedTasks.find((t) => t.id === 2); - const task3 = result.updatedTasks.find((t) => t.id === 3); - expect(task2).toBeDefined(); - expect(task3).toBeDefined(); - expect(task2.description.toLowerCase()).toMatch( - /microservice|scalability/ - ); - expect(task3.description.toLowerCase()).toMatch( - /microservice|scalability/ - ); - }, 30000); - }); - - describe('parse-prd command', () => { - test('should parse PRD and generate tasks with structured output', async () => { - // Use a new file for PRD output to avoid conflicts - const prdTasksFile = path.join(testDir, 'prd-tasks.json'); - - const result = await parsePRD( - testPrdFile, - prdTasksFile, - 5, // Generate 5 tasks - { - projectRoot: process.cwd(), - force: true, - append: false, - research: false, - tag: 'master' - } - ); - - expect(result).toBeDefined(); - expect(result.success).toBe(true); - expect(result.tasksPath).toBe(prdTasksFile); - expect(result.telemetryData).toBeDefined(); - - // Verify tasks were generated - const generatedData = JSON.parse(fs.readFileSync(prdTasksFile, 'utf8')); - expect(generatedData.master).toBeDefined(); - expect(generatedData.master.tasks).toBeDefined(); - expect(generatedData.master.tasks.length).toBeGreaterThan(0); - expect(generatedData.master.tasks.length).toBeLessThanOrEqual(5); - - // Verify task quality - const firstTask = generatedData.master.tasks[0]; - expect(firstTask.title).toBeTruthy(); - expect(firstTask.description).toBeTruthy(); - expect(firstTask.status).toBe('pending'); - expect(firstTask.priority).toMatch(/low|medium|high/); - - // Clean up - fs.unlinkSync(prdTasksFile); - }, 30000); - }); - - describe('Command Integration Flow', () => { - test('should handle a complete workflow with multiple commands', async () => { - // 1. Add a new task - const addResult = await addTask( - testTasksFile, - 'Implement comprehensive logging system', - [1], - 'high', - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ); - const newTaskId = addResult.newTaskId; - - // 2. Analyze its complexity - const complexityResult = await analyzeTaskComplexity( - testTasksFile, - newTaskId, - false, - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ); - expect(complexityResult.complexityAnalysis).toBeDefined(); - - // 3. Expand it into subtasks - const expandResult = await expandTask( - testTasksFile, - newTaskId, - 3, - false, - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ); - expect(expandResult.generatedSubtasks.length).toBeGreaterThan(0); - - // 4. Update the task with additional context - const updateResult = await updateTaskById( - testTasksFile, - newTaskId, - 'Include structured logging with JSON format and log aggregation support', - false, - false, - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ); - expect(updateResult.updatedTask.description).toContain('JSON format'); - - // 5. Verify final state - const finalData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const finalTask = finalData.master.tasks.find((t) => t.id === newTaskId); - expect(finalTask).toBeDefined(); - expect(finalTask.subtasks.length).toBeGreaterThan(0); - expect(finalTask.description).toContain('JSON format'); - }, 60000); // Longer timeout for multiple operations - }); - - describe('Error Handling', () => { - test('should handle invalid task IDs gracefully', async () => { - await expect( - analyzeTaskComplexity( - testTasksFile, - 999, // Non-existent task ID - false, - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ) - ).rejects.toThrow('Task with ID 999 not found'); - }); - - test('should handle empty prompts', async () => { - await expect( - addTask( - testTasksFile, - '', // Empty prompt - [], - 'medium', - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ) - ).rejects.toThrow(); - }); - - test('should handle invalid dependencies', async () => { - const result = await addTask( - testTasksFile, - 'New task with invalid dependency', - [999], // Non-existent dependency - 'medium', - { projectRoot: process.cwd(), tag: 'master' }, - 'json' - ); - - // Should succeed but filter out invalid dependency - expect(result.newTaskId).toBeDefined(); - const data = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const newTask = data.master.tasks.find((t) => t.id === result.newTaskId); - expect(newTask.dependencies).not.toContain(999); - }); - }); -}); diff --git a/tests/integration/commands/analyze-complexity.test.js b/tests/integration/commands/analyze-complexity.test.js deleted file mode 100644 index 018cca4f..00000000 --- a/tests/integration/commands/analyze-complexity.test.js +++ /dev/null @@ -1,77 +0,0 @@ -import analyzeTaskComplexity from '../../../scripts/modules/task-manager/analyze-task-complexity.js'; -import { readJSON } from '../../../scripts/modules/utils.js'; -import fs from 'fs'; -import path from 'path'; - -describe('analyze-complexity with generateObject', () => { - const testTasksFile = path.join(process.cwd(), 'test-tasks.json'); - const testComplexityFile = path.join(process.cwd(), 'test-complexity.json'); - - beforeEach(() => { - // Create a test tasks file - const testTasks = { - projectName: 'Test Project', - tasks: [ - { - id: 1, - title: 'Setup project structure', - description: 'Initialize the project with proper folder structure', - status: 'pending', - dependencies: [], - priority: 'high' - }, - { - id: 2, - title: 'Implement authentication', - description: 'Add user authentication with JWT tokens', - status: 'pending', - dependencies: [1], - priority: 'high' - } - ] - }; - fs.writeFileSync(testTasksFile, JSON.stringify(testTasks, null, 2)); - }); - - afterEach(() => { - // Clean up test files - if (fs.existsSync(testTasksFile)) { - fs.unlinkSync(testTasksFile); - } - if (fs.existsSync(testComplexityFile)) { - fs.unlinkSync(testComplexityFile); - } - }); - - test('should return structured complexity analysis', async () => { - const result = await analyzeTaskComplexity({ - file: testTasksFile, - output: testComplexityFile, - threshold: 5 - }); - - expect(result).toHaveProperty('report'); - expect(result.report).toHaveProperty('complexityAnalysis'); - expect(Array.isArray(result.report.complexityAnalysis)).toBe(true); - - if (result.report.complexityAnalysis.length > 0) { - const analysis = result.report.complexityAnalysis[0]; - expect(analysis).toHaveProperty('taskId'); - expect(analysis).toHaveProperty('taskTitle'); - expect(analysis).toHaveProperty('complexityScore'); - expect(analysis).toHaveProperty('recommendedSubtasks'); - expect(analysis).toHaveProperty('expansionPrompt'); - expect(analysis).toHaveProperty('reasoning'); - - // Check that the values are of the correct type - expect(typeof analysis.taskId).toBe('number'); - expect(typeof analysis.taskTitle).toBe('string'); - expect(typeof analysis.complexityScore).toBe('number'); - expect(analysis.complexityScore).toBeGreaterThanOrEqual(1); - expect(analysis.complexityScore).toBeLessThanOrEqual(10); - expect(typeof analysis.recommendedSubtasks).toBe('number'); - expect(typeof analysis.expansionPrompt).toBe('string'); - expect(typeof analysis.reasoning).toBe('string'); - } - }, 30000); // Increase timeout for AI call -}); diff --git a/tests/integration/commands/expand-task.test.js b/tests/integration/commands/expand-task.test.js deleted file mode 100644 index ec86f538..00000000 --- a/tests/integration/commands/expand-task.test.js +++ /dev/null @@ -1,148 +0,0 @@ -import expandTask from '../../../scripts/modules/task-manager/expand-task.js'; -import { readJSON, writeJSON } from '../../../scripts/modules/utils.js'; -import fs from 'fs'; -import path from 'path'; - -describe('expand-task with generateObject', () => { - const testTasksFile = path.join(process.cwd(), 'test-tasks.json'); - - beforeEach(() => { - // Create a test tasks file - const testTasks = { - projectName: 'Test Project', - tasks: [ - { - id: 1, - title: 'Setup project structure', - description: 'Initialize the project with proper folder structure', - status: 'done', - dependencies: [], - priority: 'high', - details: 'Create folders for src, tests, docs', - testStrategy: 'Manual verification', - subtasks: [] - }, - { - id: 2, - title: 'Implement authentication', - description: 'Add user authentication with JWT tokens', - status: 'pending', - dependencies: [1], - priority: 'high', - details: 'Need to support OAuth2 and traditional login', - testStrategy: null, - subtasks: [] - }, - { - id: 3, - title: 'Build API endpoints', - description: 'Create RESTful API endpoints', - status: 'pending', - dependencies: [2], - priority: 'medium', - details: null, - testStrategy: null, - subtasks: [ - { - id: 1, - title: 'Design API schema', - description: 'Create OpenAPI specification', - dependencies: [], - details: 'Use OpenAPI 3.0 specification', - status: 'done' - } - ] - } - ] - }; - fs.writeFileSync(testTasksFile, JSON.stringify(testTasks, null, 2)); - }); - - afterEach(() => { - // Clean up test files - if (fs.existsSync(testTasksFile)) { - fs.unlinkSync(testTasksFile); - } - }); - - test('should expand task with structured subtasks', async () => { - const result = await expandTask( - testTasksFile, - '2', // taskId as string - 3, // numSubtasks - false, // force - 'Break down authentication into implementation steps' // additionalContext - ); - - expect(result).toHaveProperty('task'); - expect(result).toHaveProperty('telemetryData'); - - const { task } = result; - - // Verify task was expanded - expect(task.id).toBe(2); - expect(task.subtasks).toBeDefined(); - expect(Array.isArray(task.subtasks)).toBe(true); - expect(task.subtasks.length).toBeGreaterThan(0); - - // Verify subtask structure - const subtask = task.subtasks[0]; - expect(subtask).toHaveProperty('id'); - expect(subtask).toHaveProperty('title'); - expect(subtask).toHaveProperty('description'); - expect(subtask).toHaveProperty('dependencies'); - expect(subtask).toHaveProperty('details'); - expect(subtask).toHaveProperty('status', 'pending'); - - // Verify task was written back to file - const savedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const savedTask = savedData.tasks.find((t) => t.id === 2); - expect(savedTask.subtasks.length).toBe(task.subtasks.length); - }, 30000); // Increase timeout for AI call - - test('should append subtasks when force=false', async () => { - // First expansion - await expandTask(testTasksFile, '3', 2, false); - - const dataAfterFirst = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const taskAfterFirst = dataAfterFirst.tasks.find((t) => t.id === 3); - const initialSubtaskCount = taskAfterFirst.subtasks.length; - - // Second expansion (append) - await expandTask( - testTasksFile, - '3', - 2, - false, - 'Add more implementation details' - ); - - const dataAfterSecond = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const taskAfterSecond = dataAfterSecond.tasks.find((t) => t.id === 3); - - // Should have more subtasks than before - expect(taskAfterSecond.subtasks.length).toBeGreaterThan( - initialSubtaskCount - ); - }, 60000); - - test('should replace subtasks when force=true', async () => { - // First expansion - await expandTask(testTasksFile, '3', 2, false); - - // Second expansion with force=true - const result = await expandTask( - testTasksFile, - '3', - 3, - true, - 'Complete redesign needed' - ); - - const savedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const savedTask = savedData.tasks.find((t) => t.id === 3); - - // Should have exactly 3 subtasks (replaced, not appended) - expect(savedTask.subtasks.length).toBe(3); - }, 60000); -}); diff --git a/tests/integration/commands/update-task-by-id.test.js b/tests/integration/commands/update-task-by-id.test.js deleted file mode 100644 index 0c8a92aa..00000000 --- a/tests/integration/commands/update-task-by-id.test.js +++ /dev/null @@ -1,89 +0,0 @@ -import updateTaskById from '../../../scripts/modules/task-manager/update-task-by-id.js'; -import { readJSON, writeJSON } from '../../../scripts/modules/utils.js'; -import fs from 'fs'; -import path from 'path'; - -describe('update-task-by-id with generateObject', () => { - const testTasksFile = path.join(process.cwd(), 'test-tasks.json'); - - beforeEach(() => { - // Create a test tasks file - const testTasks = { - projectName: 'Test Project', - tasks: [ - { - id: 1, - title: 'Setup project structure', - description: 'Initialize the project with proper folder structure', - status: 'pending', - dependencies: [], - priority: 'high', - details: 'Create folders for src, tests, docs', - testStrategy: 'Manual verification' - }, - { - id: 2, - title: 'Implement authentication', - description: 'Add user authentication with JWT tokens', - status: 'pending', - dependencies: [1], - priority: 'high', - details: null, - testStrategy: null - } - ] - }; - fs.writeFileSync(testTasksFile, JSON.stringify(testTasks, null, 2)); - }); - - afterEach(() => { - // Clean up test files - if (fs.existsSync(testTasksFile)) { - fs.unlinkSync(testTasksFile); - } - }); - - test('should update task with structured data', async () => { - const result = await updateTaskById({ - file: testTasksFile, - prompt: 'Update the description to include OAuth2 support', - id: 2 - }); - - expect(result).toHaveProperty('updatedTask'); - const { updatedTask } = result; - - // Verify the task structure - expect(updatedTask).toHaveProperty('id', 2); - expect(updatedTask).toHaveProperty('title'); - expect(updatedTask).toHaveProperty('description'); - expect(updatedTask).toHaveProperty('status'); - expect(updatedTask).toHaveProperty('dependencies'); - expect(updatedTask).toHaveProperty('priority'); - - // Check that description was updated - expect(updatedTask.description.toLowerCase()).toContain('oauth'); - - // Verify task was written back to file - const savedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const savedTask = savedData.tasks.find((t) => t.id === 2); - expect(savedTask.description).toBe(updatedTask.description); - }, 30000); // Increase timeout for AI call - - test('should handle append mode with plain text', async () => { - const result = await updateTaskById({ - file: testTasksFile, - prompt: 'Add information about refresh tokens', - id: 2, - append: true - }); - - expect(result).toHaveProperty('updatedTask'); - const { updatedTask } = result; - - // Check that details were appended - expect(updatedTask.details).toBeTruthy(); - expect(updatedTask.details).toContain(' { - const testTasksFile = path.join(process.cwd(), 'test-tasks.json'); - - beforeEach(() => { - // Create a test tasks file - const testTasks = { - projectName: 'Test Project', - tasks: [ - { - id: 1, - title: 'Setup project structure', - description: 'Initialize the project with proper folder structure', - status: 'done', - dependencies: [], - priority: 'high', - details: 'Create folders for src, tests, docs', - testStrategy: 'Manual verification', - subtasks: [] - }, - { - id: 2, - title: 'Implement authentication', - description: 'Add user authentication with JWT tokens', - status: 'pending', - dependencies: [1], - priority: 'high', - details: 'Need to support OAuth2 and traditional login', - testStrategy: null, - subtasks: [ - { - id: 1, - title: 'Design auth flow', - description: 'Create authentication flow diagrams', - status: 'done', - dependencies: [] - } - ] - }, - { - id: 3, - title: 'Build API endpoints', - description: 'Create RESTful API endpoints', - status: 'in-progress', - dependencies: [2], - priority: 'medium', - details: 'Use Express.js for the API', - testStrategy: 'Integration tests with Jest', - subtasks: [] - }, - { - id: 4, - title: 'Add database layer', - description: 'Implement database models and migrations', - status: 'pending', - dependencies: [1], - priority: 'high', - details: null, - testStrategy: null, - subtasks: [] - } - ] - }; - fs.writeFileSync(testTasksFile, JSON.stringify(testTasks, null, 2)); - }); - - afterEach(() => { - // Clean up test files - if (fs.existsSync(testTasksFile)) { - fs.unlinkSync(testTasksFile); - } - }); - - test('should update multiple tasks with structured data', async () => { - const result = await updateTasks( - testTasksFile, - 2, // Update from task ID 2 onwards - 'Switch to microservices architecture with Docker containers' - ); - - expect(result).toBeDefined(); - expect(result).toHaveProperty('updatedTasks'); - expect(result).toHaveProperty('telemetryData'); - - // Read the updated file - const updatedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - - // Task 1 should remain unchanged (status: done) - const task1 = updatedData.tasks.find((t) => t.id === 1); - expect(task1.title).toBe('Setup project structure'); - expect(task1.status).toBe('done'); - - // Tasks 2, 3, and 4 should be updated - const task2 = updatedData.tasks.find((t) => t.id === 2); - expect(task2.description.toLowerCase()).toContain('microservice'); - // Completed subtasks should be preserved - expect( - task2.subtasks.find((st) => st.id === 1 && st.status === 'done') - ).toBeDefined(); - - const task3 = updatedData.tasks.find((t) => t.id === 3); - expect(task3.description.toLowerCase()).toContain('docker'); - - const task4 = updatedData.tasks.find((t) => t.id === 4); - expect(task4.description.toLowerCase()).toMatch( - /microservice|docker|container/ - ); - }, 30000); // Increase timeout for AI call - - test('should preserve completed subtasks when updating', async () => { - await updateTasks( - testTasksFile, - 2, - 'Add comprehensive error handling and logging' - ); - - const updatedData = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - const task2 = updatedData.tasks.find((t) => t.id === 2); - - // Find the completed subtask - const completedSubtask = task2.subtasks.find((st) => st.id === 1); - expect(completedSubtask).toBeDefined(); - expect(completedSubtask.status).toBe('done'); - expect(completedSubtask.title).toBe('Design auth flow'); - expect(completedSubtask.description).toBe( - 'Create authentication flow diagrams' - ); - }, 30000); - - test('should handle no tasks to update', async () => { - const result = await updateTasks( - testTasksFile, - 10, // Start from non-existent task ID - 'Update all tasks' - ); - - expect(result).toBeUndefined(); - - // File should remain unchanged - const data = JSON.parse(fs.readFileSync(testTasksFile, 'utf8')); - expect(data.tasks.length).toBe(4); - }, 30000); -}); diff --git a/tests/integration/migration-verification.test.js b/tests/integration/migration-verification.test.js deleted file mode 100644 index 16e95c2a..00000000 --- a/tests/integration/migration-verification.test.js +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Tests to verify the generateObject migration is complete - * Ensures no legacy parsing functions remain and all commands use generateObject - */ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -describe('GenerateObject Migration Verification', () => { - const scriptsDir = path.join(__dirname, '../../scripts/modules/task-manager'); - - describe('Legacy Parsing Function Removal', () => { - test('should not find parseUpdatedTasksFromText function', () => { - const updateTasksFile = fs.readFileSync( - path.join(scriptsDir, 'update-tasks.js'), - 'utf8' - ); - - // The function should still exist but only for reference - // It's not being used anywhere in the actual command flow - const hasParsingFunction = updateTasksFile.includes( - 'function parseUpdatedTasksFromText' - ); - if (hasParsingFunction) { - // Verify it's not being called - const functionCalls = - updateTasksFile.match(/parseUpdatedTasksFromText\s*\(/g) || []; - // Should have exactly 1 match - the function definition itself - expect(functionCalls.length).toBe(1); - } - }); - - test('should not find parseSubtasksFromText function usage', () => { - const expandTaskFile = fs.readFileSync( - path.join(scriptsDir, 'expand-task.js'), - 'utf8' - ); - - // Should not contain the parsing function at all - expect(expandTaskFile).not.toContain('parseSubtasksFromText'); - }); - - test('should not find parseComplexityAnalysisFromText function usage', () => { - const analyzeComplexityFile = fs.readFileSync( - path.join(scriptsDir, 'analyze-task-complexity.js'), - 'utf8' - ); - - // Should not contain the parsing function at all - expect(analyzeComplexityFile).not.toContain( - 'parseComplexityAnalysisFromText' - ); - }); - }); - - describe('GenerateObject Service Usage', () => { - const commandFiles = [ - 'analyze-task-complexity.js', - 'update-task-by-id.js', - 'expand-task.js', - 'update-tasks.js', - 'add-task.js', - 'parse-prd.js' - ]; - - commandFiles.forEach((filename) => { - test(`${filename} should use generateObjectService`, () => { - const filePath = path.join(scriptsDir, filename); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - // Should import generateObjectService - expect(fileContent).toMatch( - /import\s+.*generateObjectService.*from\s+['"]\.\.\/ai-services-unified\.js['"]/ - ); - - // Should call generateObjectService - expect(fileContent).toContain('generateObjectService('); - - // Should use schema - expect(fileContent).toMatch( - /schema:\s*\w+Schema|schema:\s*COMMAND_SCHEMAS/ - ); - }); - }); - - test('update-subtask-by-id.js should continue using generateTextService', () => { - const filePath = path.join(scriptsDir, 'update-subtask-by-id.js'); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - // Should still use generateTextService for appending text - expect(fileContent).toContain('generateTextService'); - expect(fileContent).not.toContain('generateObjectService'); - }); - }); - - describe('Schema Registry Usage', () => { - test('should have a complete schema registry', () => { - const registryPath = path.join( - __dirname, - '../../src/schemas/registry.js' - ); - const registryContent = fs.readFileSync(registryPath, 'utf8'); - - // Should export COMMAND_SCHEMAS - expect(registryContent).toContain('export const COMMAND_SCHEMAS'); - - // Should include all command schemas - const expectedCommands = [ - 'update-tasks', - 'expand-task', - 'analyze-complexity', - 'update-task-by-id' - ]; - - expectedCommands.forEach((command) => { - expect(registryContent).toContain(`'${command}':`); - }); - }); - - test('update-tasks.js should use schema from registry', () => { - const filePath = path.join(scriptsDir, 'update-tasks.js'); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - // Should import from registry - expect(fileContent).toContain( - "import { COMMAND_SCHEMAS } from '../../../src/schemas/registry.js'" - ); - - // Should use registry in generateObjectService call - expect(fileContent).toContain("COMMAND_SCHEMAS['update-tasks']"); - }); - }); - - describe('Prompt Template Updates', () => { - const promptsDir = path.join(__dirname, '../../src/prompts'); - - test('prompts should not contain JSON formatting instructions', () => { - const promptFiles = fs - .readdirSync(promptsDir) - .filter((f) => f.endsWith('.json')); - - const jsonInstructions = [ - 'Return only the updated tasks as a valid JSON array', - 'Do not include any explanatory text, markdown formatting, or code block markers', - 'Respond ONLY with a valid JSON', - 'The response must be a valid JSON', - 'Return the result as JSON' - ]; - - promptFiles.forEach((filename) => { - // Skip update-subtask.json as it returns plain text - if (filename === 'update-subtask.json') return; - - const filePath = path.join(promptsDir, filename); - const content = fs.readFileSync(filePath, 'utf8'); - - jsonInstructions.forEach((instruction) => { - expect(content).not.toContain(instruction); - }); - }); - }); - }); - - describe('Direct Object Access Patterns', () => { - test('commands should access data directly from mainResult', () => { - const patterns = [ - { - file: 'analyze-task-complexity.js', - pattern: /aiServiceResponse\.mainResult\.complexityAnalysis/ - }, - { - file: 'expand-task.js', - pattern: /aiServiceResponse\.mainResult\.subtasks/ - }, - { - file: 'update-tasks.js', - pattern: /aiServiceResponse\.mainResult\.tasks/ - }, - { - file: 'update-task-by-id.js', - pattern: /aiServiceResponse\.mainResult\.task/ - } - ]; - - patterns.forEach(({ file, pattern }) => { - const filePath = path.join(scriptsDir, file); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - expect(fileContent).toMatch(pattern); - }); - }); - }); - - describe('Error Handling Updates', () => { - test('commands should not have AI response JSON parsing error handling', () => { - const commandFiles = [ - 'analyze-task-complexity.js', - 'expand-task.js', - 'update-task-by-id.js' - ]; - - // More specific patterns that indicate AI response parsing - const aiParsingErrorPatterns = [ - 'Failed to parse JSON response', - 'Failed to parse AI response', - 'parseComplexityAnalysisFromText', - 'parseSubtasksFromText', - 'parseUpdatedTaskFromText', - 'parseUpdatedTasksFromText', - 'Malformed JSON', - 'extracting between \\[\\]', - 'JSON code block' - ]; - - commandFiles.forEach((filename) => { - const filePath = path.join(scriptsDir, filename); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - // Check for AI response parsing patterns - aiParsingErrorPatterns.forEach((pattern) => { - expect(fileContent).not.toMatch(new RegExp(pattern, 'i')); - }); - }); - }); - }); -});