beth-copilot 1.0.14 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +195 -177
- package/README.md +528 -185
- package/bin/cli.js +47 -0
- package/dist/cli/commands/doctor.e2e.test.d.ts +8 -0
- package/dist/cli/commands/doctor.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/doctor.e2e.test.js +428 -0
- package/dist/cli/commands/doctor.e2e.test.js.map +1 -0
- package/dist/cli/commands/doctor.test.js +1 -1
- package/dist/cli/commands/help.e2e.test.d.ts +9 -0
- package/dist/cli/commands/help.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/help.e2e.test.js +150 -0
- package/dist/cli/commands/help.e2e.test.js.map +1 -0
- package/dist/cli/commands/init.test.d.ts +6 -0
- package/dist/cli/commands/init.test.d.ts.map +1 -0
- package/dist/cli/commands/init.test.js +289 -0
- package/dist/cli/commands/init.test.js.map +1 -0
- package/dist/cli/commands/mcp.e2e.test.d.ts +9 -0
- package/dist/cli/commands/mcp.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/mcp.e2e.test.js +139 -0
- package/dist/cli/commands/mcp.e2e.test.js.map +1 -0
- package/dist/cli/commands/pipeline.e2e.test.d.ts +9 -0
- package/dist/cli/commands/pipeline.e2e.test.d.ts.map +1 -0
- package/dist/cli/commands/pipeline.e2e.test.js +192 -0
- package/dist/cli/commands/pipeline.e2e.test.js.map +1 -0
- package/dist/cli/commands/quickstart.test.d.ts +6 -0
- package/dist/cli/commands/quickstart.test.d.ts.map +1 -0
- package/dist/cli/commands/quickstart.test.js +232 -0
- package/dist/cli/commands/quickstart.test.js.map +1 -0
- package/dist/core/agents/frontmatter.test.d.ts +8 -0
- package/dist/core/agents/frontmatter.test.d.ts.map +1 -0
- package/dist/core/agents/frontmatter.test.js +589 -0
- package/dist/core/agents/frontmatter.test.js.map +1 -0
- package/dist/core/agents/handoffs.test.d.ts +8 -0
- package/dist/core/agents/handoffs.test.d.ts.map +1 -0
- package/dist/core/agents/handoffs.test.js +320 -0
- package/dist/core/agents/handoffs.test.js.map +1 -0
- package/dist/core/agents/loader.test.js +1 -1
- package/dist/core/agents/suite.test.d.ts +8 -0
- package/dist/core/agents/suite.test.d.ts.map +1 -0
- package/dist/core/agents/suite.test.js +207 -0
- package/dist/core/agents/suite.test.js.map +1 -0
- package/dist/core/agents/tools.test.d.ts +8 -0
- package/dist/core/agents/tools.test.d.ts.map +1 -0
- package/dist/core/agents/tools.test.js +332 -0
- package/dist/core/agents/tools.test.js.map +1 -0
- package/dist/core/context.d.ts +171 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +353 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/context.test.d.ts +8 -0
- package/dist/core/context.test.d.ts.map +1 -0
- package/dist/core/context.test.js +253 -0
- package/dist/core/context.test.js.map +1 -0
- package/dist/core/handoffs.d.ts +151 -0
- package/dist/core/handoffs.d.ts.map +1 -0
- package/dist/core/handoffs.js +220 -0
- package/dist/core/handoffs.js.map +1 -0
- package/dist/core/handoffs.test.d.ts +8 -0
- package/dist/core/handoffs.test.d.ts.map +1 -0
- package/dist/core/handoffs.test.js +231 -0
- package/dist/core/handoffs.test.js.map +1 -0
- package/dist/core/orchestrator.d.ts +246 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +514 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/orchestrator.test.d.ts +8 -0
- package/dist/core/orchestrator.test.d.ts.map +1 -0
- package/dist/core/orchestrator.test.js +517 -0
- package/dist/core/orchestrator.test.js.map +1 -0
- package/dist/core/router.d.ts +102 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +178 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/router.test.d.ts +8 -0
- package/dist/core/router.test.d.ts.map +1 -0
- package/dist/core/router.test.js +215 -0
- package/dist/core/router.test.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/init.test.js +288 -0
- package/dist/providers/azure.d.ts +147 -0
- package/dist/providers/azure.d.ts.map +1 -0
- package/dist/providers/azure.js +491 -0
- package/dist/providers/azure.js.map +1 -0
- package/dist/providers/azure.test.d.ts +11 -0
- package/dist/providers/azure.test.d.ts.map +1 -0
- package/dist/providers/azure.test.js +330 -0
- package/dist/providers/azure.test.js.map +1 -0
- package/dist/providers/config.d.ts +87 -0
- package/dist/providers/config.d.ts.map +1 -0
- package/dist/providers/config.js +193 -0
- package/dist/providers/config.js.map +1 -0
- package/dist/providers/config.test.d.ts +7 -0
- package/dist/providers/config.test.d.ts.map +1 -0
- package/dist/providers/config.test.js +370 -0
- package/dist/providers/config.test.js.map +1 -0
- package/dist/providers/index.d.ts +18 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +14 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/interface.d.ts +191 -0
- package/dist/providers/interface.d.ts.map +1 -0
- package/dist/providers/interface.js +94 -0
- package/dist/providers/interface.js.map +1 -0
- package/dist/providers/retry.d.ts +128 -0
- package/dist/providers/retry.d.ts.map +1 -0
- package/dist/providers/retry.js +205 -0
- package/dist/providers/retry.js.map +1 -0
- package/dist/providers/retry.test.d.ts +7 -0
- package/dist/providers/retry.test.d.ts.map +1 -0
- package/dist/providers/retry.test.js +439 -0
- package/dist/providers/retry.test.js.map +1 -0
- package/dist/providers/streaming.d.ts +157 -0
- package/dist/providers/streaming.d.ts.map +1 -0
- package/dist/providers/streaming.js +233 -0
- package/dist/providers/streaming.js.map +1 -0
- package/dist/providers/streaming.test.d.ts +7 -0
- package/dist/providers/streaming.test.d.ts.map +1 -0
- package/dist/providers/streaming.test.js +372 -0
- package/dist/providers/streaming.test.js.map +1 -0
- package/dist/providers/types.d.ts +209 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +53 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/providers/types.test.d.ts +7 -0
- package/dist/providers/types.test.d.ts.map +1 -0
- package/dist/providers/types.test.js +141 -0
- package/dist/providers/types.test.js.map +1 -0
- package/dist/tools/cli/beads.d.ts +27 -0
- package/dist/tools/cli/beads.d.ts.map +1 -0
- package/dist/tools/cli/beads.js +172 -0
- package/dist/tools/cli/beads.js.map +1 -0
- package/dist/tools/cli/beads.test.d.ts +8 -0
- package/dist/tools/cli/beads.test.d.ts.map +1 -0
- package/dist/tools/cli/beads.test.js +264 -0
- package/dist/tools/cli/beads.test.js.map +1 -0
- package/dist/tools/cli/editFile.d.ts +17 -0
- package/dist/tools/cli/editFile.d.ts.map +1 -0
- package/dist/tools/cli/editFile.js +125 -0
- package/dist/tools/cli/editFile.js.map +1 -0
- package/dist/tools/cli/editFile.test.d.ts +8 -0
- package/dist/tools/cli/editFile.test.d.ts.map +1 -0
- package/dist/tools/cli/editFile.test.js +177 -0
- package/dist/tools/cli/editFile.test.js.map +1 -0
- package/dist/tools/cli/readFile.d.ts +25 -0
- package/dist/tools/cli/readFile.d.ts.map +1 -0
- package/dist/tools/cli/readFile.js +118 -0
- package/dist/tools/cli/readFile.js.map +1 -0
- package/dist/tools/cli/readFile.test.d.ts +8 -0
- package/dist/tools/cli/readFile.test.d.ts.map +1 -0
- package/dist/tools/cli/readFile.test.js +194 -0
- package/dist/tools/cli/readFile.test.js.map +1 -0
- package/dist/tools/cli/search.d.ts +16 -0
- package/dist/tools/cli/search.d.ts.map +1 -0
- package/dist/tools/cli/search.js +261 -0
- package/dist/tools/cli/search.js.map +1 -0
- package/dist/tools/cli/search.test.d.ts +8 -0
- package/dist/tools/cli/search.test.d.ts.map +1 -0
- package/dist/tools/cli/search.test.js +172 -0
- package/dist/tools/cli/search.test.js.map +1 -0
- package/dist/tools/cli/subagent.d.ts +43 -0
- package/dist/tools/cli/subagent.d.ts.map +1 -0
- package/dist/tools/cli/subagent.js +99 -0
- package/dist/tools/cli/subagent.js.map +1 -0
- package/dist/tools/cli/subagent.test.d.ts +8 -0
- package/dist/tools/cli/subagent.test.d.ts.map +1 -0
- package/dist/tools/cli/subagent.test.js +190 -0
- package/dist/tools/cli/subagent.test.js.map +1 -0
- package/dist/tools/cli/terminal.d.ts +19 -0
- package/dist/tools/cli/terminal.d.ts.map +1 -0
- package/dist/tools/cli/terminal.js +164 -0
- package/dist/tools/cli/terminal.js.map +1 -0
- package/dist/tools/cli/terminal.test.d.ts +8 -0
- package/dist/tools/cli/terminal.test.d.ts.map +1 -0
- package/dist/tools/cli/terminal.test.js +161 -0
- package/dist/tools/cli/terminal.test.js.map +1 -0
- package/dist/tools/index.d.ts +25 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +41 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/interface.d.ts +64 -0
- package/dist/tools/interface.d.ts.map +1 -0
- package/dist/tools/interface.js +37 -0
- package/dist/tools/interface.js.map +1 -0
- package/dist/tools/interface.test.d.ts +7 -0
- package/dist/tools/interface.test.d.ts.map +1 -0
- package/dist/tools/interface.test.js +179 -0
- package/dist/tools/interface.test.js.map +1 -0
- package/dist/tools/mcp/bridge.d.ts +48 -0
- package/dist/tools/mcp/bridge.d.ts.map +1 -0
- package/dist/tools/mcp/bridge.js +128 -0
- package/dist/tools/mcp/bridge.js.map +1 -0
- package/dist/tools/mcp/bridge.test.d.ts +8 -0
- package/dist/tools/mcp/bridge.test.d.ts.map +1 -0
- package/dist/tools/mcp/bridge.test.js +300 -0
- package/dist/tools/mcp/bridge.test.js.map +1 -0
- package/dist/tools/mcp/client.d.ts +135 -0
- package/dist/tools/mcp/client.d.ts.map +1 -0
- package/dist/tools/mcp/client.js +263 -0
- package/dist/tools/mcp/client.js.map +1 -0
- package/dist/tools/mcp/client.test.d.ts +8 -0
- package/dist/tools/mcp/client.test.d.ts.map +1 -0
- package/dist/tools/mcp/client.test.js +390 -0
- package/dist/tools/mcp/client.test.js.map +1 -0
- package/dist/tools/registry.d.ts +82 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +99 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/registry.test.d.ts +7 -0
- package/dist/tools/registry.test.d.ts.map +1 -0
- package/dist/tools/registry.test.js +199 -0
- package/dist/tools/registry.test.js.map +1 -0
- package/dist/tools/suite.test.d.ts +11 -0
- package/dist/tools/suite.test.d.ts.map +1 -0
- package/dist/tools/suite.test.js +119 -0
- package/dist/tools/suite.test.js.map +1 -0
- package/dist/tools/types.d.ts +75 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +30 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/types.test.d.ts +7 -0
- package/dist/tools/types.test.d.ts.map +1 -0
- package/dist/tools/types.test.js +178 -0
- package/dist/tools/types.test.js.map +1 -0
- package/package.json +60 -56
- package/sbom.json +3302 -8
- package/templates/.github/agents/beth.agent.md +329 -329
- package/templates/.github/agents/developer.agent.md +572 -572
- package/templates/.github/agents/product-manager.agent.md +272 -272
- package/templates/.github/agents/researcher.agent.md +338 -338
- package/templates/.github/agents/security-reviewer.agent.md +465 -465
- package/templates/.github/agents/tester.agent.md +496 -496
- package/templates/.github/agents/ux-designer.agent.md +393 -393
- package/templates/mcp.json.example +4 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E tests for the help command.
|
|
3
|
+
* Run with: node --test dist/cli/commands/help.e2e.test.js
|
|
4
|
+
*
|
|
5
|
+
* Validates that `npx beth-copilot help` shows all available commands,
|
|
6
|
+
* options, and what gets installed.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it } from 'node:test';
|
|
9
|
+
import assert from 'node:assert';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
import { join, resolve } from 'path';
|
|
12
|
+
const CLI_PATH = resolve(join(import.meta.dirname, '..', '..', '..', 'bin', 'cli.js'));
|
|
13
|
+
/**
|
|
14
|
+
* Run a CLI command and capture output.
|
|
15
|
+
*/
|
|
16
|
+
function runCli(args) {
|
|
17
|
+
try {
|
|
18
|
+
const stdout = execSync(`node "${CLI_PATH}" ${args}`, {
|
|
19
|
+
encoding: 'utf-8',
|
|
20
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
21
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
22
|
+
});
|
|
23
|
+
return { stdout, stderr: '', code: 0 };
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const e = error;
|
|
27
|
+
return { stdout: e.stdout || '', stderr: e.stderr || '', code: e.status || 1 };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
describe('help command E2E', () => {
|
|
31
|
+
describe('invocation methods', () => {
|
|
32
|
+
it('should show help with "help" command', () => {
|
|
33
|
+
const result = runCli('help');
|
|
34
|
+
assert.strictEqual(result.code, 0, 'help should exit with code 0');
|
|
35
|
+
assert.ok(result.stdout.includes('Beth'), 'Should mention Beth');
|
|
36
|
+
});
|
|
37
|
+
it('should show help with "--help" flag', () => {
|
|
38
|
+
const result = runCli('--help');
|
|
39
|
+
assert.strictEqual(result.code, 0, '--help should exit with code 0');
|
|
40
|
+
assert.ok(result.stdout.includes('Beth'), 'Should mention Beth');
|
|
41
|
+
});
|
|
42
|
+
it('should show help with "-h" flag', () => {
|
|
43
|
+
const result = runCli('-h');
|
|
44
|
+
assert.strictEqual(result.code, 0, '-h should exit with code 0');
|
|
45
|
+
assert.ok(result.stdout.includes('Beth'), 'Should mention Beth');
|
|
46
|
+
});
|
|
47
|
+
it('should show help when run with no command', () => {
|
|
48
|
+
const result = runCli('');
|
|
49
|
+
assert.strictEqual(result.code, 0, 'No command should show help and exit 0');
|
|
50
|
+
assert.ok(result.stdout.includes('Beth'), 'Should mention Beth');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('all CLI commands listed', () => {
|
|
54
|
+
it('should list the init command', () => {
|
|
55
|
+
const result = runCli('help');
|
|
56
|
+
assert.ok(result.stdout.includes('init'), 'Help should list the init command');
|
|
57
|
+
});
|
|
58
|
+
it('should list the doctor command', () => {
|
|
59
|
+
const result = runCli('help');
|
|
60
|
+
assert.ok(result.stdout.includes('doctor'), 'Help should list the doctor command');
|
|
61
|
+
});
|
|
62
|
+
it('should list the quickstart command', () => {
|
|
63
|
+
const result = runCli('help');
|
|
64
|
+
assert.ok(result.stdout.includes('quickstart'), 'Help should list the quickstart command');
|
|
65
|
+
});
|
|
66
|
+
it('should list the help command', () => {
|
|
67
|
+
const result = runCli('help');
|
|
68
|
+
assert.ok(result.stdout.includes('help'), 'Help should list the help command');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('CLI options listed', () => {
|
|
72
|
+
it('should list --force option', () => {
|
|
73
|
+
const result = runCli('help');
|
|
74
|
+
assert.ok(result.stdout.includes('--force'), 'Help should list --force option');
|
|
75
|
+
});
|
|
76
|
+
it('should list --skip-backlog option', () => {
|
|
77
|
+
const result = runCli('help');
|
|
78
|
+
assert.ok(result.stdout.includes('--skip-backlog'), 'Help should list --skip-backlog option');
|
|
79
|
+
});
|
|
80
|
+
it('should list --skip-mcp option', () => {
|
|
81
|
+
const result = runCli('help');
|
|
82
|
+
assert.ok(result.stdout.includes('--skip-mcp'), 'Help should list --skip-mcp option');
|
|
83
|
+
});
|
|
84
|
+
it('should list --skip-beads option', () => {
|
|
85
|
+
const result = runCli('help');
|
|
86
|
+
assert.ok(result.stdout.includes('--skip-beads'), 'Help should list --skip-beads option');
|
|
87
|
+
});
|
|
88
|
+
it('should list --verbose option', () => {
|
|
89
|
+
const result = runCli('help');
|
|
90
|
+
assert.ok(result.stdout.includes('--verbose'), 'Help should list --verbose option');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('installation contents documented', () => {
|
|
94
|
+
it('should mention agents directory', () => {
|
|
95
|
+
const result = runCli('help');
|
|
96
|
+
assert.ok(result.stdout.includes('.github/agents') || result.stdout.includes('agents'), 'Help should document that agents get installed');
|
|
97
|
+
});
|
|
98
|
+
it('should mention skills directory', () => {
|
|
99
|
+
const result = runCli('help');
|
|
100
|
+
assert.ok(result.stdout.includes('.github/skills') || result.stdout.includes('skills'), 'Help should document that skills get installed');
|
|
101
|
+
});
|
|
102
|
+
it('should mention MCP config', () => {
|
|
103
|
+
const result = runCli('help');
|
|
104
|
+
assert.ok(result.stdout.includes('mcp.json') || result.stdout.includes('MCP'), 'Help should document MCP server config');
|
|
105
|
+
});
|
|
106
|
+
it('should mention AGENTS.md', () => {
|
|
107
|
+
const result = runCli('help');
|
|
108
|
+
assert.ok(result.stdout.includes('AGENTS.md'), 'Help should document AGENTS.md');
|
|
109
|
+
});
|
|
110
|
+
it('should mention copilot-instructions.md', () => {
|
|
111
|
+
const result = runCli('help');
|
|
112
|
+
assert.ok(result.stdout.includes('copilot-instructions'), 'Help should document copilot-instructions.md');
|
|
113
|
+
});
|
|
114
|
+
it('should mention VS Code settings', () => {
|
|
115
|
+
const result = runCli('help');
|
|
116
|
+
assert.ok(result.stdout.includes('settings.json') || result.stdout.includes('.vscode'), 'Help should document VS Code settings');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('post-install guidance', () => {
|
|
120
|
+
it('should mention VS Code as the target editor', () => {
|
|
121
|
+
const result = runCli('help');
|
|
122
|
+
assert.ok(result.stdout.includes('VS Code'), 'Help should mention VS Code');
|
|
123
|
+
});
|
|
124
|
+
it('should mention Copilot Chat', () => {
|
|
125
|
+
const result = runCli('help');
|
|
126
|
+
assert.ok(result.stdout.includes('Copilot Chat'), 'Help should mention Copilot Chat');
|
|
127
|
+
});
|
|
128
|
+
it('should mention @Beth as the entry point', () => {
|
|
129
|
+
const result = runCli('help');
|
|
130
|
+
assert.ok(result.stdout.includes('@Beth'), 'Help should mention @Beth as the entry point to the agent system');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('unknown command handling', () => {
|
|
134
|
+
it('should show error for unknown command', () => {
|
|
135
|
+
const result = runCli('foobar');
|
|
136
|
+
assert.strictEqual(result.code, 1, 'Unknown command should exit with code 1');
|
|
137
|
+
assert.ok(result.stdout.includes('Unknown command') || result.stderr.includes('Unknown command'), 'Should indicate unknown command');
|
|
138
|
+
});
|
|
139
|
+
it('should suggest help for unknown command', () => {
|
|
140
|
+
const result = runCli('foobar');
|
|
141
|
+
assert.ok(result.stdout.includes('help') || result.stderr.includes('help'), 'Should suggest running help');
|
|
142
|
+
});
|
|
143
|
+
it('should reject unknown flags', () => {
|
|
144
|
+
const result = runCli('init --nonexistent');
|
|
145
|
+
assert.strictEqual(result.code, 1, 'Unknown flag should exit with code 1');
|
|
146
|
+
assert.ok(result.stdout.includes('Unknown flag') || result.stderr.includes('Unknown flag'), 'Should indicate unknown flag');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
//# sourceMappingURL=help.e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.e2e.test.js","sourceRoot":"","sources":["../../../src/cli/commands/help.e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEvF;;GAEG;AACH,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,QAAQ,KAAK,IAAI,EAAE,EAAE;YACpD,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE;YACtC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACzC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,KAA8D,CAAC;QACzE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IACjF,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,8BAA8B,CAAC,CAAC;YACnE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,gCAAgC,CAAC,CAAC;YACrE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,4BAA4B,CAAC,CAAC;YACjE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,wCAAwC,CAAC,CAAC;YAC7E,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC9B,mCAAmC,CACpC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAChC,qCAAqC,CACtC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EACpC,yCAAyC,CAC1C,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC9B,mCAAmC,CACpC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EACjC,iCAAiC,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EACxC,wCAAwC,CACzC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EACpC,oCAAoC,CACrC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EACtC,sCAAsC,CACvC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC,mCAAmC,CACpC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAC5E,gDAAgD,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAC5E,gDAAgD,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EACnE,wCAAwC,CACzC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC,gCAAgC,CACjC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC9C,8CAA8C,CAC/C,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAC5E,uCAAuC,CACxC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EACjC,6BAA6B,CAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EACtC,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAC/B,kEAAkE,CACnE,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,yCAAyC,CAAC,CAAC;YAC9E,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EACtF,iCAAiC,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAChE,6BAA6B,CAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,MAAM,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,sCAAsC,CAAC,CAAC;YAC3E,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAChF,8BAA8B,CAC/B,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E tests for init command.
|
|
3
|
+
* Run with: node --test dist/cli/commands/init.test.js
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync, readdirSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { tmpdir } from 'os';
|
|
11
|
+
// Expected files and directories from templates
|
|
12
|
+
const EXPECTED_AGENTS = [
|
|
13
|
+
'beth.agent.md',
|
|
14
|
+
'developer.agent.md',
|
|
15
|
+
'product-manager.agent.md',
|
|
16
|
+
'researcher.agent.md',
|
|
17
|
+
'security-reviewer.agent.md',
|
|
18
|
+
'tester.agent.md',
|
|
19
|
+
'ux-designer.agent.md',
|
|
20
|
+
];
|
|
21
|
+
const EXPECTED_SKILLS = [
|
|
22
|
+
'framer-components',
|
|
23
|
+
'prd',
|
|
24
|
+
'security-analysis',
|
|
25
|
+
'shadcn-ui',
|
|
26
|
+
'vercel-react-best-practices',
|
|
27
|
+
'web-design-guidelines',
|
|
28
|
+
];
|
|
29
|
+
// Path to CLI binary
|
|
30
|
+
const CLI_PATH = join(process.cwd(), 'bin', 'cli.js');
|
|
31
|
+
/**
|
|
32
|
+
* Run the init command in a specified directory.
|
|
33
|
+
* Uses --skip-beads to avoid interactive prompts during testing.
|
|
34
|
+
*/
|
|
35
|
+
function runInit(cwd, flags = []) {
|
|
36
|
+
// Always include --skip-beads to avoid interactive prompts
|
|
37
|
+
const allFlags = ['--skip-beads', ...flags];
|
|
38
|
+
const command = `node "${CLI_PATH}" init ${allFlags.join(' ')}`;
|
|
39
|
+
try {
|
|
40
|
+
const stdout = execSync(command, {
|
|
41
|
+
cwd,
|
|
42
|
+
encoding: 'utf-8',
|
|
43
|
+
env: { ...process.env, NO_COLOR: '1' }, // Disable colors and animations
|
|
44
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
+
});
|
|
46
|
+
return { stdout, stderr: '', exitCode: 0 };
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const execError = error;
|
|
50
|
+
return {
|
|
51
|
+
stdout: execError.stdout || '',
|
|
52
|
+
stderr: execError.stderr || '',
|
|
53
|
+
exitCode: execError.status || 1,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
describe('init command E2E', () => {
|
|
58
|
+
let testDir;
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
// Create a temp directory for each test
|
|
61
|
+
testDir = join(tmpdir(), `beth-init-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
62
|
+
mkdirSync(testDir, { recursive: true });
|
|
63
|
+
});
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
// Clean up temp directory
|
|
66
|
+
if (existsSync(testDir)) {
|
|
67
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
describe('directory structure creation', () => {
|
|
71
|
+
it('should create .github/agents directory with all 7 agent files', () => {
|
|
72
|
+
runInit(testDir);
|
|
73
|
+
const agentsDir = join(testDir, '.github', 'agents');
|
|
74
|
+
assert.strictEqual(existsSync(agentsDir), true, '.github/agents directory should exist');
|
|
75
|
+
const files = readdirSync(agentsDir).filter(f => f.endsWith('.agent.md')).sort();
|
|
76
|
+
assert.deepStrictEqual(files, EXPECTED_AGENTS, 'All 7 agent files should be created');
|
|
77
|
+
});
|
|
78
|
+
it('should create .github/skills directory with all skill directories', () => {
|
|
79
|
+
runInit(testDir);
|
|
80
|
+
const skillsDir = join(testDir, '.github', 'skills');
|
|
81
|
+
assert.strictEqual(existsSync(skillsDir), true, '.github/skills directory should exist');
|
|
82
|
+
const dirs = readdirSync(skillsDir).filter(f => {
|
|
83
|
+
return existsSync(join(skillsDir, f, 'SKILL.md')) ||
|
|
84
|
+
existsSync(join(skillsDir, f, 'AGENTS.md'));
|
|
85
|
+
}).sort();
|
|
86
|
+
assert.deepStrictEqual(dirs, EXPECTED_SKILLS, 'All skill directories should be created');
|
|
87
|
+
});
|
|
88
|
+
it('should create AGENTS.md in project root', () => {
|
|
89
|
+
runInit(testDir);
|
|
90
|
+
const agentsMd = join(testDir, 'AGENTS.md');
|
|
91
|
+
assert.strictEqual(existsSync(agentsMd), true, 'AGENTS.md should exist');
|
|
92
|
+
const content = readFileSync(agentsMd, 'utf-8');
|
|
93
|
+
assert.ok(content.includes('beads'), 'AGENTS.md should mention beads');
|
|
94
|
+
});
|
|
95
|
+
it('should create Backlog.md in project root', () => {
|
|
96
|
+
runInit(testDir);
|
|
97
|
+
const backlogMd = join(testDir, 'Backlog.md');
|
|
98
|
+
assert.strictEqual(existsSync(backlogMd), true, 'Backlog.md should exist');
|
|
99
|
+
});
|
|
100
|
+
it('should create mcp.json.example in project root', () => {
|
|
101
|
+
runInit(testDir);
|
|
102
|
+
const mcpJson = join(testDir, 'mcp.json.example');
|
|
103
|
+
assert.strictEqual(existsSync(mcpJson), true, 'mcp.json.example should exist');
|
|
104
|
+
});
|
|
105
|
+
it('should create .vscode/settings.json', () => {
|
|
106
|
+
runInit(testDir);
|
|
107
|
+
const settingsJson = join(testDir, '.vscode', 'settings.json');
|
|
108
|
+
assert.strictEqual(existsSync(settingsJson), true, '.vscode/settings.json should exist');
|
|
109
|
+
});
|
|
110
|
+
it('should create copilot-instructions.md in .github', () => {
|
|
111
|
+
runInit(testDir);
|
|
112
|
+
const copilotInstructions = join(testDir, '.github', 'copilot-instructions.md');
|
|
113
|
+
assert.strictEqual(existsSync(copilotInstructions), true, '.github/copilot-instructions.md should exist');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('--force flag', () => {
|
|
117
|
+
it('should overwrite existing files when --force is used', () => {
|
|
118
|
+
// Create existing AGENTS.md with different content
|
|
119
|
+
const agentsMd = join(testDir, 'AGENTS.md');
|
|
120
|
+
writeFileSync(agentsMd, 'ORIGINAL CONTENT');
|
|
121
|
+
// Run init without --force
|
|
122
|
+
runInit(testDir);
|
|
123
|
+
let content = readFileSync(agentsMd, 'utf-8');
|
|
124
|
+
assert.strictEqual(content, 'ORIGINAL CONTENT', 'Should not overwrite without --force');
|
|
125
|
+
// Run init with --force
|
|
126
|
+
runInit(testDir, ['--force']);
|
|
127
|
+
content = readFileSync(agentsMd, 'utf-8');
|
|
128
|
+
assert.notStrictEqual(content, 'ORIGINAL CONTENT', 'Should overwrite with --force');
|
|
129
|
+
assert.ok(content.includes('beads'), 'Content should be from template');
|
|
130
|
+
});
|
|
131
|
+
it('should overwrite existing agent files with --force', () => {
|
|
132
|
+
// Create existing .github/agents directory with modified file
|
|
133
|
+
const agentsDir = join(testDir, '.github', 'agents');
|
|
134
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
135
|
+
const bethAgent = join(agentsDir, 'beth.agent.md');
|
|
136
|
+
writeFileSync(bethAgent, 'MODIFIED BETH');
|
|
137
|
+
// Run init without --force
|
|
138
|
+
runInit(testDir);
|
|
139
|
+
let content = readFileSync(bethAgent, 'utf-8');
|
|
140
|
+
assert.strictEqual(content, 'MODIFIED BETH', 'Should not overwrite without --force');
|
|
141
|
+
// Run init with --force
|
|
142
|
+
runInit(testDir, ['--force']);
|
|
143
|
+
content = readFileSync(bethAgent, 'utf-8');
|
|
144
|
+
assert.notStrictEqual(content, 'MODIFIED BETH', 'Should overwrite with --force');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
describe('--skip-backlog flag', () => {
|
|
148
|
+
it('should not create Backlog.md when --skip-backlog is used', () => {
|
|
149
|
+
runInit(testDir, ['--skip-backlog']);
|
|
150
|
+
const backlogMd = join(testDir, 'Backlog.md');
|
|
151
|
+
assert.strictEqual(existsSync(backlogMd), false, 'Backlog.md should not exist');
|
|
152
|
+
});
|
|
153
|
+
it('should still create other files when --skip-backlog is used', () => {
|
|
154
|
+
runInit(testDir, ['--skip-backlog']);
|
|
155
|
+
assert.strictEqual(existsSync(join(testDir, 'AGENTS.md')), true, 'AGENTS.md should exist');
|
|
156
|
+
assert.strictEqual(existsSync(join(testDir, 'mcp.json.example')), true, 'mcp.json.example should exist');
|
|
157
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, '.github/agents should exist');
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe('--skip-mcp flag', () => {
|
|
161
|
+
it('should not create mcp.json.example when --skip-mcp is used', () => {
|
|
162
|
+
runInit(testDir, ['--skip-mcp']);
|
|
163
|
+
const mcpJson = join(testDir, 'mcp.json.example');
|
|
164
|
+
assert.strictEqual(existsSync(mcpJson), false, 'mcp.json.example should not exist');
|
|
165
|
+
});
|
|
166
|
+
it('should still create other files when --skip-mcp is used', () => {
|
|
167
|
+
runInit(testDir, ['--skip-mcp']);
|
|
168
|
+
assert.strictEqual(existsSync(join(testDir, 'AGENTS.md')), true, 'AGENTS.md should exist');
|
|
169
|
+
assert.strictEqual(existsSync(join(testDir, 'Backlog.md')), true, 'Backlog.md should exist');
|
|
170
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, '.github/agents should exist');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('--skip-beads flag', () => {
|
|
174
|
+
it('should complete without beads check when --skip-beads is used', () => {
|
|
175
|
+
const result = runInit(testDir);
|
|
176
|
+
// Should complete successfully (exit 0)
|
|
177
|
+
assert.strictEqual(result.exitCode, 0, 'Should exit with code 0');
|
|
178
|
+
// Should have created files
|
|
179
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, 'Should create agents');
|
|
180
|
+
});
|
|
181
|
+
it('should show warning about skipping beads', () => {
|
|
182
|
+
const result = runInit(testDir);
|
|
183
|
+
// Output should mention skipping beads
|
|
184
|
+
assert.ok(result.stdout.includes('Skipped beads check') || result.stdout.includes('skip-beads'), 'Should warn about skipping beads');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
describe('existing files handling', () => {
|
|
188
|
+
it('should warn about existing files without --force', () => {
|
|
189
|
+
// Create existing file
|
|
190
|
+
writeFileSync(join(testDir, 'AGENTS.md'), 'EXISTING');
|
|
191
|
+
const result = runInit(testDir);
|
|
192
|
+
assert.ok(result.stdout.includes('Skipped') || result.stdout.includes('exists'), 'Should mention that file was skipped');
|
|
193
|
+
});
|
|
194
|
+
it('should not overwrite existing files without --force', () => {
|
|
195
|
+
const agentsMd = join(testDir, 'AGENTS.md');
|
|
196
|
+
writeFileSync(agentsMd, 'ORIGINAL');
|
|
197
|
+
runInit(testDir);
|
|
198
|
+
const content = readFileSync(agentsMd, 'utf-8');
|
|
199
|
+
assert.strictEqual(content, 'ORIGINAL', 'Should preserve original content');
|
|
200
|
+
});
|
|
201
|
+
it('should count files correctly when some are skipped', () => {
|
|
202
|
+
// Create some existing files
|
|
203
|
+
writeFileSync(join(testDir, 'AGENTS.md'), 'EXISTING');
|
|
204
|
+
writeFileSync(join(testDir, 'Backlog.md'), 'EXISTING');
|
|
205
|
+
const result = runInit(testDir);
|
|
206
|
+
// Should have installed some files but not all
|
|
207
|
+
assert.ok(result.stdout.includes('Installed'), 'Should report installed files');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
describe('empty directory behavior', () => {
|
|
211
|
+
it('should work correctly in an empty directory', () => {
|
|
212
|
+
const result = runInit(testDir);
|
|
213
|
+
assert.strictEqual(result.exitCode, 0, 'Should exit with code 0');
|
|
214
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, '.github/agents should exist');
|
|
215
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'skills')), true, '.github/skills should exist');
|
|
216
|
+
assert.strictEqual(existsSync(join(testDir, 'AGENTS.md')), true, 'AGENTS.md should exist');
|
|
217
|
+
});
|
|
218
|
+
it('should install all expected files in empty directory', () => {
|
|
219
|
+
runInit(testDir);
|
|
220
|
+
// Check all expected files exist
|
|
221
|
+
const agentsDir = join(testDir, '.github', 'agents');
|
|
222
|
+
const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.agent.md'));
|
|
223
|
+
assert.strictEqual(agentFiles.length, 7, 'Should create 7 agent files');
|
|
224
|
+
const skillsDir = join(testDir, '.github', 'skills');
|
|
225
|
+
const skillDirs = readdirSync(skillsDir);
|
|
226
|
+
assert.strictEqual(skillDirs.length, 6, 'Should create 6 skill directories');
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
describe('existing .github folder behavior', () => {
|
|
230
|
+
it('should work in directory with existing .github folder', () => {
|
|
231
|
+
// Create existing .github folder with some content
|
|
232
|
+
const existingGithub = join(testDir, '.github', 'workflows');
|
|
233
|
+
mkdirSync(existingGithub, { recursive: true });
|
|
234
|
+
writeFileSync(join(existingGithub, 'ci.yml'), 'name: CI');
|
|
235
|
+
const result = runInit(testDir);
|
|
236
|
+
assert.strictEqual(result.exitCode, 0, 'Should exit with code 0');
|
|
237
|
+
// Should preserve existing content
|
|
238
|
+
assert.strictEqual(existsSync(join(existingGithub, 'ci.yml')), true, 'Should preserve existing .github/workflows/ci.yml');
|
|
239
|
+
// Should add new content
|
|
240
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, 'Should create .github/agents');
|
|
241
|
+
});
|
|
242
|
+
it('should merge with existing .github/agents folder', () => {
|
|
243
|
+
// Create existing agents folder with custom agent
|
|
244
|
+
const agentsDir = join(testDir, '.github', 'agents');
|
|
245
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
246
|
+
writeFileSync(join(agentsDir, 'custom.agent.md'), 'CUSTOM AGENT');
|
|
247
|
+
runInit(testDir);
|
|
248
|
+
// Should preserve custom agent
|
|
249
|
+
assert.strictEqual(existsSync(join(agentsDir, 'custom.agent.md')), true, 'Should preserve custom.agent.md');
|
|
250
|
+
// Custom agent content should be unchanged
|
|
251
|
+
const customContent = readFileSync(join(agentsDir, 'custom.agent.md'), 'utf-8');
|
|
252
|
+
assert.strictEqual(customContent, 'CUSTOM AGENT', 'Custom agent content preserved');
|
|
253
|
+
// Should have added Beth agents (they don't exist yet)
|
|
254
|
+
assert.strictEqual(existsSync(join(agentsDir, 'beth.agent.md')), true, 'Should create beth.agent.md');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('multiple flag combinations', () => {
|
|
258
|
+
it('should handle --skip-backlog and --skip-mcp together', () => {
|
|
259
|
+
runInit(testDir, ['--skip-backlog', '--skip-mcp']);
|
|
260
|
+
assert.strictEqual(existsSync(join(testDir, 'Backlog.md')), false, 'Backlog.md should not exist');
|
|
261
|
+
assert.strictEqual(existsSync(join(testDir, 'mcp.json.example')), false, 'mcp.json.example should not exist');
|
|
262
|
+
assert.strictEqual(existsSync(join(testDir, 'AGENTS.md')), true, 'AGENTS.md should exist');
|
|
263
|
+
assert.strictEqual(existsSync(join(testDir, '.github', 'agents')), true, '.github/agents should exist');
|
|
264
|
+
});
|
|
265
|
+
it('should handle --force with skip flags', () => {
|
|
266
|
+
// Create existing file
|
|
267
|
+
writeFileSync(join(testDir, 'AGENTS.md'), 'ORIGINAL');
|
|
268
|
+
runInit(testDir, ['--force', '--skip-backlog', '--skip-mcp']);
|
|
269
|
+
// Force should overwrite
|
|
270
|
+
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
271
|
+
assert.notStrictEqual(content, 'ORIGINAL', 'Should overwrite with --force');
|
|
272
|
+
// Skip flags should still work
|
|
273
|
+
assert.strictEqual(existsSync(join(testDir, 'Backlog.md')), false, 'Backlog.md should not exist');
|
|
274
|
+
assert.strictEqual(existsSync(join(testDir, 'mcp.json.example')), false, 'mcp.json.example should not exist');
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
describe('output messages', () => {
|
|
278
|
+
it('should report number of installed files', () => {
|
|
279
|
+
const result = runInit(testDir);
|
|
280
|
+
assert.ok(result.stdout.includes('Installed'), 'Should mention installed files');
|
|
281
|
+
assert.ok(/Installed \d+ files/.test(result.stdout), 'Should report file count');
|
|
282
|
+
});
|
|
283
|
+
it('should show next steps after installation', () => {
|
|
284
|
+
const result = runInit(testDir);
|
|
285
|
+
assert.ok(result.stdout.includes('Next steps') || result.stdout.includes('VS Code'), 'Should show next steps');
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
//# sourceMappingURL=init.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../../src/cli/commands/init.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E tests for MCP configuration validation.
|
|
3
|
+
* Run with: node --test dist/cli/commands/mcp.e2e.test.js
|
|
4
|
+
*
|
|
5
|
+
* Validates that mcp.json.example is valid JSON, has expected structure,
|
|
6
|
+
* and that init correctly copies it to target projects.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=mcp.e2e.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.e2e.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/mcp.e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E tests for MCP configuration validation.
|
|
3
|
+
* Run with: node --test dist/cli/commands/mcp.e2e.test.js
|
|
4
|
+
*
|
|
5
|
+
* Validates that mcp.json.example is valid JSON, has expected structure,
|
|
6
|
+
* and that init correctly copies it to target projects.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
9
|
+
import assert from 'node:assert';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
import { existsSync, mkdirSync, rmSync, readFileSync, writeFileSync } from 'fs';
|
|
12
|
+
import { join, resolve } from 'path';
|
|
13
|
+
import { tmpdir } from 'os';
|
|
14
|
+
// Paths
|
|
15
|
+
const PROJECT_ROOT = resolve(join(import.meta.dirname, '..', '..', '..'));
|
|
16
|
+
const CLI_PATH = join(PROJECT_ROOT, 'bin', 'cli.js');
|
|
17
|
+
const TEMPLATE_MCP = join(PROJECT_ROOT, 'templates', 'mcp.json.example');
|
|
18
|
+
/**
|
|
19
|
+
* Run init command in a directory (with --skip-beads to avoid interactive prompts).
|
|
20
|
+
*/
|
|
21
|
+
function runInit(cwd, flags = []) {
|
|
22
|
+
const allFlags = ['--skip-beads', ...flags];
|
|
23
|
+
const command = `node "${CLI_PATH}" init ${allFlags.join(' ')}`;
|
|
24
|
+
try {
|
|
25
|
+
const stdout = execSync(command, {
|
|
26
|
+
cwd,
|
|
27
|
+
encoding: 'utf-8',
|
|
28
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
29
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
30
|
+
});
|
|
31
|
+
return { stdout, stderr: '', exitCode: 0 };
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const execError = error;
|
|
35
|
+
return {
|
|
36
|
+
stdout: execError.stdout || '',
|
|
37
|
+
stderr: execError.stderr || '',
|
|
38
|
+
exitCode: execError.status || 1,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
describe('MCP configuration validation', () => {
|
|
43
|
+
describe('template mcp.json.example', () => {
|
|
44
|
+
it('should exist in templates directory', () => {
|
|
45
|
+
assert.ok(existsSync(TEMPLATE_MCP), `mcp.json.example should exist at ${TEMPLATE_MCP}`);
|
|
46
|
+
});
|
|
47
|
+
it('should be valid JSON', () => {
|
|
48
|
+
const content = readFileSync(TEMPLATE_MCP, 'utf-8');
|
|
49
|
+
let parsed;
|
|
50
|
+
assert.doesNotThrow(() => {
|
|
51
|
+
parsed = JSON.parse(content);
|
|
52
|
+
}, 'mcp.json.example must be valid JSON');
|
|
53
|
+
assert.ok(parsed !== null && typeof parsed === 'object', 'Parsed JSON should be an object');
|
|
54
|
+
});
|
|
55
|
+
it('should have servers object at top level', () => {
|
|
56
|
+
const config = JSON.parse(readFileSync(TEMPLATE_MCP, 'utf-8'));
|
|
57
|
+
assert.ok(config.servers && typeof config.servers === 'object', 'mcp.json.example must have a "servers" object');
|
|
58
|
+
});
|
|
59
|
+
it('should have $schema field for VS Code validation', () => {
|
|
60
|
+
const config = JSON.parse(readFileSync(TEMPLATE_MCP, 'utf-8'));
|
|
61
|
+
assert.ok(config.$schema && typeof config.$schema === 'string', 'mcp.json.example should have $schema for VS Code MCP validation');
|
|
62
|
+
assert.ok(config.$schema.includes('vscode') || config.$schema.includes('mcp'), '$schema should reference VS Code or MCP schema');
|
|
63
|
+
});
|
|
64
|
+
it('should define at least one MCP server', () => {
|
|
65
|
+
const config = JSON.parse(readFileSync(TEMPLATE_MCP, 'utf-8'));
|
|
66
|
+
const serverNames = Object.keys(config.servers);
|
|
67
|
+
assert.ok(serverNames.length >= 1, `Should have at least 1 MCP server configured, found ${serverNames.length}`);
|
|
68
|
+
});
|
|
69
|
+
it('each server should have command+args or type+url', () => {
|
|
70
|
+
const config = JSON.parse(readFileSync(TEMPLATE_MCP, 'utf-8'));
|
|
71
|
+
for (const [name, server] of Object.entries(config.servers)) {
|
|
72
|
+
const s = server;
|
|
73
|
+
const hasCommandArgs = typeof s.command === 'string' && Array.isArray(s.args);
|
|
74
|
+
const hasTypeUrl = typeof s.type === 'string' && typeof s.url === 'string';
|
|
75
|
+
assert.ok(hasCommandArgs || hasTypeUrl, `Server "${name}" must have either (command + args) or (type + url). Got: ${JSON.stringify(s)}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
it('should include shadcn server for component browsing', () => {
|
|
79
|
+
const config = JSON.parse(readFileSync(TEMPLATE_MCP, 'utf-8'));
|
|
80
|
+
assert.ok(config.servers.shadcn, 'Should include shadcn MCP server (used by developer agent for component browsing)');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('MCP file installation via init', () => {
|
|
84
|
+
let testDir;
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
testDir = join(tmpdir(), `beth-mcp-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
87
|
+
mkdirSync(testDir, { recursive: true });
|
|
88
|
+
});
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
if (existsSync(testDir)) {
|
|
91
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
it('should copy mcp.json.example to target project', () => {
|
|
95
|
+
runInit(testDir);
|
|
96
|
+
const mcpDest = join(testDir, 'mcp.json.example');
|
|
97
|
+
assert.ok(existsSync(mcpDest), 'mcp.json.example should be copied to project');
|
|
98
|
+
});
|
|
99
|
+
it('copied mcp.json.example should be valid JSON', () => {
|
|
100
|
+
runInit(testDir);
|
|
101
|
+
const mcpDest = join(testDir, 'mcp.json.example');
|
|
102
|
+
const content = readFileSync(mcpDest, 'utf-8');
|
|
103
|
+
assert.doesNotThrow(() => {
|
|
104
|
+
JSON.parse(content);
|
|
105
|
+
}, 'Copied mcp.json.example must be valid JSON');
|
|
106
|
+
});
|
|
107
|
+
it('copied file should match template content exactly', () => {
|
|
108
|
+
runInit(testDir);
|
|
109
|
+
const templateContent = readFileSync(TEMPLATE_MCP, 'utf-8');
|
|
110
|
+
const copiedContent = readFileSync(join(testDir, 'mcp.json.example'), 'utf-8');
|
|
111
|
+
assert.strictEqual(copiedContent, templateContent, 'Copied file should match template exactly');
|
|
112
|
+
});
|
|
113
|
+
it('should NOT copy mcp.json.example when --skip-mcp is used', () => {
|
|
114
|
+
runInit(testDir, ['--skip-mcp']);
|
|
115
|
+
const mcpDest = join(testDir, 'mcp.json.example');
|
|
116
|
+
assert.ok(!existsSync(mcpDest), 'mcp.json.example should NOT exist with --skip-mcp');
|
|
117
|
+
});
|
|
118
|
+
it('should preserve existing mcp.json.example without --force', () => {
|
|
119
|
+
const mcpDest = join(testDir, 'mcp.json.example');
|
|
120
|
+
const original = '{"custom": true}';
|
|
121
|
+
writeFileSync(mcpDest, original);
|
|
122
|
+
runInit(testDir);
|
|
123
|
+
const content = readFileSync(mcpDest, 'utf-8');
|
|
124
|
+
assert.strictEqual(content, original, 'Should not overwrite existing mcp.json.example without --force');
|
|
125
|
+
});
|
|
126
|
+
it('should overwrite mcp.json.example with --force', () => {
|
|
127
|
+
const mcpDest = join(testDir, 'mcp.json.example');
|
|
128
|
+
const original = '{"custom": true}';
|
|
129
|
+
writeFileSync(mcpDest, original);
|
|
130
|
+
runInit(testDir, ['--force']);
|
|
131
|
+
const content = readFileSync(mcpDest, 'utf-8');
|
|
132
|
+
assert.notStrictEqual(content, original, 'Should overwrite with --force');
|
|
133
|
+
// Verify it's valid JSON from the template
|
|
134
|
+
const parsed = JSON.parse(content);
|
|
135
|
+
assert.ok(parsed.servers, 'Overwritten file should have servers from template');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=mcp.e2e.test.js.map
|