Files
automaker/libs/prompts/tests/enhancement.test.ts
gsxdsm 0330c70261 Feature: worktree view customization and stability fixes (#805)
* Changes from feature/worktree-view-customization

* Feature: Git sync, set-tracking, and push divergence handling (#796)

* Add quick-add feature with improved workflows (#802)

* Changes from feature/quick-add

* feat: Clarify system prompt and improve error handling across services. Address PR Feedback

* feat: Improve PR description parsing and refactor event handling

* feat: Add context options to pipeline orchestrator initialization

* fix: Deduplicate React and handle CJS interop for use-sync-external-store

Resolve "Cannot read properties of null (reading 'useState')" errors by
deduplicating React/react-dom and ensuring use-sync-external-store is
bundled together with React to prevent CJS packages from resolving to
different React instances.

* Changes from feature/worktree-view-customization

* refactor: Remove unused worktree swap and highlight props

* refactor: Consolidate feature completion logic and improve thinking level defaults

* feat: Increase max turn limit to 10000

- Update DEFAULT_MAX_TURNS from 1000 to 10000 in settings-helpers.ts and agent-executor.ts
- Update MAX_ALLOWED_TURNS from 2000 to 10000 in settings-helpers.ts
- Update UI clamping logic from 2000 to 10000 in app-store.ts
- Update fallback values from 1000 to 10000 in use-settings-sync.ts
- Update default value from 1000 to 10000 in DEFAULT_GLOBAL_SETTINGS
- Update documentation to reflect new range: 1-10000

Allows agents to perform up to 10000 turns for complex feature execution.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* feat: Add model resolution, improve session handling, and enhance UI stability

* refactor: Remove unused sync and tracking branch props from worktree components

* feat: Add PR number update functionality to worktrees. Address pr feedback

* feat: Optimize Gemini CLI startup and add tool result tracking

* refactor: Improve error handling and simplify worktree task cleanup

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-23 20:31:25 -08:00

580 lines
20 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
getEnhancementPrompt,
getSystemPrompt,
getExamples,
buildUserPrompt,
isValidEnhancementMode,
getAvailableEnhancementModes,
IMPROVE_SYSTEM_PROMPT,
TECHNICAL_SYSTEM_PROMPT,
SIMPLIFY_SYSTEM_PROMPT,
ACCEPTANCE_SYSTEM_PROMPT,
UX_REVIEWER_SYSTEM_PROMPT,
IMPROVE_EXAMPLES,
TECHNICAL_EXAMPLES,
SIMPLIFY_EXAMPLES,
ACCEPTANCE_EXAMPLES,
UX_REVIEWER_EXAMPLES,
} from '../src/enhancement.js';
describe('enhancement.ts', () => {
describe('System Prompt Constants', () => {
it('should export IMPROVE_SYSTEM_PROMPT', () => {
expect(IMPROVE_SYSTEM_PROMPT).toBeDefined();
expect(typeof IMPROVE_SYSTEM_PROMPT).toBe('string');
expect(IMPROVE_SYSTEM_PROMPT).toContain('vague, unclear');
expect(IMPROVE_SYSTEM_PROMPT).toContain('actionable');
});
it('should export TECHNICAL_SYSTEM_PROMPT', () => {
expect(TECHNICAL_SYSTEM_PROMPT).toBeDefined();
expect(typeof TECHNICAL_SYSTEM_PROMPT).toBe('string');
expect(TECHNICAL_SYSTEM_PROMPT).toContain('technical');
expect(TECHNICAL_SYSTEM_PROMPT).toContain('implementation');
});
it('should export SIMPLIFY_SYSTEM_PROMPT', () => {
expect(SIMPLIFY_SYSTEM_PROMPT).toBeDefined();
expect(typeof SIMPLIFY_SYSTEM_PROMPT).toBe('string');
expect(SIMPLIFY_SYSTEM_PROMPT).toContain('verbose');
expect(SIMPLIFY_SYSTEM_PROMPT).toContain('concise');
});
it('should export ACCEPTANCE_SYSTEM_PROMPT', () => {
expect(ACCEPTANCE_SYSTEM_PROMPT).toBeDefined();
expect(typeof ACCEPTANCE_SYSTEM_PROMPT).toBe('string');
expect(ACCEPTANCE_SYSTEM_PROMPT).toContain('acceptance criteria');
expect(ACCEPTANCE_SYSTEM_PROMPT).toContain('testable');
});
it('should export UX_REVIEWER_SYSTEM_PROMPT', () => {
expect(UX_REVIEWER_SYSTEM_PROMPT).toBeDefined();
expect(typeof UX_REVIEWER_SYSTEM_PROMPT).toBe('string');
expect(UX_REVIEWER_SYSTEM_PROMPT).toContain('User Experience');
});
});
describe('Examples Constants', () => {
it('should export IMPROVE_EXAMPLES with valid structure', () => {
expect(IMPROVE_EXAMPLES).toBeDefined();
expect(Array.isArray(IMPROVE_EXAMPLES)).toBe(true);
expect(IMPROVE_EXAMPLES.length).toBeGreaterThan(0);
IMPROVE_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty('input');
expect(example).toHaveProperty('output');
expect(typeof example.input).toBe('string');
expect(typeof example.output).toBe('string');
});
});
it('should export TECHNICAL_EXAMPLES with valid structure', () => {
expect(TECHNICAL_EXAMPLES).toBeDefined();
expect(Array.isArray(TECHNICAL_EXAMPLES)).toBe(true);
expect(TECHNICAL_EXAMPLES.length).toBeGreaterThan(0);
TECHNICAL_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty('input');
expect(example).toHaveProperty('output');
expect(typeof example.input).toBe('string');
expect(typeof example.output).toBe('string');
});
});
it('should export SIMPLIFY_EXAMPLES with valid structure', () => {
expect(SIMPLIFY_EXAMPLES).toBeDefined();
expect(Array.isArray(SIMPLIFY_EXAMPLES)).toBe(true);
expect(SIMPLIFY_EXAMPLES.length).toBeGreaterThan(0);
SIMPLIFY_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty('input');
expect(example).toHaveProperty('output');
expect(typeof example.input).toBe('string');
expect(typeof example.output).toBe('string');
});
});
it('should export ACCEPTANCE_EXAMPLES with valid structure', () => {
expect(ACCEPTANCE_EXAMPLES).toBeDefined();
expect(Array.isArray(ACCEPTANCE_EXAMPLES)).toBe(true);
expect(ACCEPTANCE_EXAMPLES.length).toBeGreaterThan(0);
ACCEPTANCE_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty('input');
expect(example).toHaveProperty('output');
expect(typeof example.input).toBe('string');
expect(typeof example.output).toBe('string');
});
});
it('should export UX_REVIEWER_EXAMPLES with valid structure', () => {
expect(UX_REVIEWER_EXAMPLES).toBeDefined();
expect(Array.isArray(UX_REVIEWER_EXAMPLES)).toBe(true);
expect(UX_REVIEWER_EXAMPLES.length).toBeGreaterThan(0);
UX_REVIEWER_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty('input');
expect(example).toHaveProperty('output');
expect(typeof example.input).toBe('string');
expect(typeof example.output).toBe('string');
});
});
it('should have shorter outputs in SIMPLIFY_EXAMPLES', () => {
SIMPLIFY_EXAMPLES.forEach((example) => {
// Simplify examples should have shorter output than input
// (though not always strictly enforced, it's the general pattern)
expect(example.output).toBeDefined();
expect(example.output.length).toBeGreaterThan(0);
});
});
});
describe('getEnhancementPrompt', () => {
it("should return prompt config for 'improve' mode", () => {
const result = getEnhancementPrompt('improve');
expect(result).toHaveProperty('systemPrompt');
expect(result).toHaveProperty('description');
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(result.description).toContain('vague');
expect(result.description).toContain('actionable');
});
it("should return prompt config for 'technical' mode", () => {
const result = getEnhancementPrompt('technical');
expect(result).toHaveProperty('systemPrompt');
expect(result).toHaveProperty('description');
expect(result.systemPrompt).toBe(TECHNICAL_SYSTEM_PROMPT);
expect(result.description).toContain('implementation');
});
it("should return prompt config for 'simplify' mode", () => {
const result = getEnhancementPrompt('simplify');
expect(result).toHaveProperty('systemPrompt');
expect(result).toHaveProperty('description');
expect(result.systemPrompt).toBe(SIMPLIFY_SYSTEM_PROMPT);
expect(result.description).toContain('verbose');
});
it("should return prompt config for 'acceptance' mode", () => {
const result = getEnhancementPrompt('acceptance');
expect(result).toHaveProperty('systemPrompt');
expect(result).toHaveProperty('description');
expect(result.systemPrompt).toBe(ACCEPTANCE_SYSTEM_PROMPT);
expect(result.description).toContain('acceptance');
});
it("should return prompt config for 'ux-reviewer' mode", () => {
const result = getEnhancementPrompt('ux-reviewer');
expect(result).toHaveProperty('systemPrompt');
expect(result).toHaveProperty('description');
expect(result.systemPrompt).toBe(UX_REVIEWER_SYSTEM_PROMPT);
expect(result.description.toLowerCase()).toContain('user experience');
});
it('should handle uppercase mode', () => {
const result = getEnhancementPrompt('IMPROVE');
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
});
it('should handle mixed case mode', () => {
const result = getEnhancementPrompt('TeChnIcaL');
expect(result.systemPrompt).toBe(TECHNICAL_SYSTEM_PROMPT);
});
it("should fall back to 'improve' for invalid mode", () => {
const result = getEnhancementPrompt('invalid-mode');
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(result.description).toContain('vague');
});
it("should fall back to 'improve' for empty string", () => {
const result = getEnhancementPrompt('');
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
});
});
describe('getSystemPrompt', () => {
it("should return IMPROVE_SYSTEM_PROMPT for 'improve'", () => {
const result = getSystemPrompt('improve');
expect(result).toBe(IMPROVE_SYSTEM_PROMPT);
});
it("should return TECHNICAL_SYSTEM_PROMPT for 'technical'", () => {
const result = getSystemPrompt('technical');
expect(result).toBe(TECHNICAL_SYSTEM_PROMPT);
});
it("should return SIMPLIFY_SYSTEM_PROMPT for 'simplify'", () => {
const result = getSystemPrompt('simplify');
expect(result).toBe(SIMPLIFY_SYSTEM_PROMPT);
});
it("should return ACCEPTANCE_SYSTEM_PROMPT for 'acceptance'", () => {
const result = getSystemPrompt('acceptance');
expect(result).toBe(ACCEPTANCE_SYSTEM_PROMPT);
});
it("should return UX_REVIEWER_SYSTEM_PROMPT for 'ux-reviewer'", () => {
const result = getSystemPrompt('ux-reviewer');
expect(result).toBe(UX_REVIEWER_SYSTEM_PROMPT);
});
});
describe('getExamples', () => {
it("should return IMPROVE_EXAMPLES for 'improve'", () => {
const result = getExamples('improve');
expect(result).toBe(IMPROVE_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return TECHNICAL_EXAMPLES for 'technical'", () => {
const result = getExamples('technical');
expect(result).toBe(TECHNICAL_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return SIMPLIFY_EXAMPLES for 'simplify'", () => {
const result = getExamples('simplify');
expect(result).toBe(SIMPLIFY_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return ACCEPTANCE_EXAMPLES for 'acceptance'", () => {
const result = getExamples('acceptance');
expect(result).toBe(ACCEPTANCE_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return UX_REVIEWER_EXAMPLES for 'ux-reviewer'", () => {
const result = getExamples('ux-reviewer');
expect(result).toBe(UX_REVIEWER_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
});
describe('buildUserPrompt', () => {
const testText = 'Add a login feature';
describe('with examples (default)', () => {
it("should include examples by default for 'improve' mode", () => {
const result = buildUserPrompt('improve', testText);
expect(result).toContain('Here are some examples');
expect(result).toContain('Example 1:');
expect(result).toContain(IMPROVE_EXAMPLES[0].input);
expect(result).toContain(IMPROVE_EXAMPLES[0].output);
expect(result).toContain(testText);
});
it("should include examples by default for 'technical' mode", () => {
const result = buildUserPrompt('technical', testText);
expect(result).toContain('Here are examples of the additional details section');
expect(result).toContain('Example 1:');
expect(result).toContain(TECHNICAL_EXAMPLES[0].input);
expect(result).toContain(testText);
});
it('should include examples when explicitly set to true', () => {
const result = buildUserPrompt('improve', testText, true);
expect(result).toContain('Here are some examples');
expect(result).toContain(testText);
});
it('should format all examples with numbered labels', () => {
const result = buildUserPrompt('improve', testText);
IMPROVE_EXAMPLES.forEach((_, index) => {
expect(result).toContain(`Example ${index + 1}:`);
});
});
it('should separate examples with dividers', () => {
const result = buildUserPrompt('improve', testText);
// Count dividers (---) - should be (examples.length) + 1
const dividerCount = (result.match(/---/g) || []).length;
expect(dividerCount).toBe(IMPROVE_EXAMPLES.length);
});
it("should include 'Please enhance' before user text", () => {
const result = buildUserPrompt('improve', testText);
expect(result).toContain('Please enhance the following task description:');
expect(result).toContain(testText);
});
});
describe('without examples', () => {
it('should not include examples when includeExamples is false', () => {
const result = buildUserPrompt('improve', testText, false);
expect(result).not.toContain('Here are some examples');
expect(result).not.toContain('Example 1:');
expect(result).not.toContain(IMPROVE_EXAMPLES[0].input);
});
it('should have simple prompt without examples', () => {
const result = buildUserPrompt('improve', testText, false);
expect(result).toBe(`Please enhance the following task description:\n\n${testText}`);
});
it('should preserve user text without examples', () => {
const result = buildUserPrompt('technical', testText, false);
expect(result).toContain(testText);
expect(result).toContain('Generate ONLY the additional details');
});
it('should use additive phrasing for ux-reviewer mode', () => {
const result = buildUserPrompt('ux-reviewer', testText, true);
expect(result).toContain(testText);
expect(result).toContain('Here are examples of the additional details section');
});
});
describe('text formatting', () => {
it('should preserve multiline text', () => {
const multilineText = 'Line 1\nLine 2\nLine 3';
const result = buildUserPrompt('improve', multilineText);
expect(result).toContain(multilineText);
});
it('should handle empty text', () => {
const result = buildUserPrompt('improve', '');
// With examples by default, it should contain "Please enhance"
expect(result).toContain('Please enhance the following task description:');
expect(result).toContain('Here are some examples');
});
it('should handle whitespace-only text', () => {
const result = buildUserPrompt('improve', ' ');
expect(result).toContain(' ');
});
it('should handle special characters in text', () => {
const specialText = 'Test <html> & "quotes" \'apostrophes\'';
const result = buildUserPrompt('improve', specialText);
expect(result).toContain(specialText);
});
});
describe('all modes', () => {
it('should work for all valid enhancement modes', () => {
const modes: Array<'improve' | 'technical' | 'simplify' | 'acceptance' | 'ux-reviewer'> = [
'improve',
'technical',
'simplify',
'acceptance',
'ux-reviewer',
];
modes.forEach((mode) => {
const result = buildUserPrompt(mode, testText);
expect(result).toBeDefined();
expect(result).toContain(testText);
expect(result.length).toBeGreaterThan(testText.length);
});
});
});
});
describe('isValidEnhancementMode', () => {
it("should return true for 'improve'", () => {
expect(isValidEnhancementMode('improve')).toBe(true);
});
it("should return true for 'technical'", () => {
expect(isValidEnhancementMode('technical')).toBe(true);
});
it("should return true for 'simplify'", () => {
expect(isValidEnhancementMode('simplify')).toBe(true);
});
it("should return true for 'acceptance'", () => {
expect(isValidEnhancementMode('acceptance')).toBe(true);
});
it("should return true for 'ux-reviewer'", () => {
expect(isValidEnhancementMode('ux-reviewer')).toBe(true);
});
it('should return false for invalid mode', () => {
expect(isValidEnhancementMode('invalid')).toBe(false);
});
it('should return false for empty string', () => {
expect(isValidEnhancementMode('')).toBe(false);
});
it('should return false for uppercase mode', () => {
// Should be case-sensitive since we check object keys directly
expect(isValidEnhancementMode('IMPROVE')).toBe(false);
});
it('should return false for mixed case mode', () => {
expect(isValidEnhancementMode('ImProve')).toBe(false);
});
it('should return false for partial mode names', () => {
expect(isValidEnhancementMode('impro')).toBe(false);
expect(isValidEnhancementMode('tech')).toBe(false);
});
it('should return false for mode with extra characters', () => {
expect(isValidEnhancementMode('improve ')).toBe(false);
expect(isValidEnhancementMode(' improve')).toBe(false);
});
});
describe('getAvailableEnhancementModes', () => {
it('should return array of all enhancement modes', () => {
const modes = getAvailableEnhancementModes();
expect(Array.isArray(modes)).toBe(true);
expect(modes.length).toBe(5);
});
it('should include all valid modes', () => {
const modes = getAvailableEnhancementModes();
expect(modes).toContain('improve');
expect(modes).toContain('technical');
expect(modes).toContain('simplify');
expect(modes).toContain('acceptance');
expect(modes).toContain('ux-reviewer');
});
it('should return modes in consistent order', () => {
const modes1 = getAvailableEnhancementModes();
const modes2 = getAvailableEnhancementModes();
expect(modes1).toEqual(modes2);
});
it('should return all valid modes that pass isValidEnhancementMode', () => {
const modes = getAvailableEnhancementModes();
modes.forEach((mode) => {
expect(isValidEnhancementMode(mode)).toBe(true);
});
});
});
describe('Integration tests', () => {
it('should work together: getEnhancementPrompt + buildUserPrompt', () => {
const mode = 'improve';
const text = 'Add search feature';
const { systemPrompt, description } = getEnhancementPrompt(mode);
const userPrompt = buildUserPrompt(mode, text);
expect(systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(description).toBeDefined();
expect(userPrompt).toContain(text);
});
it('should handle complete enhancement workflow', () => {
const availableModes = getAvailableEnhancementModes();
expect(availableModes.length).toBeGreaterThan(0);
availableModes.forEach((mode) => {
const isValid = isValidEnhancementMode(mode);
expect(isValid).toBe(true);
const systemPrompt = getSystemPrompt(mode);
expect(systemPrompt).toBeDefined();
expect(systemPrompt.length).toBeGreaterThan(0);
const examples = getExamples(mode);
expect(Array.isArray(examples)).toBe(true);
expect(examples.length).toBeGreaterThan(0);
const userPrompt = buildUserPrompt(mode, 'test description');
expect(userPrompt).toContain('test description');
});
});
it('should provide consistent data across functions', () => {
const mode = 'technical';
const promptConfig = getEnhancementPrompt(mode);
const systemPrompt = getSystemPrompt(mode);
const examples = getExamples(mode);
expect(promptConfig.systemPrompt).toBe(systemPrompt);
expect(examples).toBe(TECHNICAL_EXAMPLES);
});
});
describe('Examples content validation', () => {
it('IMPROVE_EXAMPLES should demonstrate improvement', () => {
IMPROVE_EXAMPLES.forEach((example) => {
// Output should be longer and more detailed than input
expect(example.output.length).toBeGreaterThan(example.input.length);
// Input should be brief/vague
expect(example.input.length).toBeLessThan(100);
});
});
it('TECHNICAL_EXAMPLES should contain technical terms', () => {
const technicalTerms = [
'API',
'endpoint',
'component',
'database',
'frontend',
'backend',
'validation',
'schema',
'React',
'GET',
'PUT',
'POST',
];
TECHNICAL_EXAMPLES.forEach((example) => {
const hasAnyTechnicalTerm = technicalTerms.some((term) => example.output.includes(term));
expect(hasAnyTechnicalTerm).toBe(true);
});
});
it('ACCEPTANCE_EXAMPLES should contain acceptance criteria format', () => {
ACCEPTANCE_EXAMPLES.forEach((example) => {
// Should contain numbered criteria or Given-When-Then format
const hasAcceptanceCriteria =
example.output.includes('Acceptance Criteria') || example.output.match(/\d+\./g);
expect(hasAcceptanceCriteria).toBeTruthy();
// Should contain Given-When-Then format
const hasGWT =
example.output.includes('Given') &&
example.output.includes('when') &&
example.output.includes('then');
expect(hasGWT).toBe(true);
});
});
});
});