/** * @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 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'); }); }); });