mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 21:03:08 +00:00
style: fix formatting with Prettier
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { AutoModeService } from "@/services/auto-mode-service.js";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { AutoModeService } from '@/services/auto-mode-service.js';
|
||||
|
||||
describe("auto-mode-service.ts - Planning Mode", () => {
|
||||
describe('auto-mode-service.ts - Planning Mode', () => {
|
||||
let service: AutoModeService;
|
||||
const mockEvents = {
|
||||
subscribe: vi.fn(),
|
||||
@@ -18,98 +18,98 @@ describe("auto-mode-service.ts - Planning Mode", () => {
|
||||
await service.stopAutoLoop().catch(() => {});
|
||||
});
|
||||
|
||||
describe("getPlanningPromptPrefix", () => {
|
||||
describe('getPlanningPromptPrefix', () => {
|
||||
// Access private method through any cast for testing
|
||||
const getPlanningPromptPrefix = (svc: any, feature: any) => {
|
||||
return svc.getPlanningPromptPrefix(feature);
|
||||
};
|
||||
|
||||
it("should return empty string for skip mode", () => {
|
||||
const feature = { id: "test", planningMode: "skip" as const };
|
||||
it('should return empty string for skip mode', () => {
|
||||
const feature = { id: 'test', planningMode: 'skip' as const };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toBe("");
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it("should return empty string when planningMode is undefined", () => {
|
||||
const feature = { id: "test" };
|
||||
it('should return empty string when planningMode is undefined', () => {
|
||||
const feature = { id: 'test' };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toBe("");
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it("should return lite prompt for lite mode without approval", () => {
|
||||
it('should return lite prompt for lite mode without approval', () => {
|
||||
const feature = {
|
||||
id: "test",
|
||||
planningMode: "lite" as const,
|
||||
requirePlanApproval: false
|
||||
id: 'test',
|
||||
planningMode: 'lite' as const,
|
||||
requirePlanApproval: false,
|
||||
};
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Planning Phase (Lite Mode)");
|
||||
expect(result).toContain("[PLAN_GENERATED]");
|
||||
expect(result).toContain("Feature Request");
|
||||
expect(result).toContain('Planning Phase (Lite Mode)');
|
||||
expect(result).toContain('[PLAN_GENERATED]');
|
||||
expect(result).toContain('Feature Request');
|
||||
});
|
||||
|
||||
it("should return lite_with_approval prompt for lite mode with approval", () => {
|
||||
it('should return lite_with_approval prompt for lite mode with approval', () => {
|
||||
const feature = {
|
||||
id: "test",
|
||||
planningMode: "lite" as const,
|
||||
requirePlanApproval: true
|
||||
id: 'test',
|
||||
planningMode: 'lite' as const,
|
||||
requirePlanApproval: true,
|
||||
};
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Planning Phase (Lite Mode)");
|
||||
expect(result).toContain("[SPEC_GENERATED]");
|
||||
expect(result).toContain("DO NOT proceed with implementation");
|
||||
expect(result).toContain('Planning Phase (Lite Mode)');
|
||||
expect(result).toContain('[SPEC_GENERATED]');
|
||||
expect(result).toContain('DO NOT proceed with implementation');
|
||||
});
|
||||
|
||||
it("should return spec prompt for spec mode", () => {
|
||||
it('should return spec prompt for spec mode', () => {
|
||||
const feature = {
|
||||
id: "test",
|
||||
planningMode: "spec" as const
|
||||
id: 'test',
|
||||
planningMode: 'spec' as const,
|
||||
};
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Specification Phase (Spec Mode)");
|
||||
expect(result).toContain("```tasks");
|
||||
expect(result).toContain("T001");
|
||||
expect(result).toContain("[TASK_START]");
|
||||
expect(result).toContain("[TASK_COMPLETE]");
|
||||
expect(result).toContain('Specification Phase (Spec Mode)');
|
||||
expect(result).toContain('```tasks');
|
||||
expect(result).toContain('T001');
|
||||
expect(result).toContain('[TASK_START]');
|
||||
expect(result).toContain('[TASK_COMPLETE]');
|
||||
});
|
||||
|
||||
it("should return full prompt for full mode", () => {
|
||||
it('should return full prompt for full mode', () => {
|
||||
const feature = {
|
||||
id: "test",
|
||||
planningMode: "full" as const
|
||||
id: 'test',
|
||||
planningMode: 'full' as const,
|
||||
};
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Full Specification Phase (Full SDD Mode)");
|
||||
expect(result).toContain("Phase 1: Foundation");
|
||||
expect(result).toContain("Phase 2: Core Implementation");
|
||||
expect(result).toContain("Phase 3: Integration & Testing");
|
||||
expect(result).toContain('Full Specification Phase (Full SDD Mode)');
|
||||
expect(result).toContain('Phase 1: Foundation');
|
||||
expect(result).toContain('Phase 2: Core Implementation');
|
||||
expect(result).toContain('Phase 3: Integration & Testing');
|
||||
});
|
||||
|
||||
it("should include the separator and Feature Request header", () => {
|
||||
it('should include the separator and Feature Request header', () => {
|
||||
const feature = {
|
||||
id: "test",
|
||||
planningMode: "spec" as const
|
||||
id: 'test',
|
||||
planningMode: 'spec' as const,
|
||||
};
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("---");
|
||||
expect(result).toContain("## Feature Request");
|
||||
expect(result).toContain('---');
|
||||
expect(result).toContain('## Feature Request');
|
||||
});
|
||||
|
||||
it("should instruct agent to NOT output exploration text", () => {
|
||||
const modes = ["lite", "spec", "full"] as const;
|
||||
it('should instruct agent to NOT output exploration text', () => {
|
||||
const modes = ['lite', 'spec', 'full'] as const;
|
||||
for (const mode of modes) {
|
||||
const feature = { id: "test", planningMode: mode };
|
||||
const feature = { id: 'test', planningMode: mode };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Do NOT output exploration text");
|
||||
expect(result).toContain("Start DIRECTLY");
|
||||
expect(result).toContain('Do NOT output exploration text');
|
||||
expect(result).toContain('Start DIRECTLY');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseTasksFromSpec (via module)", () => {
|
||||
describe('parseTasksFromSpec (via module)', () => {
|
||||
// We need to test the module-level function
|
||||
// Import it directly for testing
|
||||
it("should parse tasks from a valid tasks block", async () => {
|
||||
it('should parse tasks from a valid tasks block', async () => {
|
||||
// This tests the internal logic through integration
|
||||
// The function is module-level, so we verify behavior through the service
|
||||
const specContent = `
|
||||
@@ -123,12 +123,12 @@ describe("auto-mode-service.ts - Planning Mode", () => {
|
||||
`;
|
||||
// Since parseTasksFromSpec is a module-level function,
|
||||
// we verify its behavior indirectly through plan parsing
|
||||
expect(specContent).toContain("T001");
|
||||
expect(specContent).toContain("T002");
|
||||
expect(specContent).toContain("T003");
|
||||
expect(specContent).toContain('T001');
|
||||
expect(specContent).toContain('T002');
|
||||
expect(specContent).toContain('T003');
|
||||
});
|
||||
|
||||
it("should handle tasks block with phases", () => {
|
||||
it('should handle tasks block with phases', () => {
|
||||
const specContent = `
|
||||
\`\`\`tasks
|
||||
## Phase 1: Setup
|
||||
@@ -139,190 +139,191 @@ describe("auto-mode-service.ts - Planning Mode", () => {
|
||||
- [ ] T003: Create main module | File: src/index.ts
|
||||
\`\`\`
|
||||
`;
|
||||
expect(specContent).toContain("Phase 1");
|
||||
expect(specContent).toContain("Phase 2");
|
||||
expect(specContent).toContain("T001");
|
||||
expect(specContent).toContain("T003");
|
||||
expect(specContent).toContain('Phase 1');
|
||||
expect(specContent).toContain('Phase 2');
|
||||
expect(specContent).toContain('T001');
|
||||
expect(specContent).toContain('T003');
|
||||
});
|
||||
});
|
||||
|
||||
describe("plan approval flow", () => {
|
||||
it("should track pending approvals correctly", () => {
|
||||
expect(service.hasPendingApproval("test-feature")).toBe(false);
|
||||
describe('plan approval flow', () => {
|
||||
it('should track pending approvals correctly', () => {
|
||||
expect(service.hasPendingApproval('test-feature')).toBe(false);
|
||||
});
|
||||
|
||||
it("should allow cancelling non-existent approval without error", () => {
|
||||
expect(() => service.cancelPlanApproval("non-existent")).not.toThrow();
|
||||
it('should allow cancelling non-existent approval without error', () => {
|
||||
expect(() => service.cancelPlanApproval('non-existent')).not.toThrow();
|
||||
});
|
||||
|
||||
it("should return running features count after stop", async () => {
|
||||
it('should return running features count after stop', async () => {
|
||||
const count = await service.stopAutoLoop();
|
||||
expect(count).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolvePlanApproval", () => {
|
||||
it("should return error when no pending approval exists", async () => {
|
||||
describe('resolvePlanApproval', () => {
|
||||
it('should return error when no pending approval exists', async () => {
|
||||
const result = await service.resolvePlanApproval(
|
||||
"non-existent-feature",
|
||||
'non-existent-feature',
|
||||
true,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("No pending approval");
|
||||
expect(result.error).toContain('No pending approval');
|
||||
});
|
||||
|
||||
it("should handle approval with edited plan", async () => {
|
||||
it('should handle approval with edited plan', async () => {
|
||||
// Without a pending approval, this should fail gracefully
|
||||
const result = await service.resolvePlanApproval(
|
||||
"test-feature",
|
||||
'test-feature',
|
||||
true,
|
||||
"Edited plan content",
|
||||
'Edited plan content',
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
expect(result.success).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle rejection with feedback", async () => {
|
||||
it('should handle rejection with feedback', async () => {
|
||||
const result = await service.resolvePlanApproval(
|
||||
"test-feature",
|
||||
'test-feature',
|
||||
false,
|
||||
undefined,
|
||||
"Please add more details",
|
||||
'Please add more details',
|
||||
undefined
|
||||
);
|
||||
expect(result.success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildFeaturePrompt", () => {
|
||||
describe('buildFeaturePrompt', () => {
|
||||
const buildFeaturePrompt = (svc: any, feature: any) => {
|
||||
return svc.buildFeaturePrompt(feature);
|
||||
};
|
||||
|
||||
it("should include feature ID and description", () => {
|
||||
it('should include feature ID and description', () => {
|
||||
const feature = {
|
||||
id: "feat-123",
|
||||
description: "Add user authentication",
|
||||
id: 'feat-123',
|
||||
description: 'Add user authentication',
|
||||
};
|
||||
const result = buildFeaturePrompt(service, feature);
|
||||
expect(result).toContain("feat-123");
|
||||
expect(result).toContain("Add user authentication");
|
||||
expect(result).toContain('feat-123');
|
||||
expect(result).toContain('Add user authentication');
|
||||
});
|
||||
|
||||
it("should include specification when present", () => {
|
||||
it('should include specification when present', () => {
|
||||
const feature = {
|
||||
id: "feat-123",
|
||||
description: "Test feature",
|
||||
spec: "Detailed specification here",
|
||||
id: 'feat-123',
|
||||
description: 'Test feature',
|
||||
spec: 'Detailed specification here',
|
||||
};
|
||||
const result = buildFeaturePrompt(service, feature);
|
||||
expect(result).toContain("Specification:");
|
||||
expect(result).toContain("Detailed specification here");
|
||||
expect(result).toContain('Specification:');
|
||||
expect(result).toContain('Detailed specification here');
|
||||
});
|
||||
|
||||
it("should include image paths when present", () => {
|
||||
it('should include image paths when present', () => {
|
||||
const feature = {
|
||||
id: "feat-123",
|
||||
description: "Test feature",
|
||||
id: 'feat-123',
|
||||
description: 'Test feature',
|
||||
imagePaths: [
|
||||
{ path: "/tmp/image1.png", filename: "image1.png", mimeType: "image/png" },
|
||||
"/tmp/image2.jpg",
|
||||
{ path: '/tmp/image1.png', filename: 'image1.png', mimeType: 'image/png' },
|
||||
'/tmp/image2.jpg',
|
||||
],
|
||||
};
|
||||
const result = buildFeaturePrompt(service, feature);
|
||||
expect(result).toContain("Context Images Attached");
|
||||
expect(result).toContain("image1.png");
|
||||
expect(result).toContain("/tmp/image2.jpg");
|
||||
expect(result).toContain('Context Images Attached');
|
||||
expect(result).toContain('image1.png');
|
||||
expect(result).toContain('/tmp/image2.jpg');
|
||||
});
|
||||
|
||||
it("should include summary tags instruction", () => {
|
||||
it('should include summary tags instruction', () => {
|
||||
const feature = {
|
||||
id: "feat-123",
|
||||
description: "Test feature",
|
||||
id: 'feat-123',
|
||||
description: 'Test feature',
|
||||
};
|
||||
const result = buildFeaturePrompt(service, feature);
|
||||
expect(result).toContain("<summary>");
|
||||
expect(result).toContain("</summary>");
|
||||
expect(result).toContain('<summary>');
|
||||
expect(result).toContain('</summary>');
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractTitleFromDescription", () => {
|
||||
describe('extractTitleFromDescription', () => {
|
||||
const extractTitle = (svc: any, description: string) => {
|
||||
return svc.extractTitleFromDescription(description);
|
||||
};
|
||||
|
||||
it("should return 'Untitled Feature' for empty description", () => {
|
||||
expect(extractTitle(service, "")).toBe("Untitled Feature");
|
||||
expect(extractTitle(service, " ")).toBe("Untitled Feature");
|
||||
expect(extractTitle(service, '')).toBe('Untitled Feature');
|
||||
expect(extractTitle(service, ' ')).toBe('Untitled Feature');
|
||||
});
|
||||
|
||||
it("should return first line if under 60 characters", () => {
|
||||
const description = "Add user login\nWith email validation";
|
||||
expect(extractTitle(service, description)).toBe("Add user login");
|
||||
it('should return first line if under 60 characters', () => {
|
||||
const description = 'Add user login\nWith email validation';
|
||||
expect(extractTitle(service, description)).toBe('Add user login');
|
||||
});
|
||||
|
||||
it("should truncate long first lines to 60 characters", () => {
|
||||
const description = "This is a very long feature description that exceeds the sixty character limit significantly";
|
||||
it('should truncate long first lines to 60 characters', () => {
|
||||
const description =
|
||||
'This is a very long feature description that exceeds the sixty character limit significantly';
|
||||
const result = extractTitle(service, description);
|
||||
expect(result.length).toBe(60);
|
||||
expect(result).toContain("...");
|
||||
expect(result).toContain('...');
|
||||
});
|
||||
});
|
||||
|
||||
describe("PLANNING_PROMPTS structure", () => {
|
||||
describe('PLANNING_PROMPTS structure', () => {
|
||||
const getPlanningPromptPrefix = (svc: any, feature: any) => {
|
||||
return svc.getPlanningPromptPrefix(feature);
|
||||
};
|
||||
|
||||
it("should have all required planning modes", () => {
|
||||
const modes = ["lite", "spec", "full"] as const;
|
||||
it('should have all required planning modes', () => {
|
||||
const modes = ['lite', 'spec', 'full'] as const;
|
||||
for (const mode of modes) {
|
||||
const feature = { id: "test", planningMode: mode };
|
||||
const feature = { id: 'test', planningMode: mode };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result.length).toBeGreaterThan(100);
|
||||
}
|
||||
});
|
||||
|
||||
it("lite prompt should include correct structure", () => {
|
||||
const feature = { id: "test", planningMode: "lite" as const };
|
||||
it('lite prompt should include correct structure', () => {
|
||||
const feature = { id: 'test', planningMode: 'lite' as const };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Goal");
|
||||
expect(result).toContain("Approach");
|
||||
expect(result).toContain("Files to Touch");
|
||||
expect(result).toContain("Tasks");
|
||||
expect(result).toContain("Risks");
|
||||
expect(result).toContain('Goal');
|
||||
expect(result).toContain('Approach');
|
||||
expect(result).toContain('Files to Touch');
|
||||
expect(result).toContain('Tasks');
|
||||
expect(result).toContain('Risks');
|
||||
});
|
||||
|
||||
it("spec prompt should include task format instructions", () => {
|
||||
const feature = { id: "test", planningMode: "spec" as const };
|
||||
it('spec prompt should include task format instructions', () => {
|
||||
const feature = { id: 'test', planningMode: 'spec' as const };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Problem");
|
||||
expect(result).toContain("Solution");
|
||||
expect(result).toContain("Acceptance Criteria");
|
||||
expect(result).toContain("GIVEN-WHEN-THEN");
|
||||
expect(result).toContain("Implementation Tasks");
|
||||
expect(result).toContain("Verification");
|
||||
expect(result).toContain('Problem');
|
||||
expect(result).toContain('Solution');
|
||||
expect(result).toContain('Acceptance Criteria');
|
||||
expect(result).toContain('GIVEN-WHEN-THEN');
|
||||
expect(result).toContain('Implementation Tasks');
|
||||
expect(result).toContain('Verification');
|
||||
});
|
||||
|
||||
it("full prompt should include phases", () => {
|
||||
const feature = { id: "test", planningMode: "full" as const };
|
||||
it('full prompt should include phases', () => {
|
||||
const feature = { id: 'test', planningMode: 'full' as const };
|
||||
const result = getPlanningPromptPrefix(service, feature);
|
||||
expect(result).toContain("Problem Statement");
|
||||
expect(result).toContain("User Story");
|
||||
expect(result).toContain("Technical Context");
|
||||
expect(result).toContain("Non-Goals");
|
||||
expect(result).toContain("Phase 1");
|
||||
expect(result).toContain("Phase 2");
|
||||
expect(result).toContain("Phase 3");
|
||||
expect(result).toContain('Problem Statement');
|
||||
expect(result).toContain('User Story');
|
||||
expect(result).toContain('Technical Context');
|
||||
expect(result).toContain('Non-Goals');
|
||||
expect(result).toContain('Phase 1');
|
||||
expect(result).toContain('Phase 2');
|
||||
expect(result).toContain('Phase 3');
|
||||
});
|
||||
});
|
||||
|
||||
describe("status management", () => {
|
||||
it("should report correct status", () => {
|
||||
describe('status management', () => {
|
||||
it('should report correct status', () => {
|
||||
const status = service.getStatus();
|
||||
expect(status.runningFeatures).toEqual([]);
|
||||
expect(status.isRunning).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user