mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 09:19:42 +02:00
Codeman turns absolute paths in the terminal into links that open the file viewer, but agents usually report created files as relative paths, which cannot be clicked. The generated CLAUDE.md now asks for the full absolute path of every created file in the final reply, and says why relative, ~/ and markdown-link forms do not work. It also tells the agent about the codeman skill (start, prompt, wait on and clean up worker sessions) when the skill is available, and how the user can install it when it is not. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
175 lines
5.6 KiB
TypeScript
175 lines
5.6 KiB
TypeScript
/**
|
|
* @fileoverview Tests for template generation functions
|
|
*
|
|
* Tests the CLAUDE.md template generation including
|
|
* default template and custom template loading.
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { existsSync, writeFileSync, unlinkSync, mkdirSync, rmSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
import { generateClaudeMd } from '../src/templates/claude-md.js';
|
|
|
|
describe('generateClaudeMd', () => {
|
|
const testDir = join(tmpdir(), 'codeman-template-test-' + Date.now());
|
|
|
|
beforeEach(() => {
|
|
if (!existsSync(testDir)) {
|
|
mkdirSync(testDir, { recursive: true });
|
|
}
|
|
});
|
|
|
|
afterEach(() => {
|
|
try {
|
|
rmSync(testDir, { recursive: true, force: true });
|
|
} catch (e) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
describe('default template', () => {
|
|
it('should generate template with case name', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('**Project Name**: my-project');
|
|
});
|
|
|
|
it('should generate template with description', () => {
|
|
const result = generateClaudeMd('my-project', 'A test project description');
|
|
|
|
expect(result).toContain('**Description**: A test project description');
|
|
});
|
|
|
|
it('should use default description when not provided', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('**Description**: A new project');
|
|
});
|
|
|
|
it('should include current date', () => {
|
|
const today = new Date().toISOString().split('T')[0];
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain(`Generated by Codeman on ${today}`);
|
|
});
|
|
|
|
it('should include Codeman environment section', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('## Codeman Environment');
|
|
expect(result).toContain('CODEMAN_MUX=1');
|
|
});
|
|
|
|
it('should tell the agent to print absolute paths of files it creates', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('full absolute path');
|
|
expect(result).toContain('clickable');
|
|
});
|
|
|
|
it('should point the agent at the codeman skill', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('`codeman` skill');
|
|
expect(result).toContain('codeman skill install');
|
|
});
|
|
|
|
it('should include workflow rules', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).toContain('## Workflow');
|
|
expect(result).toContain('conventional commits');
|
|
});
|
|
|
|
it('should stay under the 200-line CLAUDE.md guidance', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result.split('\n').length).toBeLessThan(200);
|
|
});
|
|
|
|
it('should not include legacy bloat sections', () => {
|
|
const result = generateClaudeMd('my-project');
|
|
|
|
expect(result).not.toContain('## Session Log');
|
|
expect(result).not.toContain('TodoWrite');
|
|
expect(result).not.toContain('## Planning Mode');
|
|
expect(result).not.toContain('[TECHNOLOGIES_USED]');
|
|
// Ralph loop instructions live in the loop prompt (wizard) and plugin,
|
|
// not in every project's CLAUDE.md
|
|
expect(result).not.toContain('RALPH_STATUS');
|
|
expect(result).not.toContain('/ralph-loop:');
|
|
});
|
|
});
|
|
|
|
describe('custom template', () => {
|
|
it('should use custom template when provided and exists', () => {
|
|
const templatePath = join(testDir, 'custom-template.md');
|
|
writeFileSync(
|
|
templatePath,
|
|
`
|
|
# [PROJECT_NAME]
|
|
|
|
Description: [PROJECT_DESCRIPTION]
|
|
Date: [DATE]
|
|
|
|
Custom content here.
|
|
`
|
|
);
|
|
|
|
const result = generateClaudeMd('my-project', 'Test desc', templatePath);
|
|
|
|
expect(result).toContain('# my-project');
|
|
expect(result).toContain('Description: Test desc');
|
|
expect(result).toContain('Custom content here.');
|
|
});
|
|
|
|
it('should replace all placeholder occurrences', () => {
|
|
const templatePath = join(testDir, 'multi-placeholder.md');
|
|
writeFileSync(
|
|
templatePath,
|
|
`
|
|
[PROJECT_NAME] is a project.
|
|
The name is [PROJECT_NAME].
|
|
About [PROJECT_NAME]: [PROJECT_DESCRIPTION]
|
|
`
|
|
);
|
|
|
|
const result = generateClaudeMd('awesome-app', 'Cool stuff', templatePath);
|
|
|
|
expect(result).toContain('awesome-app is a project.');
|
|
expect(result).toContain('The name is awesome-app.');
|
|
expect(result).toContain('About awesome-app: Cool stuff');
|
|
});
|
|
|
|
it('should use default description in template when not provided', () => {
|
|
const templatePath = join(testDir, 'desc-template.md');
|
|
writeFileSync(templatePath, 'Description: [PROJECT_DESCRIPTION]');
|
|
|
|
const result = generateClaudeMd('my-project', '', templatePath);
|
|
|
|
expect(result).toContain('Description: A new project');
|
|
});
|
|
|
|
it('should fall back to default template if custom file does not exist', () => {
|
|
const result = generateClaudeMd('my-project', 'desc', '/nonexistent/template.md');
|
|
|
|
// Should get default template content
|
|
expect(result).toContain('## Codeman Environment');
|
|
expect(result).toContain('**Project Name**: my-project');
|
|
});
|
|
|
|
it('should fall back to default template if custom path is empty', () => {
|
|
const result = generateClaudeMd('my-project', 'desc', '');
|
|
|
|
expect(result).toContain('## Codeman Environment');
|
|
});
|
|
|
|
it('should fall back to default template if custom path is undefined', () => {
|
|
const result = generateClaudeMd('my-project', 'desc', undefined);
|
|
|
|
expect(result).toContain('## Codeman Environment');
|
|
});
|
|
});
|
|
});
|