Files
claude-task-master/tests/unit/ui/indicators.test.js
Joe Danziger e3ed4d7c14 feat: CLI & MCP progress tracking for parse-prd command (#1048)
* initial cutover

* update log to debug

* update tracker to pass units

* update test to match new base tracker format

* add streamTextService mocks

* remove unused imports

* Ensure the CLI waits for async main() completion

* refactor to reduce code duplication

* update comment

* reuse function

* ensure targetTag is defined in streaming mode

* avoid throwing inside process.exit spy

* check for null

* remove reference to generate

* fix formatting

* fix textStream assignment

* ensure no division by 0

* fix jest chalk mocks

* refactor for maintainability

* Improve bar chart calculation logic for consistent visual representation

* use custom streaming error types; fix mocks

* Update streamText extraction in parse-prd.js to match actual service response

* remove check - doesn't belong here

* update mocks

* remove streaming test that wasn't really doing anything

* add comment

* make parsing logic more DRY

* fix formatting

* Fix textStream extraction to match actual service response

* fix mock

* Add a cleanup method to ensure proper resource disposal and prevent memory leaks

* debounce progress updates to reduce UI flicker during rapid updates

* Implement timeout protection for streaming operations (60-second timeout) with automatic fallback to non-streaming mode.

* clear timeout properly

* Add a maximum buffer size limit (1MB) to prevent unbounded memory growth with very large streaming responses.

* fix formatting

* remove duplicate mock

* better docs

* fix formatting

* sanitize the dynamic property name

* Fix incorrect remaining progress calculation

* Use onError callback instead of console.warn

* Remove unused chalk import

* Add missing custom validator in fallback parsing configuration

* add custom validator parameter in fallback parsing

* chore: fix package-lock.json

* chore: large code refactor

* chore: increase timeout from 1 minute to 3 minutes

* fix: refactor and fix streaming

* Merge remote-tracking branch 'origin/next' into joedanz/parse-prd-progress

* fix: cleanup and fix unit tests

* chore: fix unit tests

* chore: fix format

* chore: run format

* chore: fix weird CI unit test error

* chore: fix format

---------

Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
2025-08-12 22:37:07 +02:00

170 lines
5.8 KiB
JavaScript

/**
* Unit tests for indicators module (priority and complexity indicators)
*/
import { jest } from '@jest/globals';
// Mock chalk using unstable_mockModule for ESM compatibility
jest.unstable_mockModule('chalk', () => ({
default: {
red: jest.fn((str) => str),
yellow: jest.fn((str) => str),
green: jest.fn((str) => str),
white: jest.fn((str) => str),
hex: jest.fn(() => jest.fn((str) => str))
}
}));
// Import after mocking
const {
getMcpPriorityIndicators,
getCliPriorityIndicators,
getPriorityIndicators,
getPriorityIndicator,
getStatusBarPriorityIndicators,
getPriorityColors,
getCliComplexityIndicators,
getStatusBarComplexityIndicators,
getComplexityColors,
getComplexityIndicator
} = await import('../../../src/ui/indicators.js');
describe('Priority Indicators', () => {
describe('getMcpPriorityIndicators', () => {
it('should return emoji indicators for MCP context', () => {
const indicators = getMcpPriorityIndicators();
expect(indicators).toEqual({
high: '🔴',
medium: '🟠',
low: '🟢'
});
});
});
describe('getCliPriorityIndicators', () => {
it('should return colored dot indicators for CLI context', () => {
const indicators = getCliPriorityIndicators();
expect(indicators).toHaveProperty('high');
expect(indicators).toHaveProperty('medium');
expect(indicators).toHaveProperty('low');
// Since chalk is mocked, we're just verifying structure
expect(indicators.high).toContain('●');
});
});
describe('getPriorityIndicators', () => {
it('should return MCP indicators when isMcp is true', () => {
const indicators = getPriorityIndicators(true);
expect(indicators).toEqual({
high: '🔴',
medium: '🟠',
low: '🟢'
});
});
it('should return CLI indicators when isMcp is false', () => {
const indicators = getPriorityIndicators(false);
expect(indicators).toHaveProperty('high');
expect(indicators).toHaveProperty('medium');
expect(indicators).toHaveProperty('low');
});
it('should default to CLI indicators when no parameter provided', () => {
const indicators = getPriorityIndicators();
expect(indicators).toHaveProperty('high');
expect(indicators.high).toContain('●');
});
});
describe('getPriorityIndicator', () => {
it('should return correct MCP indicator for valid priority', () => {
expect(getPriorityIndicator('high', true)).toBe('🔴');
expect(getPriorityIndicator('medium', true)).toBe('🟠');
expect(getPriorityIndicator('low', true)).toBe('🟢');
});
it('should return correct CLI indicator for valid priority', () => {
const highIndicator = getPriorityIndicator('high', false);
const mediumIndicator = getPriorityIndicator('medium', false);
const lowIndicator = getPriorityIndicator('low', false);
expect(highIndicator).toContain('●');
expect(mediumIndicator).toContain('●');
expect(lowIndicator).toContain('●');
});
it('should return medium indicator for invalid priority', () => {
expect(getPriorityIndicator('invalid', true)).toBe('🟠');
expect(getPriorityIndicator(null, true)).toBe('🟠');
expect(getPriorityIndicator(undefined, true)).toBe('🟠');
});
it('should default to CLI context when isMcp not provided', () => {
const indicator = getPriorityIndicator('high');
expect(indicator).toContain('●');
});
});
});
describe('Complexity Indicators', () => {
describe('getCliComplexityIndicators', () => {
it('should return colored dot indicators for complexity levels', () => {
const indicators = getCliComplexityIndicators();
expect(indicators).toHaveProperty('high');
expect(indicators).toHaveProperty('medium');
expect(indicators).toHaveProperty('low');
expect(indicators.high).toContain('●');
});
});
describe('getStatusBarComplexityIndicators', () => {
it('should return single character indicators for status bars', () => {
const indicators = getStatusBarComplexityIndicators();
// Since chalk is mocked, we need to check for the actual characters
expect(indicators.high).toContain('⋮');
expect(indicators.medium).toContain(':');
expect(indicators.low).toContain('.');
});
});
describe('getComplexityColors', () => {
it('should return complexity color functions', () => {
const colors = getComplexityColors();
expect(colors).toHaveProperty('high');
expect(colors).toHaveProperty('medium');
expect(colors).toHaveProperty('low');
// Verify they are functions (mocked chalk functions)
expect(typeof colors.high).toBe('function');
});
});
describe('getComplexityIndicator', () => {
it('should return high indicator for scores >= 7', () => {
const cliIndicators = getCliComplexityIndicators();
expect(getComplexityIndicator(7)).toBe(cliIndicators.high);
expect(getComplexityIndicator(8)).toBe(cliIndicators.high);
expect(getComplexityIndicator(10)).toBe(cliIndicators.high);
});
it('should return low indicator for scores <= 3', () => {
const cliIndicators = getCliComplexityIndicators();
expect(getComplexityIndicator(1)).toBe(cliIndicators.low);
expect(getComplexityIndicator(2)).toBe(cliIndicators.low);
expect(getComplexityIndicator(3)).toBe(cliIndicators.low);
});
it('should return medium indicator for scores 4-6', () => {
const cliIndicators = getCliComplexityIndicators();
expect(getComplexityIndicator(4)).toBe(cliIndicators.medium);
expect(getComplexityIndicator(5)).toBe(cliIndicators.medium);
expect(getComplexityIndicator(6)).toBe(cliIndicators.medium);
});
it('should return status bar indicators when statusBar is true', () => {
const statusBarIndicators = getStatusBarComplexityIndicators();
expect(getComplexityIndicator(8, true)).toBe(statusBarIndicators.high);
expect(getComplexityIndicator(5, true)).toBe(statusBarIndicators.medium);
expect(getComplexityIndicator(2, true)).toBe(statusBarIndicators.low);
});
});
});