diff --git a/tests/unit/scripts/modules/task-manager/add-task.test.js b/tests/unit/scripts/modules/task-manager/add-task.test.js index 9a31cf10..26ec02ef 100644 --- a/tests/unit/scripts/modules/task-manager/add-task.test.js +++ b/tests/unit/scripts/modules/task-manager/add-task.test.js @@ -1,404 +1,404 @@ /** * Tests for the add-task.js module */ -import { jest } from "@jest/globals"; +import { jest } from '@jest/globals'; // Mock the dependencies before importing the module under test -jest.unstable_mockModule("../../../../../scripts/modules/utils.js", () => ({ - readJSON: jest.fn(), - writeJSON: jest.fn(), - log: jest.fn(), - CONFIG: { - model: "mock-claude-model", - maxTokens: 4000, - temperature: 0.7, - debug: false, - }, - truncate: jest.fn((text) => text), +jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ + readJSON: jest.fn(), + writeJSON: jest.fn(), + log: jest.fn(), + CONFIG: { + model: 'mock-claude-model', + maxTokens: 4000, + temperature: 0.7, + debug: false + }, + truncate: jest.fn((text) => text) })); -jest.unstable_mockModule("../../../../../scripts/modules/ui.js", () => ({ - displayBanner: jest.fn(), - getStatusWithColor: jest.fn((status) => status), - startLoadingIndicator: jest.fn(), - stopLoadingIndicator: jest.fn(), - succeedLoadingIndicator: jest.fn(), - failLoadingIndicator: jest.fn(), - warnLoadingIndicator: jest.fn(), - infoLoadingIndicator: jest.fn(), - displayAiUsageSummary: jest.fn(), +jest.unstable_mockModule('../../../../../scripts/modules/ui.js', () => ({ + displayBanner: jest.fn(), + getStatusWithColor: jest.fn((status) => status), + startLoadingIndicator: jest.fn(), + stopLoadingIndicator: jest.fn(), + succeedLoadingIndicator: jest.fn(), + failLoadingIndicator: jest.fn(), + warnLoadingIndicator: jest.fn(), + infoLoadingIndicator: jest.fn(), + displayAiUsageSummary: jest.fn() })); jest.unstable_mockModule( - "../../../../../scripts/modules/ai-services-unified.js", - () => ({ - generateObjectService: jest.fn().mockResolvedValue({ - mainResult: { - object: { - title: "Task from prompt: Create a new authentication system", - description: - "Task generated from: Create a new authentication system", - details: - "Implementation details for task generated from prompt: Create a new authentication system", - testStrategy: "Write unit tests to verify functionality", - dependencies: [], - }, - }, - telemetryData: { - timestamp: new Date().toISOString(), - userId: "1234567890", - commandName: "add-task", - modelUsed: "claude-3-5-sonnet", - providerName: "anthropic", - inputTokens: 1000, - outputTokens: 500, - totalTokens: 1500, - totalCost: 0.012414, - currency: "USD", - }, - }), - }) + '../../../../../scripts/modules/ai-services-unified.js', + () => ({ + generateObjectService: jest.fn().mockResolvedValue({ + mainResult: { + object: { + title: 'Task from prompt: Create a new authentication system', + description: + 'Task generated from: Create a new authentication system', + details: + 'Implementation details for task generated from prompt: Create a new authentication system', + testStrategy: 'Write unit tests to verify functionality', + dependencies: [] + } + }, + telemetryData: { + timestamp: new Date().toISOString(), + userId: '1234567890', + commandName: 'add-task', + modelUsed: 'claude-3-5-sonnet', + providerName: 'anthropic', + inputTokens: 1000, + outputTokens: 500, + totalTokens: 1500, + totalCost: 0.012414, + currency: 'USD' + } + }) + }) ); jest.unstable_mockModule( - "../../../../../scripts/modules/config-manager.js", - () => ({ - getDefaultPriority: jest.fn(() => "medium"), - }) + '../../../../../scripts/modules/config-manager.js', + () => ({ + getDefaultPriority: jest.fn(() => 'medium') + }) ); jest.unstable_mockModule( - "../../../../../scripts/modules/task-manager/generate-task-files.js", - () => ({ - default: jest.fn().mockResolvedValue(), - }) + '../../../../../scripts/modules/task-manager/generate-task-files.js', + () => ({ + default: jest.fn().mockResolvedValue() + }) ); // Mock external UI libraries -jest.unstable_mockModule("chalk", () => ({ - default: { - white: { bold: jest.fn((text) => text) }, - cyan: Object.assign( - jest.fn((text) => text), - { - bold: jest.fn((text) => text), - } - ), - green: jest.fn((text) => text), - yellow: jest.fn((text) => text), - bold: jest.fn((text) => text), - }, +jest.unstable_mockModule('chalk', () => ({ + default: { + white: { bold: jest.fn((text) => text) }, + cyan: Object.assign( + jest.fn((text) => text), + { + bold: jest.fn((text) => text) + } + ), + green: jest.fn((text) => text), + yellow: jest.fn((text) => text), + bold: jest.fn((text) => text) + } })); -jest.unstable_mockModule("boxen", () => ({ - default: jest.fn((text) => text), +jest.unstable_mockModule('boxen', () => ({ + default: jest.fn((text) => text) })); -jest.unstable_mockModule("cli-table3", () => ({ - default: jest.fn().mockImplementation(() => ({ - push: jest.fn(), - toString: jest.fn(() => "mocked table"), - })), +jest.unstable_mockModule('cli-table3', () => ({ + default: jest.fn().mockImplementation(() => ({ + push: jest.fn(), + toString: jest.fn(() => 'mocked table') + })) })); // Import the mocked modules const { readJSON, writeJSON, log } = await import( - "../../../../../scripts/modules/utils.js" + '../../../../../scripts/modules/utils.js' ); const { generateObjectService } = await import( - "../../../../../scripts/modules/ai-services-unified.js" + '../../../../../scripts/modules/ai-services-unified.js' ); const generateTaskFiles = await import( - "../../../../../scripts/modules/task-manager/generate-task-files.js" + '../../../../../scripts/modules/task-manager/generate-task-files.js' ); // Import the module under test const { default: addTask } = await import( - "../../../../../scripts/modules/task-manager/add-task.js" + '../../../../../scripts/modules/task-manager/add-task.js' ); -describe("addTask", () => { - const sampleTasks = { - tasks: [ - { - id: 1, - title: "Task 1", - description: "First task", - status: "pending", - dependencies: [], - }, - { - id: 2, - title: "Task 2", - description: "Second task", - status: "pending", - dependencies: [], - }, - { - id: 3, - title: "Task 3", - description: "Third task", - status: "pending", - dependencies: [1], - }, - ], - }; +describe('addTask', () => { + const sampleTasks = { + tasks: [ + { + id: 1, + title: 'Task 1', + description: 'First task', + status: 'pending', + dependencies: [] + }, + { + id: 2, + title: 'Task 2', + description: 'Second task', + status: 'pending', + dependencies: [] + }, + { + id: 3, + title: 'Task 3', + description: 'Third task', + status: 'pending', + dependencies: [1] + } + ] + }; - // Create a helper function for consistent mcpLog mock - const createMcpLogMock = () => ({ - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - debug: jest.fn(), - success: jest.fn(), - }); + // Create a helper function for consistent mcpLog mock + const createMcpLogMock = () => ({ + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + debug: jest.fn(), + success: jest.fn() + }); - beforeEach(() => { - jest.clearAllMocks(); - readJSON.mockReturnValue(JSON.parse(JSON.stringify(sampleTasks))); + beforeEach(() => { + jest.clearAllMocks(); + readJSON.mockReturnValue(JSON.parse(JSON.stringify(sampleTasks))); - // Mock console.log to avoid output during tests - jest.spyOn(console, "log").mockImplementation(() => {}); - }); + // Mock console.log to avoid output during tests + jest.spyOn(console, 'log').mockImplementation(() => {}); + }); - afterEach(() => { - console.log.mockRestore(); - }); + afterEach(() => { + console.log.mockRestore(); + }); - test("should add a new task using AI", async () => { - // Arrange - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should add a new task using AI', async () => { + // Arrange + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act - const result = await addTask( - "tasks/tasks.json", - prompt, - [], - "medium", - context, - "json" - ); + // Act + const result = await addTask( + 'tasks/tasks.json', + prompt, + [], + 'medium', + context, + 'json' + ); - // Assert - expect(readJSON).toHaveBeenCalledWith("tasks/tasks.json"); - expect(generateObjectService).toHaveBeenCalledWith(expect.any(Object)); - expect(writeJSON).toHaveBeenCalledWith( - "tasks/tasks.json", - expect.objectContaining({ - tasks: expect.arrayContaining([ - expect.objectContaining({ - id: 4, // Next ID after existing tasks - title: expect.stringContaining( - "Create a new authentication system" - ), - status: "pending", - }), - ]), - }) - ); - expect(generateTaskFiles.default).toHaveBeenCalled(); - expect(result).toEqual( - expect.objectContaining({ - newTaskId: 4, - telemetryData: expect.any(Object), - }) - ); - }); + // Assert + expect(readJSON).toHaveBeenCalledWith('tasks/tasks.json'); + expect(generateObjectService).toHaveBeenCalledWith(expect.any(Object)); + expect(writeJSON).toHaveBeenCalledWith( + 'tasks/tasks.json', + expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ + id: 4, // Next ID after existing tasks + title: expect.stringContaining( + 'Create a new authentication system' + ), + status: 'pending' + }) + ]) + }) + ); + expect(generateTaskFiles.default).toHaveBeenCalled(); + expect(result).toEqual( + expect.objectContaining({ + newTaskId: 4, + telemetryData: expect.any(Object) + }) + ); + }); - test("should validate dependencies when adding a task", async () => { - // Arrange - const prompt = "Create a new authentication system"; - const validDependencies = [1, 2]; // These exist in sampleTasks - const context = { - mcpLog: createMcpLogMock(), - }; + test('should validate dependencies when adding a task', async () => { + // Arrange + const prompt = 'Create a new authentication system'; + const validDependencies = [1, 2]; // These exist in sampleTasks + const context = { + mcpLog: createMcpLogMock() + }; - // Act - const result = await addTask( - "tasks/tasks.json", - prompt, - validDependencies, - "medium", - context, - "json" - ); + // Act + const result = await addTask( + 'tasks/tasks.json', + prompt, + validDependencies, + 'medium', + context, + 'json' + ); - // Assert - expect(writeJSON).toHaveBeenCalledWith( - "tasks/tasks.json", - expect.objectContaining({ - tasks: expect.arrayContaining([ - expect.objectContaining({ - id: 4, - dependencies: validDependencies, - }), - ]), - }) - ); - }); + // Assert + expect(writeJSON).toHaveBeenCalledWith( + 'tasks/tasks.json', + expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ + id: 4, + dependencies: validDependencies + }) + ]) + }) + ); + }); - test("should filter out invalid dependencies", async () => { - // Arrange - const prompt = "Create a new authentication system"; - const invalidDependencies = [999]; // Non-existent task ID - const context = { mcpLog: createMcpLogMock() }; + test('should filter out invalid dependencies', async () => { + // Arrange + const prompt = 'Create a new authentication system'; + const invalidDependencies = [999]; // Non-existent task ID + const context = { mcpLog: createMcpLogMock() }; - // Act - const result = await addTask( - "tasks/tasks.json", - prompt, - invalidDependencies, - "medium", - context, - "json" - ); + // Act + const result = await addTask( + 'tasks/tasks.json', + prompt, + invalidDependencies, + 'medium', + context, + 'json' + ); - // Assert - expect(writeJSON).toHaveBeenCalledWith( - "tasks/tasks.json", - expect.objectContaining({ - tasks: expect.arrayContaining([ - expect.objectContaining({ - id: 4, - dependencies: [], // Invalid dependencies should be filtered out - }), - ]), - }) - ); - expect(context.mcpLog.warn).toHaveBeenCalledWith( - expect.stringContaining( - "The following dependencies do not exist or are invalid: 999" - ) - ); - }); + // Assert + expect(writeJSON).toHaveBeenCalledWith( + 'tasks/tasks.json', + expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ + id: 4, + dependencies: [] // Invalid dependencies should be filtered out + }) + ]) + }) + ); + expect(context.mcpLog.warn).toHaveBeenCalledWith( + expect.stringContaining( + 'The following dependencies do not exist or are invalid: 999' + ) + ); + }); - test("should use specified priority", async () => { - // Arrange - const prompt = "Create a new authentication system"; - const priority = "high"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should use specified priority', async () => { + // Arrange + const prompt = 'Create a new authentication system'; + const priority = 'high'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act - await addTask("tasks/tasks.json", prompt, [], priority, context, "json"); + // Act + await addTask('tasks/tasks.json', prompt, [], priority, context, 'json'); - // Assert - expect(writeJSON).toHaveBeenCalledWith( - "tasks/tasks.json", - expect.objectContaining({ - tasks: expect.arrayContaining([ - expect.objectContaining({ - priority: priority, - }), - ]), - }) - ); - }); + // Assert + expect(writeJSON).toHaveBeenCalledWith( + 'tasks/tasks.json', + expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ + priority: priority + }) + ]) + }) + ); + }); - test("should handle empty tasks file", async () => { - // Arrange - readJSON.mockReturnValue({ tasks: [] }); - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should handle empty tasks file', async () => { + // Arrange + readJSON.mockReturnValue({ tasks: [] }); + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act - const result = await addTask( - "tasks/tasks.json", - prompt, - [], - "medium", - context, - "json" - ); + // Act + const result = await addTask( + 'tasks/tasks.json', + prompt, + [], + 'medium', + context, + 'json' + ); - // Assert - expect(result.newTaskId).toBe(1); // First task should have ID 1 - expect(writeJSON).toHaveBeenCalledWith( - "tasks/tasks.json", - expect.objectContaining({ - tasks: expect.arrayContaining([ - expect.objectContaining({ - id: 1, - }), - ]), - }) - ); - }); + // Assert + expect(result.newTaskId).toBe(1); // First task should have ID 1 + expect(writeJSON).toHaveBeenCalledWith( + 'tasks/tasks.json', + expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ + id: 1 + }) + ]) + }) + ); + }); - test("should handle missing tasks file", async () => { - // Arrange - readJSON.mockReturnValue(null); - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should handle missing tasks file', async () => { + // Arrange + readJSON.mockReturnValue(null); + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act - const result = await addTask( - "tasks/tasks.json", - prompt, - [], - "medium", - context, - "json" - ); + // Act + const result = await addTask( + 'tasks/tasks.json', + prompt, + [], + 'medium', + context, + 'json' + ); - // Assert - expect(result.newTaskId).toBe(1); // First task should have ID 1 - expect(writeJSON).toHaveBeenCalledTimes(2); // Once to create file, once to add task - }); + // Assert + expect(result.newTaskId).toBe(1); // First task should have ID 1 + expect(writeJSON).toHaveBeenCalledTimes(2); // Once to create file, once to add task + }); - test("should handle AI service errors", async () => { - // Arrange - generateObjectService.mockRejectedValueOnce(new Error("AI service failed")); - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should handle AI service errors', async () => { + // Arrange + generateObjectService.mockRejectedValueOnce(new Error('AI service failed')); + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act & Assert - await expect( - addTask("tasks/tasks.json", prompt, [], "medium", context, "json") - ).rejects.toThrow("AI service failed"); - }); + // Act & Assert + await expect( + addTask('tasks/tasks.json', prompt, [], 'medium', context, 'json') + ).rejects.toThrow('AI service failed'); + }); - test("should handle file read errors", async () => { - // Arrange - readJSON.mockImplementation(() => { - throw new Error("File read failed"); - }); - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should handle file read errors', async () => { + // Arrange + readJSON.mockImplementation(() => { + throw new Error('File read failed'); + }); + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act & Assert - await expect( - addTask("tasks/tasks.json", prompt, [], "medium", context, "json") - ).rejects.toThrow("File read failed"); - }); + // Act & Assert + await expect( + addTask('tasks/tasks.json', prompt, [], 'medium', context, 'json') + ).rejects.toThrow('File read failed'); + }); - test("should handle file write errors", async () => { - // Arrange - writeJSON.mockImplementation(() => { - throw new Error("File write failed"); - }); - const prompt = "Create a new authentication system"; - const context = { - mcpLog: createMcpLogMock(), - }; + test('should handle file write errors', async () => { + // Arrange + writeJSON.mockImplementation(() => { + throw new Error('File write failed'); + }); + const prompt = 'Create a new authentication system'; + const context = { + mcpLog: createMcpLogMock() + }; - // Act & Assert - await expect( - addTask("tasks/tasks.json", prompt, [], "medium", context, "json") - ).rejects.toThrow("File write failed"); - }); + // Act & Assert + await expect( + addTask('tasks/tasks.json', prompt, [], 'medium', context, 'json') + ).rejects.toThrow('File write failed'); + }); }); diff --git a/tests/unit/ui.test.js b/tests/unit/ui.test.js index 02b869f0..fff21af6 100644 --- a/tests/unit/ui.test.js +++ b/tests/unit/ui.test.js @@ -2,245 +2,245 @@ * UI module tests */ -import { jest } from "@jest/globals"; +import { jest } from '@jest/globals'; import { - getStatusWithColor, - formatDependenciesWithStatus, - createProgressBar, - getComplexityWithColor, -} from "../../scripts/modules/ui.js"; -import { sampleTasks } from "../fixtures/sample-tasks.js"; + getStatusWithColor, + formatDependenciesWithStatus, + createProgressBar, + getComplexityWithColor +} from '../../scripts/modules/ui.js'; +import { sampleTasks } from '../fixtures/sample-tasks.js'; // Mock dependencies -jest.mock("chalk", () => { - const origChalkFn = (text) => text; - const chalk = origChalkFn; - chalk.green = (text) => text; // Return text as-is for status functions - chalk.yellow = (text) => text; - chalk.red = (text) => text; - chalk.cyan = (text) => text; - chalk.blue = (text) => text; - chalk.gray = (text) => text; - chalk.white = (text) => text; - chalk.bold = (text) => text; - chalk.dim = (text) => text; +jest.mock('chalk', () => { + const origChalkFn = (text) => text; + const chalk = origChalkFn; + chalk.green = (text) => text; // Return text as-is for status functions + chalk.yellow = (text) => text; + chalk.red = (text) => text; + chalk.cyan = (text) => text; + chalk.blue = (text) => text; + chalk.gray = (text) => text; + chalk.white = (text) => text; + chalk.bold = (text) => text; + chalk.dim = (text) => text; - // Add hex and other methods - chalk.hex = () => origChalkFn; - chalk.rgb = () => origChalkFn; + // Add hex and other methods + chalk.hex = () => origChalkFn; + chalk.rgb = () => origChalkFn; - return chalk; + return chalk; }); -jest.mock("figlet", () => ({ - textSync: jest.fn(() => "Task Master Banner"), +jest.mock('figlet', () => ({ + textSync: jest.fn(() => 'Task Master Banner') })); -jest.mock("boxen", () => jest.fn((text) => `[boxed: ${text}]`)); +jest.mock('boxen', () => jest.fn((text) => `[boxed: ${text}]`)); -jest.mock("ora", () => - jest.fn(() => ({ - start: jest.fn(), - succeed: jest.fn(), - fail: jest.fn(), - stop: jest.fn(), - })) +jest.mock('ora', () => + jest.fn(() => ({ + start: jest.fn(), + succeed: jest.fn(), + fail: jest.fn(), + stop: jest.fn() + })) ); -jest.mock("cli-table3", () => - jest.fn().mockImplementation(() => ({ - push: jest.fn(), - toString: jest.fn(() => "Table Content"), - })) +jest.mock('cli-table3', () => + jest.fn().mockImplementation(() => ({ + push: jest.fn(), + toString: jest.fn(() => 'Table Content') + })) ); -jest.mock("gradient-string", () => jest.fn(() => jest.fn((text) => text))); +jest.mock('gradient-string', () => jest.fn(() => jest.fn((text) => text))); -jest.mock("../../scripts/modules/utils.js", () => ({ - CONFIG: { - projectName: "Test Project", - projectVersion: "1.0.0", - }, - log: jest.fn(), - findTaskById: jest.fn(), - readJSON: jest.fn(), - readComplexityReport: jest.fn(), - truncate: jest.fn((text) => text), +jest.mock('../../scripts/modules/utils.js', () => ({ + CONFIG: { + projectName: 'Test Project', + projectVersion: '1.0.0' + }, + log: jest.fn(), + findTaskById: jest.fn(), + readJSON: jest.fn(), + readComplexityReport: jest.fn(), + truncate: jest.fn((text) => text) })); -jest.mock("../../scripts/modules/task-manager.js", () => ({ - findNextTask: jest.fn(), - analyzeTaskComplexity: jest.fn(), +jest.mock('../../scripts/modules/task-manager.js', () => ({ + findNextTask: jest.fn(), + analyzeTaskComplexity: jest.fn() })); -describe("UI Module", () => { - beforeEach(() => { - jest.clearAllMocks(); - }); +describe('UI Module', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); - describe("getStatusWithColor function", () => { - test("should return done status with emoji for console output", () => { - const result = getStatusWithColor("done"); - expect(result).toMatch(/done/); - expect(result).toContain("✓"); - }); + describe('getStatusWithColor function', () => { + test('should return done status with emoji for console output', () => { + const result = getStatusWithColor('done'); + expect(result).toMatch(/done/); + expect(result).toContain('✓'); + }); - test("should return pending status with emoji for console output", () => { - const result = getStatusWithColor("pending"); - expect(result).toMatch(/pending/); - expect(result).toContain("○"); - }); + test('should return pending status with emoji for console output', () => { + const result = getStatusWithColor('pending'); + expect(result).toMatch(/pending/); + expect(result).toContain('○'); + }); - test("should return deferred status with emoji for console output", () => { - const result = getStatusWithColor("deferred"); - expect(result).toMatch(/deferred/); - expect(result).toContain("x"); - }); + test('should return deferred status with emoji for console output', () => { + const result = getStatusWithColor('deferred'); + expect(result).toMatch(/deferred/); + expect(result).toContain('x'); + }); - test("should return in-progress status with emoji for console output", () => { - const result = getStatusWithColor("in-progress"); - expect(result).toMatch(/in-progress/); - expect(result).toContain("🔄"); - }); + test('should return in-progress status with emoji for console output', () => { + const result = getStatusWithColor('in-progress'); + expect(result).toMatch(/in-progress/); + expect(result).toContain('🔄'); + }); - test("should return unknown status with emoji for console output", () => { - const result = getStatusWithColor("unknown"); - expect(result).toMatch(/unknown/); - expect(result).toContain("❌"); - }); + test('should return unknown status with emoji for console output', () => { + const result = getStatusWithColor('unknown'); + expect(result).toMatch(/unknown/); + expect(result).toContain('❌'); + }); - test("should use simple icons when forTable is true", () => { - const doneResult = getStatusWithColor("done", true); - expect(doneResult).toMatch(/done/); - expect(doneResult).toContain("✓"); + test('should use simple icons when forTable is true', () => { + const doneResult = getStatusWithColor('done', true); + expect(doneResult).toMatch(/done/); + expect(doneResult).toContain('✓'); - const pendingResult = getStatusWithColor("pending", true); - expect(pendingResult).toMatch(/pending/); - expect(pendingResult).toContain("○"); + const pendingResult = getStatusWithColor('pending', true); + expect(pendingResult).toMatch(/pending/); + expect(pendingResult).toContain('○'); - const inProgressResult = getStatusWithColor("in-progress", true); - expect(inProgressResult).toMatch(/in-progress/); - expect(inProgressResult).toContain("►"); + const inProgressResult = getStatusWithColor('in-progress', true); + expect(inProgressResult).toMatch(/in-progress/); + expect(inProgressResult).toContain('►'); - const deferredResult = getStatusWithColor("deferred", true); - expect(deferredResult).toMatch(/deferred/); - expect(deferredResult).toContain("x"); - }); - }); + const deferredResult = getStatusWithColor('deferred', true); + expect(deferredResult).toMatch(/deferred/); + expect(deferredResult).toContain('x'); + }); + }); - describe("formatDependenciesWithStatus function", () => { - test("should format dependencies as plain IDs when forConsole is false (default)", () => { - const dependencies = [1, 2, 3]; - const allTasks = [ - { id: 1, status: "done" }, - { id: 2, status: "pending" }, - { id: 3, status: "deferred" }, - ]; + describe('formatDependenciesWithStatus function', () => { + test('should format dependencies as plain IDs when forConsole is false (default)', () => { + const dependencies = [1, 2, 3]; + const allTasks = [ + { id: 1, status: 'done' }, + { id: 2, status: 'pending' }, + { id: 3, status: 'deferred' } + ]; - const result = formatDependenciesWithStatus(dependencies, allTasks); + const result = formatDependenciesWithStatus(dependencies, allTasks); - // With recent changes, we expect just plain IDs when forConsole is false - expect(result).toBe("1, 2, 3"); - }); + // With recent changes, we expect just plain IDs when forConsole is false + expect(result).toBe('1, 2, 3'); + }); - test("should format dependencies with status indicators when forConsole is true", () => { - const dependencies = [1, 2, 3]; - const allTasks = [ - { id: 1, status: "done" }, - { id: 2, status: "pending" }, - { id: 3, status: "deferred" }, - ]; + test('should format dependencies with status indicators when forConsole is true', () => { + const dependencies = [1, 2, 3]; + const allTasks = [ + { id: 1, status: 'done' }, + { id: 2, status: 'pending' }, + { id: 3, status: 'deferred' } + ]; - const result = formatDependenciesWithStatus(dependencies, allTasks, true); + const result = formatDependenciesWithStatus(dependencies, allTasks, true); - // We can't test for exact color formatting due to our chalk mocks - // Instead, test that the result contains all the expected IDs - expect(result).toContain("1"); - expect(result).toContain("2"); - expect(result).toContain("3"); + // We can't test for exact color formatting due to our chalk mocks + // Instead, test that the result contains all the expected IDs + expect(result).toContain('1'); + expect(result).toContain('2'); + expect(result).toContain('3'); - // Test that it's a comma-separated list - expect(result.split(", ").length).toBe(3); - }); + // Test that it's a comma-separated list + expect(result.split(', ').length).toBe(3); + }); - test('should return "None" for empty dependencies', () => { - const result = formatDependenciesWithStatus([], []); - expect(result).toBe("None"); - }); + test('should return "None" for empty dependencies', () => { + const result = formatDependenciesWithStatus([], []); + expect(result).toBe('None'); + }); - test("should handle missing tasks in the task list", () => { - const dependencies = [1, 999]; - const allTasks = [{ id: 1, status: "done" }]; + test('should handle missing tasks in the task list', () => { + const dependencies = [1, 999]; + const allTasks = [{ id: 1, status: 'done' }]; - const result = formatDependenciesWithStatus(dependencies, allTasks); - expect(result).toBe("1, 999 (Not found)"); - }); - }); + const result = formatDependenciesWithStatus(dependencies, allTasks); + expect(result).toBe('1, 999 (Not found)'); + }); + }); - describe("createProgressBar function", () => { - test("should create a progress bar with the correct percentage", () => { - const result = createProgressBar(50, 10, { - pending: 20, - "in-progress": 15, - blocked: 5, - }); - expect(result).toContain("50%"); - }); + describe('createProgressBar function', () => { + test('should create a progress bar with the correct percentage', () => { + const result = createProgressBar(50, 10, { + pending: 20, + 'in-progress': 15, + blocked: 5 + }); + expect(result).toContain('50%'); + }); - test("should handle 0% progress", () => { - const result = createProgressBar(0, 10); - expect(result).toContain("0%"); - }); + test('should handle 0% progress', () => { + const result = createProgressBar(0, 10); + expect(result).toContain('0%'); + }); - test("should handle 100% progress", () => { - const result = createProgressBar(100, 10); - expect(result).toContain("100%"); - }); + test('should handle 100% progress', () => { + const result = createProgressBar(100, 10); + expect(result).toContain('100%'); + }); - test("should handle invalid percentages by clamping", () => { - const result1 = createProgressBar(0, 10); - expect(result1).toContain("0%"); + test('should handle invalid percentages by clamping', () => { + const result1 = createProgressBar(0, 10); + expect(result1).toContain('0%'); - const result2 = createProgressBar(100, 10); - expect(result2).toContain("100%"); - }); + const result2 = createProgressBar(100, 10); + expect(result2).toContain('100%'); + }); - test("should support status breakdown in the progress bar", () => { - const result = createProgressBar(30, 10, { - pending: 30, - "in-progress": 20, - blocked: 10, - deferred: 5, - cancelled: 5, - }); + test('should support status breakdown in the progress bar', () => { + const result = createProgressBar(30, 10, { + pending: 30, + 'in-progress': 20, + blocked: 10, + deferred: 5, + cancelled: 5 + }); - expect(result).toContain("40%"); - }); - }); + expect(result).toContain('40%'); + }); + }); - describe("getComplexityWithColor function", () => { - test("should return high complexity in red", () => { - const result = getComplexityWithColor(8); - expect(result).toMatch(/8/); - expect(result).toContain("●"); - }); + describe('getComplexityWithColor function', () => { + test('should return high complexity in red', () => { + const result = getComplexityWithColor(8); + expect(result).toMatch(/8/); + expect(result).toContain('●'); + }); - test("should return medium complexity in yellow", () => { - const result = getComplexityWithColor(5); - expect(result).toMatch(/5/); - expect(result).toContain("●"); - }); + test('should return medium complexity in yellow', () => { + const result = getComplexityWithColor(5); + expect(result).toMatch(/5/); + expect(result).toContain('●'); + }); - test("should return low complexity in green", () => { - const result = getComplexityWithColor(3); - expect(result).toMatch(/3/); - expect(result).toContain("●"); - }); + test('should return low complexity in green', () => { + const result = getComplexityWithColor(3); + expect(result).toMatch(/3/); + expect(result).toContain('●'); + }); - test("should handle non-numeric inputs", () => { - const result = getComplexityWithColor("high"); - expect(result).toMatch(/high/); - expect(result).toContain("●"); - }); - }); + test('should handle non-numeric inputs', () => { + const result = getComplexityWithColor('high'); + expect(result).toMatch(/high/); + expect(result).toContain('●'); + }); + }); });