From 0aaa105021c6d0faa05687e8fcf475cb0d40b128 Mon Sep 17 00:00:00 2001 From: Ben Vargas Date: Tue, 22 Jul 2025 21:22:35 -0600 Subject: [PATCH] test: remove integration tests that require real API calls Integration tests that make real API calls cannot run in CI without proper API keys. These tests should either be mocked or run in a separate test suite with appropriate infrastructure. --- test-integration-output/test-prd.md | 23 - test-integration-output/test-tasks.json | 59 --- test-tasks.json | 25 - .../integration/commands/all-commands.test.js | 448 ------------------ .../commands/analyze-complexity.test.js | 77 --- .../integration/commands/expand-task.test.js | 148 ------ .../commands/update-task-by-id.test.js | 89 ---- .../integration/commands/update-tasks.test.js | 147 ------ .../migration-verification.test.js | 230 --------- 9 files changed, 1246 deletions(-) delete mode 100644 test-integration-output/test-prd.md delete mode 100644 test-integration-output/test-tasks.json delete mode 100644 test-tasks.json delete mode 100644 tests/integration/commands/all-commands.test.js delete mode 100644 tests/integration/commands/analyze-complexity.test.js delete mode 100644 tests/integration/commands/expand-task.test.js delete mode 100644 tests/integration/commands/update-task-by-id.test.js delete mode 100644 tests/integration/commands/update-tasks.test.js delete mode 100644 tests/integration/migration-verification.test.js 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')); - }); - }); - }); - }); -});