diff --git a/.taskmaster/tasks/task_095.txt b/.taskmaster/tasks/task_095.txt index 39038951..fec48871 100644 --- a/.taskmaster/tasks/task_095.txt +++ b/.taskmaster/tasks/task_095.txt @@ -1,6 +1,6 @@ # Task ID: 95 # Title: Implement .taskmaster Directory Structure -# Status: in-progress +# Status: done # Dependencies: 1, 3, 4, 17 # Priority: high # Description: Consolidate all Task Master-managed files in user projects into a clean, centralized .taskmaster/ directory structure to improve organization and keep user project directories clean, based on GitHub issue #275. @@ -105,7 +105,7 @@ Update Task Master's file handling code to use the new paths: tasks in .taskmast ### Details: Update the task file generation system to create and read task files from .taskmaster/tasks/ instead of tasks/. Ensure all template paths are updated. Modify any path resolution logic specific to task file handling. -## 4. Implement backward compatibility logic [in-progress] +## 4. Implement backward compatibility logic [done] ### Dependencies: 95.2, 95.3 ### Description: Add fallback mechanisms to support both old and new file locations during transition ### Details: @@ -141,7 +141,7 @@ Update README.md and other documentation to reflect the new .taskmaster structur ### Details: Create functionality to support user-defined templates in .taskmaster/templates/. Allow users to store custom task templates, PRD templates, or other reusable files. Update Task Master commands to recognize and use templates from this directory when available. -## 10. Verify clean user project directories [in-progress] +## 10. Verify clean user project directories [done] ### Dependencies: 95.8, 95.9 ### Description: Ensure the new structure keeps user project root directories clean and organized ### Details: diff --git a/.taskmaster/tasks/tasks.json b/.taskmaster/tasks/tasks.json index bc85208a..9e62ad65 100644 --- a/.taskmaster/tasks/tasks.json +++ b/.taskmaster/tasks/tasks.json @@ -6050,7 +6050,7 @@ "id": 95, "title": "Implement .taskmaster Directory Structure", "description": "Consolidate all Task Master-managed files in user projects into a clean, centralized .taskmaster/ directory structure to improve organization and keep user project directories clean, based on GitHub issue #275.", - "status": "in-progress", + "status": "done", "dependencies": [ 1, 3, @@ -6101,7 +6101,7 @@ 3 ], "details": "Implement path fallback logic that checks both old and new locations when files aren't found. Add deprecation warnings when old paths are used, informing users about the new structure. Ensure error messages are clear about the transition.", - "status": "in-progress", + "status": "done", "testStrategy": "Test with both old and new directory structures to verify fallback works correctly. Verify deprecation warnings appear when using old paths." }, { @@ -6173,7 +6173,7 @@ 9 ], "details": "Validate that after implementing the new structure, user project root directories only contain their actual project files plus the single .taskmaster/ directory. Verify that no Task Master files are created outside of .taskmaster/. Test that users can easily add .taskmaster/ to .gitignore if they choose to exclude Task Master files from version control.", - "status": "in-progress", + "status": "done", "testStrategy": "Test complete workflows and verify only .taskmaster/ directory is created in project root. Check that all Task Master operations respect the new file organization. Verify .gitignore compatibility." } ] diff --git a/scripts/modules/ui.js b/scripts/modules/ui.js index 5dad1795..e1499195 100644 --- a/scripts/modules/ui.js +++ b/scripts/modules/ui.js @@ -750,9 +750,9 @@ function displayHelp() { * @returns {string} Colored complexity score */ function getComplexityWithColor(score) { - if (score <= 3) return chalk.green(`🟢 ${score}`); - if (score <= 6) return chalk.yellow(`🟡 ${score}`); - return chalk.red(`🔴 ${score}`); + if (score <= 3) return chalk.green(`● ${score}`); + if (score <= 6) return chalk.yellow(`● ${score}`); + return chalk.red(`● ${score}`); } /** diff --git a/tests/unit/ui.test.js b/tests/unit/ui.test.js index 8be90e1d..dbab8ea8 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('⏱️'); - }); + test("should return deferred status with emoji for console output", () => { + const result = getStatusWithColor("deferred"); + expect(result).toMatch(/deferred/); + 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 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("●"); + }); + }); });