diff --git a/scripts/modules/utils.js b/scripts/modules/utils.js index ee14cc9d..540b228e 100644 --- a/scripts/modules/utils.js +++ b/scripts/modules/utils.js @@ -3,9 +3,9 @@ * Utility functions for the Task Master CLI */ +import chalk from 'chalk'; import fs from 'fs'; import path from 'path'; -import chalk from 'chalk'; // Global silent mode flag let silentMode = false; @@ -247,6 +247,8 @@ function findTaskById(tasks, taskId) { return null; } + let taskResult = null; + // Check if it's a subtask ID (e.g., "1.2") if (typeof taskId === 'string' && taskId.includes('.')) { const [parentId, subtaskId] = taskId @@ -267,13 +269,33 @@ function findTaskById(tasks, taskId) { status: parentTask.status }; subtask.isSubtask = true; + taskResult = subtask; } - - return subtask || null; + } else { + const id = parseInt(taskId, 10); + taskResult = tasks.find((t) => t.id === id) || null; } - const id = parseInt(taskId, 10); - return tasks.find((t) => t.id === id) || null; + // If we found a task, check for complexity data + if (taskResult) { + // Try to read complexity report + const complexityReport = readComplexityReport(); + + if (complexityReport && complexityReport.complexityAnalysis) { + // For a main task, look for a direct match + if (!taskResult.isSubtask) { + const taskAnalysis = complexityReport.complexityAnalysis.find( + analysis => analysis.taskId === taskResult.id + ); + + if (taskAnalysis) { + taskResult.complexityScore = taskAnalysis.complexityScore; + } + } + } + } + + return taskResult; } /** @@ -399,23 +421,6 @@ function detectCamelCaseFlags(args) { // Export all utility functions and configuration export { - CONFIG, - LOG_LEVELS, - log, - readJSON, - writeJSON, - sanitizePrompt, - readComplexityReport, - findTaskInComplexityReport, - taskExists, - formatTaskId, - findTaskById, - truncate, - findCycles, - toKebabCase, - detectCamelCaseFlags, - enableSilentMode, - disableSilentMode, - isSilentMode, - getTaskManager + CONFIG, detectCamelCaseFlags, disableSilentMode, enableSilentMode, findCycles, findTaskById, findTaskInComplexityReport, formatTaskId, getTaskManager, isSilentMode, log, LOG_LEVELS, readComplexityReport, readJSON, sanitizePrompt, taskExists, toKebabCase, truncate, writeJSON }; + diff --git a/tests/unit/task-finder.test.js b/tests/unit/task-finder.test.js index 8edf9aaf..fb177ffc 100644 --- a/tests/unit/task-finder.test.js +++ b/tests/unit/task-finder.test.js @@ -2,8 +2,26 @@ * Task finder tests */ +import { jest } from '@jest/globals'; + +// Set up mock before imports +const mockReadComplexityReport = jest.fn().mockReturnValue(null); + +// Mock utils module to control readComplexityReport behavior +jest.mock('../../scripts/modules/utils.js', () => { + // Get the original module + const originalModule = jest.requireActual('../../scripts/modules/utils.js'); + + // Return a modified version + return { + ...originalModule, + readComplexityReport: mockReadComplexityReport + }; +}); + +// Import after mocks are set up import { findTaskById } from '../../scripts/modules/utils.js'; -import { sampleTasks, emptySampleTasks } from '../fixtures/sample-tasks.js'; +import { emptySampleTasks, sampleTasks } from '../fixtures/sample-tasks.js'; describe('Task Finder', () => { describe('findTaskById function', () => { @@ -46,5 +64,67 @@ describe('Task Finder', () => { const task = findTaskById(emptySampleTasks.tasks, 1); expect(task).toBeNull(); }); + + test('should include complexity score when report exists', () => { + // call readComplexityReport + // Set up mock implementation for this test + mockReadComplexityReport.mockReturnValue({ + meta: { + generatedAt: '2023-01-01T00:00:00.000Z', + tasksAnalyzed: 3, + thresholdScore: 5 + }, + complexityAnalysis: [ + { + taskId: 1, + taskTitle: 'Initialize Project', + complexityScore: 3, + recommendedSubtasks: 2 + }, + { + taskId: 2, + taskTitle: 'Create Core Functionality', + complexityScore: 8, + recommendedSubtasks: 5 + }, + { + taskId: 3, + taskTitle: 'Implement UI Components', + complexityScore: 6, + recommendedSubtasks: 4 + } + ] + }); + + const task = findTaskById(sampleTasks.tasks, 2); + + expect(task).toBeDefined(); + expect(task.id).toBe(2); + expect(task.complexityScore).toBe(8); + }); + + test('should work correctly when task has no complexity data', () => { + // Set up mock implementation for this test + mockReadComplexityReport.mockReturnValue({ + complexityAnalysis: [{ taskId: 999, complexityScore: 5 }] + }); + + const task = findTaskById(sampleTasks.tasks, 2); + + expect(task).toBeDefined(); + expect(task.id).toBe(2); + expect(task.complexityScore).toBeUndefined(); + }); + + test('should work correctly when no complexity report exists', () => { + // Set up mock implementation for this test + mockReadComplexityReport.mockReturnValue(null); + + const task = findTaskById(sampleTasks.tasks, 2); + + expect(task).toBeDefined(); + expect(task.id).toBe(2); + expect(task.complexityScore).toBeUndefined(); + }); }); });