yoda-mcp
Version:
Intelligent Planning MCP with Optional Dependencies and Graceful Fallbacks - wise planning through the Force of lean excellence
283 lines (246 loc) • 10.3 kB
text/typescript
/**
* SmartTDDInjector Tests
*
* RED PHASE: Write failing tests that define expected behavior
* These tests MUST fail initially - they define what we want to build
*/
import { SmartTDDInjector } from '../src/smart/smart-tdd-injector';
import { Task, Plan, TDDEnhancedPlan } from '../src/types';
describe('SmartTDDInjector', () => {
let injector: SmartTDDInjector;
beforeEach(() => {
injector = new SmartTDDInjector();
});
// RED: This test MUST fail - SmartTDDInjector doesn't exist yet
describe('Domain Detection', () => {
test('should detect authentication domain from task content', () => {
const task: Task = {
id: 'auth_login',
title: 'Implement user login functionality',
description: 'Create secure user authentication with email and password',
estimatedHours: 8,
skills: ['backend', 'security'],
dependencies: [],
deliverable: 'Working login system'
};
const domain = injector.detectDomain(task);
expect(domain).toBe('auth');
});
test('should detect API domain from task content', () => {
const task: Task = {
id: 'api_endpoint',
title: 'Create REST API endpoint for user data',
description: 'Build API endpoint to handle user CRUD operations',
estimatedHours: 6,
skills: ['backend', 'api'],
dependencies: [],
deliverable: 'REST API endpoint'
};
const domain = injector.detectDomain(task);
expect(domain).toBe('api');
});
test('should detect UI domain from task content', () => {
const task: Task = {
id: 'ui_component',
title: 'Build user profile component',
description: 'Create React component for displaying user profile information',
estimatedHours: 4,
skills: ['frontend', 'react'],
dependencies: [],
deliverable: 'Profile component'
};
const domain = injector.detectDomain(task);
expect(domain).toBe('ui');
});
});
// RED: This test MUST fail - generateTestExample doesn't exist yet
describe('Test Example Generation', () => {
test('should generate working auth test example', () => {
const task: Task = {
id: 'auth_login',
title: 'Implement user login',
description: 'User authentication with email/password',
estimatedHours: 8,
skills: ['auth'],
dependencies: [],
deliverable: 'Login function'
};
const testExample = injector.generateTestExample(task, 'auth');
// Test must be syntactically valid JavaScript/TypeScript
expect(testExample).toContain('describe(');
expect(testExample).toContain('test(');
expect(testExample).toContain('expect(');
// Must test authentication failure case (TDD best practice)
expect(testExample).toContain('Invalid credentials');
// Must be specific to the task, not generic
expect(testExample).toContain('authenticateUser');
});
test('should generate working API test example', () => {
const task: Task = {
id: 'api_users',
title: 'Create users API endpoint',
description: 'CRUD operations for user management',
estimatedHours: 6,
skills: ['api'],
dependencies: [],
deliverable: 'Users API'
};
const testExample = injector.generateTestExample(task, 'api');
expect(testExample).toContain('describe(');
expect(testExample).toContain('test(');
expect(testExample).toContain('request(app)');
expect(testExample).toContain('400'); // Should test error cases first
expect(testExample).toContain('required'); // Validation testing
});
test('should generate working UI test example', () => {
const task: Task = {
id: 'ui_form',
title: 'Build user registration form',
description: 'Form component with validation',
estimatedHours: 5,
skills: ['ui', 'react'],
dependencies: [],
deliverable: 'Registration form'
};
const testExample = injector.generateTestExample(task, 'ui');
expect(testExample).toContain('describe(');
expect(testExample).toContain('test(');
expect(testExample).toContain('render(');
expect(testExample).toContain('fireEvent');
expect(testExample).toContain('screen.getByRole');
// Should test error states first (TDD best practice)
expect(testExample).toContain('error');
});
});
// RED: This test MUST fail - injectTDD doesn't exist yet
describe('TDD Workflow Creation', () => {
test('should create complete TDD workflow for a task', () => {
const task: Task = {
id: 'feature_payment',
title: 'Implement payment processing',
description: 'Process credit card payments securely',
estimatedHours: 12,
skills: ['backend', 'payment'],
dependencies: [],
deliverable: 'Payment system'
};
const tddTask = injector.createTDDWorkflow(task);
// Must have all three TDD phases
expect(tddTask.tddCycle.red).toBeDefined();
expect(tddTask.tddCycle.green).toBeDefined();
expect(tddTask.tddCycle.refactor).toBeDefined();
// Red phase must emphasize test-first approach
expect(tddTask.tddCycle.red.description).toContain('failing test');
expect(tddTask.tddCycle.red.concreteExample).toContain('describe(');
expect(tddTask.tddCycle.red.successCriteria).toContain('Test fails for right reason');
// Time estimates should sum to original estimate
const totalTime = tddTask.tddCycle.red.estimatedTime +
tddTask.tddCycle.green.estimatedTime +
tddTask.tddCycle.refactor.estimatedTime;
expect(totalTime).toBe(task.estimatedHours);
// Green phase should be about minimal implementation
expect(tddTask.tddCycle.green.description).toContain('minimal code');
expect(tddTask.tddCycle.green.successCriteria).toContain('Test passes');
// Refactor phase should focus on quality improvement
expect(tddTask.tddCycle.refactor.description).toContain('quality');
expect(tddTask.tddCycle.refactor.successCriteria).toContain('All tests green');
});
});
// RED: This test MUST fail - injectTDD doesn't exist yet
describe('Plan Enhancement', () => {
test('should enhance plan with TDD methodology', () => {
const originalPlan: Plan = {
requirements: [
{
id: 'req_1',
description: 'User authentication system',
priority: 'must-have',
acceptanceCriteria: ['Users can log in', 'Passwords are secure']
}
],
tasks: [
{
id: 'task_auth',
title: 'Build login system',
description: 'Implement user authentication',
estimatedHours: 8,
skills: ['backend'],
dependencies: [],
deliverable: 'Login functionality'
}
],
timeline: {
totalEstimate: '1 week',
phases: [],
criticalPath: ['task_auth']
},
risks: [],
metadata: {
planId: 'test_plan',
generatedAt: new Date(),
estimatedReadTime: '5 minutes',
complexity: 'moderate'
}
};
const enhancedPlan: TDDEnhancedPlan = injector.injectTDD(originalPlan);
// Must preserve original plan structure
expect(enhancedPlan.requirements).toEqual(originalPlan.requirements);
expect(enhancedPlan.timeline).toEqual(originalPlan.timeline);
expect(enhancedPlan.risks).toEqual(originalPlan.risks);
expect(enhancedPlan.metadata).toEqual(originalPlan.metadata);
// Must add TDD enhancements
expect(enhancedPlan.tddGuidance).toBeDefined();
expect(enhancedPlan.tddGuidance.enabled).toBe(true);
expect(enhancedPlan.tddGuidance.redGreenRefactor).toBeDefined();
expect(enhancedPlan.tddGuidance.testingStrategy).toBeDefined();
expect(enhancedPlan.tddGuidance.testingStrategy.testCoverage).toBeGreaterThanOrEqual(90);
// Tasks must be enhanced with TDD workflows
expect(enhancedPlan.tasks).toHaveLength(originalPlan.tasks.length);
enhancedPlan.tasks.forEach(task => {
expect(task.tddCycle).toBeDefined();
expect(task.tddCycle.red).toBeDefined();
expect(task.tddCycle.green).toBeDefined();
expect(task.tddCycle.refactor).toBeDefined();
});
});
test('should only apply TDD to high-value tasks when optimized', () => {
const planWithManyTasks: Plan = {
requirements: [],
tasks: [
{
id: 'vital_task',
title: 'Core payment processing',
description: 'Critical payment functionality',
estimatedHours: 16,
skills: ['backend'],
dependencies: [],
deliverable: 'Payment system',
businessValue: 95, // High value
priority: 'vital'
},
{
id: 'trivial_task',
title: 'Update footer text',
description: 'Change copyright year',
estimatedHours: 1,
skills: ['frontend'],
dependencies: [],
deliverable: 'Updated footer',
businessValue: 5, // Low value
priority: 'trivial'
}
],
timeline: { totalEstimate: '3 weeks', phases: [], criticalPath: [] },
risks: [],
metadata: { planId: 'multi_task', generatedAt: new Date(), estimatedReadTime: '10 minutes', complexity: 'moderate' }
};
const vitalTasks = [planWithManyTasks.tasks[0]]; // Only high-value task
const enhancedPlan = injector.injectTDD(planWithManyTasks, vitalTasks);
// Only vital task should have TDD workflow
const vitalTask = enhancedPlan.tasks.find(t => t.id === 'vital_task');
const trivialTask = enhancedPlan.tasks.find(t => t.id === 'trivial_task');
expect(vitalTask.tddCycle).toBeDefined();
expect(trivialTask.tddCycle).toBeUndefined(); // Should not have TDD overhead
});
});
});