import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, rmSync, cpSync, } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js'; import { createConfigService } from '../../src/config/config-service.js'; import { runWizard } from '../../src/wizard.js'; describe('Full Wizard (headless)', () => { let tmpDir: string; const repoRoot = join(import.meta.dirname, '..', '..'); beforeEach(() => { tmpDir = mkdtempSync(join(tmpdir(), 'mosaic-wizard-test-')); // Copy templates to tmp dir const templatesDir = join(repoRoot, 'templates'); if (existsSync(templatesDir)) { cpSync(templatesDir, join(tmpDir, 'templates'), { recursive: true }); } }); afterEach(() => { rmSync(tmpDir, { recursive: true, force: true }); }); it('quick start produces valid SOUL.md', async () => { const prompter = new HeadlessPrompter({ 'Installation mode': 'quick', 'What name should agents use?': 'TestBot', 'Communication style': 'direct', 'Your name': 'Tester', 'Your pronouns': 'They/Them', 'Your timezone': 'UTC', }); await runWizard({ mosaicHome: tmpDir, sourceDir: tmpDir, prompter, configService: createConfigService(tmpDir, tmpDir), }); const soulPath = join(tmpDir, 'SOUL.md'); expect(existsSync(soulPath)).toBe(true); const soul = readFileSync(soulPath, 'utf-8'); expect(soul).toContain('You are **TestBot**'); expect(soul).toContain('Be direct, concise, and concrete'); expect(soul).toContain('execution partner and visibility engine'); }); it('quick start produces valid USER.md', async () => { const prompter = new HeadlessPrompter({ 'Installation mode': 'quick', 'What name should agents use?': 'TestBot', 'Communication style': 'direct', 'Your name': 'Tester', 'Your pronouns': 'He/Him', 'Your timezone': 'America/Chicago', }); await runWizard({ mosaicHome: tmpDir, sourceDir: tmpDir, prompter, configService: createConfigService(tmpDir, tmpDir), }); const userPath = join(tmpDir, 'USER.md'); expect(existsSync(userPath)).toBe(true); const user = readFileSync(userPath, 'utf-8'); expect(user).toContain('**Name:** Tester'); expect(user).toContain('**Pronouns:** He/Him'); expect(user).toContain('**Timezone:** America/Chicago'); }); it('applies CLI overrides', async () => { const prompter = new HeadlessPrompter({ 'Installation mode': 'quick', 'Your name': 'FromPrompt', }); await runWizard({ mosaicHome: tmpDir, sourceDir: tmpDir, prompter, configService: createConfigService(tmpDir, tmpDir), cliOverrides: { soul: { agentName: 'FromCLI', communicationStyle: 'formal', }, }, }); const soul = readFileSync(join(tmpDir, 'SOUL.md'), 'utf-8'); expect(soul).toContain('You are **FromCLI**'); expect(soul).toContain('Use professional, structured language'); }); });