create-byan-agent 2.0.1 → 2.1.1
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/API-BYAN-V2.md +741 -0
- package/BMAD-QUICK-REFERENCE.md +370 -0
- package/CHANGELOG-v2.1.0.md +371 -0
- package/LICENSE +1 -1
- package/MIGRATION-v2.0-to-v2.1.md +430 -0
- package/README-BYAN-V2.md +446 -0
- package/README.md +264 -201
- package/install/.eslintrc.js +20 -0
- package/install/.prettierrc +7 -0
- package/install/BUGFIX-CHALK.md +173 -0
- package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
- package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
- package/install/BUGFIX-QUICKSTART.md +184 -0
- package/install/BUGFIX-SUMMARY.txt +91 -0
- package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
- package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
- package/install/DOCS-INDEX.md +261 -0
- package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
- package/install/INSTALLER-V2-CHANGES.md +472 -0
- package/install/LICENSE +21 -0
- package/install/PUBLICATION-CHECKLIST.md +265 -0
- package/install/PUBLISH-GUIDE.md +190 -0
- package/install/QUICKSTART.md +311 -0
- package/install/README-NPM-PUBLISH.md +298 -0
- package/install/README-NPM-SHORT.md +298 -0
- package/install/README-NPM.md +433 -0
- package/install/README-RACHID.md +302 -0
- package/install/README-V2-INDEX.md +306 -0
- package/install/README.md +298 -0
- package/install/RESUME-EXECUTIF-YAN.md +408 -0
- package/install/UPDATE-SUMMARY.md +205 -0
- package/install/__tests__/integration/detection-flow.test.js +154 -0
- package/install/__tests__/platforms/claude-code.test.js +175 -0
- package/install/__tests__/platforms/codex.test.js +80 -0
- package/install/__tests__/platforms/copilot-cli.test.js +118 -0
- package/install/__tests__/platforms/vscode.test.js +67 -0
- package/install/__tests__/utils/file-utils.test.js +87 -0
- package/install/__tests__/utils/git-detector.test.js +80 -0
- package/install/__tests__/utils/logger.test.js +83 -0
- package/install/__tests__/utils/node-detector.test.js +71 -0
- package/install/__tests__/utils/os-detector.test.js +63 -0
- package/install/__tests__/utils/yaml-utils.test.js +85 -0
- package/install/__tests__/yanstaller/detector.test.js +210 -0
- package/install/coverage/clover.xml +219 -0
- package/install/coverage/coverage-final.json +13 -0
- package/install/coverage/lcov-report/base.css +224 -0
- package/install/coverage/lcov-report/block-navigation.js +87 -0
- package/install/coverage/lcov-report/favicon.png +0 -0
- package/install/coverage/lcov-report/index.html +146 -0
- package/install/coverage/lcov-report/lib/errors.js.html +268 -0
- package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
- package/install/coverage/lcov-report/lib/index.html +131 -0
- package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
- package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
- package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/lib/utils/index.html +206 -0
- package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
- package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
- package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
- package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
- package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
- package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
- package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
- package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
- package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/platforms/index.html +176 -0
- package/install/coverage/lcov-report/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/prettify.css +1 -0
- package/install/coverage/lcov-report/prettify.js +2 -0
- package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/install/coverage/lcov-report/sorter.js +210 -0
- package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/utils/index.html +191 -0
- package/install/coverage/lcov-report/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/yanstaller/index.html +116 -0
- package/install/coverage/lcov.info +414 -0
- package/install/install.sh +239 -0
- package/install/jest.config.js +33 -0
- package/install/lib/errors.js +61 -0
- package/install/lib/exit-codes.js +54 -0
- package/install/lib/platforms/claude-code.js +86 -0
- package/install/lib/platforms/codex.js +92 -0
- package/install/lib/platforms/copilot-cli.js +123 -0
- package/install/lib/platforms/index.js +14 -0
- package/install/lib/platforms/vscode.js +51 -0
- package/install/lib/utils/config-loader.js +79 -0
- package/install/lib/utils/file-utils.js +104 -0
- package/install/lib/utils/git-detector.js +35 -0
- package/install/lib/utils/logger.js +64 -0
- package/install/lib/utils/node-detector.js +58 -0
- package/install/lib/utils/os-detector.js +74 -0
- package/install/lib/utils/yaml-utils.js +87 -0
- package/install/lib/yanstaller/backuper.js +108 -0
- package/install/lib/yanstaller/detector.js +141 -0
- package/install/lib/yanstaller/index.js +93 -0
- package/install/lib/yanstaller/installer.js +140 -0
- package/install/lib/yanstaller/interviewer.js +88 -0
- package/install/lib/yanstaller/recommender.js +98 -0
- package/install/lib/yanstaller/troubleshooter.js +89 -0
- package/install/lib/yanstaller/validator.js +198 -0
- package/install/lib/yanstaller/wizard.js +109 -0
- package/install/package-npm.json +55 -0
- package/install/package.json +63 -0
- package/install/src/byan-v2/context/copilot-context.js +79 -0
- package/install/src/byan-v2/context/session-state.js +98 -0
- package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/install/src/byan-v2/dispatcher/task-router.js +122 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/install/src/byan-v2/generation/profile-template.js +113 -0
- package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/install/src/byan-v2/generation/templates/test-template.md +1 -0
- package/install/src/byan-v2/index.js +199 -0
- package/install/src/byan-v2/observability/error-tracker.js +105 -0
- package/install/src/byan-v2/observability/logger.js +154 -0
- package/install/src/byan-v2/observability/metrics-collector.js +194 -0
- package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
- package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
- package/install/src/core/cache/cache.js +126 -0
- package/install/src/core/context/context.js +86 -0
- package/install/src/core/dispatcher/dispatcher.js +135 -0
- package/install/src/core/worker-pool/worker-pool.js +194 -0
- package/install/src/core/workflow/workflow-executor.js +220 -0
- package/install/src/index.js +139 -0
- package/install/src/observability/dashboard/dashboard.js +191 -0
- package/install/src/observability/logger/structured-logger.js +254 -0
- package/install/src/observability/metrics/metrics-collector.js +325 -0
- package/install/switch-to-v2.sh +126 -0
- package/install/test-chalk-fix.sh +210 -0
- package/install/test-installer-v2.sh +204 -0
- package/install/test-path-resolution.sh +200 -0
- package/package.json +53 -33
- package/src/byan-v2/context/copilot-context.js +79 -0
- package/src/byan-v2/context/session-state.js +98 -0
- package/src/byan-v2/data/mantras.json +852 -0
- package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
- package/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/src/byan-v2/dispatcher/task-router.js +122 -0
- package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/src/byan-v2/generation/mantra-validator.js +416 -0
- package/src/byan-v2/generation/profile-template.js +113 -0
- package/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/src/byan-v2/generation/templates/test-template.md +1 -0
- package/src/byan-v2/index.js +652 -0
- package/src/byan-v2/integration/voice-integration.js +295 -0
- package/src/byan-v2/observability/error-tracker.js +105 -0
- package/src/byan-v2/observability/logger.js +154 -0
- package/src/byan-v2/observability/metrics-collector.js +194 -0
- package/src/byan-v2/orchestrator/active-listener.js +541 -0
- package/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
- package/src/byan-v2/orchestrator/interview-state.js +353 -0
- package/src/byan-v2/orchestrator/state-machine.js +253 -0
- package/src/core/cache/cache.js +126 -0
- package/src/core/context/context.js +86 -0
- package/src/core/dispatcher/dispatcher.js +135 -0
- package/src/core/worker-pool/worker-pool.js +194 -0
- package/src/core/workflow/workflow-executor.js +220 -0
- package/src/index.js +139 -0
- package/src/observability/dashboard/dashboard.js +191 -0
- package/src/observability/logger/structured-logger.js +254 -0
- package/src/observability/metrics/metrics-collector.js +325 -0
- package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
- package/templates/.github/agents/franck.md +0 -379
- /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
- /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
- /package/{bin → install/bin}/create-byan-agent.js +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/core/agents/carmack.md +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot CLI Platform Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/platforms/copilot-cli.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const copilotCli = require('../../lib/platforms/copilot-cli');
|
|
8
|
+
const fileUtils = require('../../lib/utils/file-utils');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
// Mock dependencies
|
|
13
|
+
jest.mock('child_process');
|
|
14
|
+
jest.mock('../../lib/utils/file-utils');
|
|
15
|
+
|
|
16
|
+
describe('Copilot CLI Platform', () => {
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
jest.clearAllMocks();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('detect() - CLI installed', () => {
|
|
22
|
+
it('should return true when github-copilot-cli command exists', async () => {
|
|
23
|
+
// Mock successful command
|
|
24
|
+
execSync.mockReturnValue('');
|
|
25
|
+
|
|
26
|
+
const result = await copilotCli.detect();
|
|
27
|
+
|
|
28
|
+
expect(result).toBe(true);
|
|
29
|
+
expect(execSync).toHaveBeenCalledWith('which github-copilot-cli', expect.any(Object));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('detect() - Directory exists', () => {
|
|
34
|
+
it('should return true when .github/agents/ directory exists', async () => {
|
|
35
|
+
// Mock command fails but directory exists
|
|
36
|
+
execSync.mockImplementation(() => {
|
|
37
|
+
throw new Error('command not found');
|
|
38
|
+
});
|
|
39
|
+
fileUtils.exists.mockResolvedValue(true);
|
|
40
|
+
|
|
41
|
+
const result = await copilotCli.detect();
|
|
42
|
+
|
|
43
|
+
expect(result).toBe(true);
|
|
44
|
+
expect(fileUtils.exists).toHaveBeenCalledWith('.github/agents');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('detect() - Neither exists', () => {
|
|
49
|
+
it('should return false when command and directory both missing', async () => {
|
|
50
|
+
// Mock both checks fail
|
|
51
|
+
execSync.mockImplementation(() => {
|
|
52
|
+
throw new Error('command not found');
|
|
53
|
+
});
|
|
54
|
+
fileUtils.exists.mockResolvedValue(false);
|
|
55
|
+
|
|
56
|
+
const result = await copilotCli.detect();
|
|
57
|
+
|
|
58
|
+
expect(result).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('detect() - Timeout protection', () => {
|
|
63
|
+
it('should have timeout protection implemented via Promise.race', async () => {
|
|
64
|
+
// This test verifies timeout exists in code, not that it triggers
|
|
65
|
+
// (testing actual 10s timeout would make tests too slow)
|
|
66
|
+
|
|
67
|
+
// Normal fast detection should work fine
|
|
68
|
+
execSync.mockReturnValue('');
|
|
69
|
+
|
|
70
|
+
const result = await copilotCli.detect();
|
|
71
|
+
|
|
72
|
+
expect(result).toBe(true);
|
|
73
|
+
|
|
74
|
+
// Verify detect() returns quickly (not hanging)
|
|
75
|
+
// If timeout logic exists, function completes immediately when detection succeeds
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('getPath()', () => {
|
|
80
|
+
it('should return .github/agents directory path', () => {
|
|
81
|
+
expect(copilotCli.getPath()).toBe('.github/agents');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('name property', () => {
|
|
86
|
+
it('should have correct platform name', () => {
|
|
87
|
+
expect(copilotCli.name).toBe('GitHub Copilot CLI');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('install()', () => {
|
|
92
|
+
const mockFileUtils = require('../../lib/utils/file-utils');
|
|
93
|
+
|
|
94
|
+
beforeEach(() => {
|
|
95
|
+
jest.clearAllMocks();
|
|
96
|
+
mockFileUtils.ensureDir.mockResolvedValue();
|
|
97
|
+
mockFileUtils.writeFile.mockResolvedValue();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should create .github/agents directory and install agents', async () => {
|
|
101
|
+
const result = await copilotCli.install('/project', ['agent1', 'agent2'], {});
|
|
102
|
+
|
|
103
|
+
expect(mockFileUtils.ensureDir).toHaveBeenCalledWith(
|
|
104
|
+
path.join('/project', '.github', 'agents')
|
|
105
|
+
);
|
|
106
|
+
expect(mockFileUtils.writeFile).toHaveBeenCalledTimes(2);
|
|
107
|
+
expect(result).toEqual({ success: true, installed: 2 });
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should handle empty agent list', async () => {
|
|
111
|
+
const result = await copilotCli.install('/project', [], {});
|
|
112
|
+
|
|
113
|
+
expect(mockFileUtils.ensureDir).toHaveBeenCalled();
|
|
114
|
+
expect(mockFileUtils.writeFile).not.toHaveBeenCalled();
|
|
115
|
+
expect(result).toEqual({ success: true, installed: 0 });
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VSCode Platform Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/platforms/vscode.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const vscode = require('../../lib/platforms/vscode');
|
|
8
|
+
const copilotCli = require('../../lib/platforms/copilot-cli');
|
|
9
|
+
|
|
10
|
+
// Mock copilot-cli module
|
|
11
|
+
jest.mock('../../lib/platforms/copilot-cli');
|
|
12
|
+
|
|
13
|
+
describe('VSCode Platform', () => {
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('detect()', () => {
|
|
19
|
+
it('should call copilot-cli.detect() and return its result', async () => {
|
|
20
|
+
// Mock copilot-cli.detect to return true
|
|
21
|
+
copilotCli.detect.mockResolvedValue(true);
|
|
22
|
+
|
|
23
|
+
const result = await vscode.detect();
|
|
24
|
+
|
|
25
|
+
expect(result).toBe(true);
|
|
26
|
+
expect(copilotCli.detect).toHaveBeenCalledTimes(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should return false when copilot-cli.detect returns false', async () => {
|
|
30
|
+
copilotCli.detect.mockResolvedValue(false);
|
|
31
|
+
|
|
32
|
+
const result = await vscode.detect();
|
|
33
|
+
|
|
34
|
+
expect(result).toBe(false);
|
|
35
|
+
expect(copilotCli.detect).toHaveBeenCalledTimes(1);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('install()', () => {
|
|
40
|
+
it('should call copilot-cli.install with same arguments', async () => {
|
|
41
|
+
const mockResult = { success: true, installed: 5 };
|
|
42
|
+
copilotCli.install.mockResolvedValue(mockResult);
|
|
43
|
+
|
|
44
|
+
const result = await vscode.install('/project', ['agent1', 'agent2'], {});
|
|
45
|
+
|
|
46
|
+
expect(result).toEqual(mockResult);
|
|
47
|
+
expect(copilotCli.install).toHaveBeenCalledWith('/project', ['agent1', 'agent2'], {});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('getPath()', () => {
|
|
52
|
+
it('should call copilot-cli.getPath and return its result', () => {
|
|
53
|
+
copilotCli.getPath.mockReturnValue('.github/agents');
|
|
54
|
+
|
|
55
|
+
const result = vscode.getPath();
|
|
56
|
+
|
|
57
|
+
expect(result).toBe('.github/agents');
|
|
58
|
+
expect(copilotCli.getPath).toHaveBeenCalledTimes(1);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('name property', () => {
|
|
63
|
+
it('should have correct platform name', () => {
|
|
64
|
+
expect(vscode.name).toBe('VSCode Copilot Extension');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Utils Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/file-utils.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fileUtils = require('../../lib/utils/file-utils');
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
jest.mock('fs-extra');
|
|
12
|
+
|
|
13
|
+
describe('File Utils', () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('exists()', () => {
|
|
19
|
+
it('should return true when path exists', async () => {
|
|
20
|
+
fs.pathExists.mockResolvedValue(true);
|
|
21
|
+
|
|
22
|
+
const result = await fileUtils.exists('/some/path');
|
|
23
|
+
|
|
24
|
+
expect(result).toBe(true);
|
|
25
|
+
expect(fs.pathExists).toHaveBeenCalledWith('/some/path');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return false when path does not exist', async () => {
|
|
29
|
+
fs.pathExists.mockResolvedValue(false);
|
|
30
|
+
|
|
31
|
+
const result = await fileUtils.exists('/missing/path');
|
|
32
|
+
|
|
33
|
+
expect(result).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('readFile()', () => {
|
|
38
|
+
it('should read file content as UTF-8', async () => {
|
|
39
|
+
fs.readFile.mockResolvedValue('file content');
|
|
40
|
+
|
|
41
|
+
const result = await fileUtils.readFile('/path/file.txt');
|
|
42
|
+
|
|
43
|
+
expect(result).toBe('file content');
|
|
44
|
+
expect(fs.readFile).toHaveBeenCalledWith('/path/file.txt', 'utf8');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('writeFile()', () => {
|
|
49
|
+
it('should write file content as UTF-8', async () => {
|
|
50
|
+
fs.writeFile.mockResolvedValue();
|
|
51
|
+
|
|
52
|
+
await fileUtils.writeFile('/path/file.txt', 'content');
|
|
53
|
+
|
|
54
|
+
expect(fs.writeFile).toHaveBeenCalledWith('/path/file.txt', 'content', 'utf8');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('ensureDir()', () => {
|
|
59
|
+
it('should create directory if not exists', async () => {
|
|
60
|
+
fs.ensureDir.mockResolvedValue();
|
|
61
|
+
|
|
62
|
+
await fileUtils.ensureDir('/some/dir');
|
|
63
|
+
|
|
64
|
+
expect(fs.ensureDir).toHaveBeenCalledWith('/some/dir');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('copy()', () => {
|
|
69
|
+
it('should copy source to destination', async () => {
|
|
70
|
+
fs.copy.mockResolvedValue();
|
|
71
|
+
|
|
72
|
+
await fileUtils.copy('/src', '/dest');
|
|
73
|
+
|
|
74
|
+
expect(fs.copy).toHaveBeenCalledWith('/src', '/dest');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('remove()', () => {
|
|
79
|
+
it('should remove path', async () => {
|
|
80
|
+
fs.remove.mockResolvedValue();
|
|
81
|
+
|
|
82
|
+
await fileUtils.remove('/path');
|
|
83
|
+
|
|
84
|
+
expect(fs.remove).toHaveBeenCalledWith('/path');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Detector Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/git-detector.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const gitDetector = require('../../lib/utils/git-detector');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
// Mock child_process
|
|
11
|
+
jest.mock('child_process');
|
|
12
|
+
|
|
13
|
+
describe('Git Detector', () => {
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('detect() - Git installed', () => {
|
|
19
|
+
it('should detect Git and extract version when installed', async () => {
|
|
20
|
+
// Mock successful git command
|
|
21
|
+
execSync.mockReturnValue('git version 2.34.1\n');
|
|
22
|
+
|
|
23
|
+
const result = await gitDetector.detect();
|
|
24
|
+
|
|
25
|
+
expect(result).toEqual({
|
|
26
|
+
installed: true,
|
|
27
|
+
version: '2.34.1'
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(execSync).toHaveBeenCalledWith('git --version', { encoding: 'utf8' });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should handle different Git version formats', async () => {
|
|
34
|
+
// Test various git version output formats
|
|
35
|
+
execSync.mockReturnValue('git version 2.40.0');
|
|
36
|
+
|
|
37
|
+
const result = await gitDetector.detect();
|
|
38
|
+
|
|
39
|
+
expect(result.installed).toBe(true);
|
|
40
|
+
expect(result.version).toBe('2.40.0');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('detect() - Git not installed', () => {
|
|
45
|
+
it('should return installed: false when Git command fails', async () => {
|
|
46
|
+
// Mock command failure (Git not installed)
|
|
47
|
+
execSync.mockImplementation(() => {
|
|
48
|
+
throw new Error('command not found: git');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const result = await gitDetector.detect();
|
|
52
|
+
|
|
53
|
+
expect(result).toEqual({
|
|
54
|
+
installed: false,
|
|
55
|
+
version: null
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('detect() - Error handling', () => {
|
|
61
|
+
it('should handle malformed git version output gracefully', async () => {
|
|
62
|
+
// Mock unexpected output format
|
|
63
|
+
execSync.mockReturnValue('some weird output without version');
|
|
64
|
+
|
|
65
|
+
const result = await gitDetector.detect();
|
|
66
|
+
|
|
67
|
+
expect(result.installed).toBe(true);
|
|
68
|
+
expect(result.version).toBeNull(); // Version extraction failed but Git exists
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should handle empty output', async () => {
|
|
72
|
+
execSync.mockReturnValue('');
|
|
73
|
+
|
|
74
|
+
const result = await gitDetector.detect();
|
|
75
|
+
|
|
76
|
+
expect(result.installed).toBe(true);
|
|
77
|
+
expect(result.version).toBeNull();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/logger.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const logger = require('../../lib/utils/logger');
|
|
8
|
+
|
|
9
|
+
// Mock chalk
|
|
10
|
+
jest.mock('chalk', () => ({
|
|
11
|
+
green: jest.fn((text) => `GREEN:${text}`),
|
|
12
|
+
red: jest.fn((text) => `RED:${text}`),
|
|
13
|
+
yellow: jest.fn((text) => `YELLOW:${text}`),
|
|
14
|
+
blue: jest.fn((text) => `BLUE:${text}`),
|
|
15
|
+
gray: jest.fn((text) => `GRAY:${text}`)
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
describe('Logger', () => {
|
|
19
|
+
let consoleLogSpy;
|
|
20
|
+
let consoleErrorSpy;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
24
|
+
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
consoleLogSpy.mockRestore();
|
|
29
|
+
consoleErrorSpy.mockRestore();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('success()', () => {
|
|
33
|
+
it('should log success message in green', () => {
|
|
34
|
+
logger.success('Test success');
|
|
35
|
+
|
|
36
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('GREEN:✓', 'Test success');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('error()', () => {
|
|
41
|
+
it('should log error message in red', () => {
|
|
42
|
+
logger.error('Test error');
|
|
43
|
+
|
|
44
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('RED:✖', 'Test error');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('warn()', () => {
|
|
49
|
+
it('should log warning message in yellow', () => {
|
|
50
|
+
logger.warn('Test warning');
|
|
51
|
+
|
|
52
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('YELLOW:⚠', 'Test warning');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('info()', () => {
|
|
57
|
+
it('should log info message in blue', () => {
|
|
58
|
+
logger.info('Test info');
|
|
59
|
+
|
|
60
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('BLUE:ℹ', 'Test info');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('debug()', () => {
|
|
65
|
+
it('should log debug message in gray when DEBUG env is set', () => {
|
|
66
|
+
process.env.DEBUG = 'true';
|
|
67
|
+
|
|
68
|
+
logger.debug('Test debug');
|
|
69
|
+
|
|
70
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('GRAY:[DEBUG]', 'Test debug');
|
|
71
|
+
|
|
72
|
+
delete process.env.DEBUG;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should not log when DEBUG env is not set', () => {
|
|
76
|
+
delete process.env.DEBUG;
|
|
77
|
+
|
|
78
|
+
logger.debug('Test debug');
|
|
79
|
+
|
|
80
|
+
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Detector Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/node-detector.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const nodeDetector = require('../../lib/utils/node-detector');
|
|
8
|
+
|
|
9
|
+
describe('Node Detector', () => {
|
|
10
|
+
describe('detect()', () => {
|
|
11
|
+
it('should detect Node.js version without v prefix', () => {
|
|
12
|
+
const result = nodeDetector.detect();
|
|
13
|
+
|
|
14
|
+
expect(typeof result).toBe('string');
|
|
15
|
+
expect(result).not.toMatch(/^v/); // No 'v' prefix
|
|
16
|
+
expect(result).toMatch(/^\d+\.\d+\.\d+/); // Semver format
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('compareVersions()', () => {
|
|
21
|
+
it('should return 0 for equal versions', () => {
|
|
22
|
+
expect(nodeDetector.compareVersions('18.0.0', '18.0.0')).toBe(0);
|
|
23
|
+
expect(nodeDetector.compareVersions('20.5.1', '20.5.1')).toBe(0);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return 1 when first version is greater', () => {
|
|
27
|
+
expect(nodeDetector.compareVersions('19.0.0', '18.0.0')).toBe(1);
|
|
28
|
+
expect(nodeDetector.compareVersions('18.1.0', '18.0.0')).toBe(1);
|
|
29
|
+
expect(nodeDetector.compareVersions('18.0.1', '18.0.0')).toBe(1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return -1 when first version is less', () => {
|
|
33
|
+
expect(nodeDetector.compareVersions('18.0.0', '19.0.0')).toBe(-1);
|
|
34
|
+
expect(nodeDetector.compareVersions('18.0.0', '18.1.0')).toBe(-1);
|
|
35
|
+
expect(nodeDetector.compareVersions('18.0.0', '18.0.1')).toBe(-1);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should handle version suffixes correctly by stripping them', () => {
|
|
39
|
+
// These should all compare equal after suffix removal
|
|
40
|
+
expect(nodeDetector.compareVersions('18.0.0-beta', '18.0.0')).toBe(0);
|
|
41
|
+
expect(nodeDetector.compareVersions('18.0.0', '18.0.0-beta')).toBe(0);
|
|
42
|
+
expect(nodeDetector.compareVersions('18.0.0-rc1', '18.0.0-beta')).toBe(0);
|
|
43
|
+
|
|
44
|
+
// These should compare correctly after suffix removal
|
|
45
|
+
expect(nodeDetector.compareVersions('19.0.0-beta', '18.0.0')).toBe(1);
|
|
46
|
+
expect(nodeDetector.compareVersions('18.0.0-rc1', '19.0.0')).toBe(-1);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('meetsRequirement()', () => {
|
|
51
|
+
it('should return true when current version meets requirement', () => {
|
|
52
|
+
expect(nodeDetector.meetsRequirement('18.0.0', '18.0.0')).toBe(true);
|
|
53
|
+
expect(nodeDetector.meetsRequirement('19.0.0', '18.0.0')).toBe(true);
|
|
54
|
+
expect(nodeDetector.meetsRequirement('18.1.0', '18.0.0')).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should return false when current version does not meet requirement', () => {
|
|
58
|
+
expect(nodeDetector.meetsRequirement('17.9.9', '18.0.0')).toBe(false);
|
|
59
|
+
expect(nodeDetector.meetsRequirement('16.0.0', '18.0.0')).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should handle version suffixes correctly', () => {
|
|
63
|
+
// 18.0.0-beta should still meet 18.0.0 requirement (same base version)
|
|
64
|
+
expect(nodeDetector.meetsRequirement('18.0.0-beta', '18.0.0')).toBe(true);
|
|
65
|
+
expect(nodeDetector.meetsRequirement('19.0.0-rc1', '18.0.0')).toBe(true);
|
|
66
|
+
|
|
67
|
+
// 17.9.9-beta should not meet 18.0.0 requirement
|
|
68
|
+
expect(nodeDetector.meetsRequirement('17.9.9-beta', '18.0.0')).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS Detector Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/os-detector.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const osDetector = require('../../lib/utils/os-detector');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
describe('OS Detector', () => {
|
|
11
|
+
describe('detect()', () => {
|
|
12
|
+
it('should detect operating system with name, version, and platform', () => {
|
|
13
|
+
const result = osDetector.detect();
|
|
14
|
+
|
|
15
|
+
expect(result).toHaveProperty('name');
|
|
16
|
+
expect(result).toHaveProperty('version');
|
|
17
|
+
expect(result).toHaveProperty('platform');
|
|
18
|
+
|
|
19
|
+
expect(typeof result.name).toBe('string');
|
|
20
|
+
expect(typeof result.version).toBe('string');
|
|
21
|
+
expect(typeof result.platform).toBe('string');
|
|
22
|
+
|
|
23
|
+
// Validate name is one of expected values
|
|
24
|
+
expect(['windows', 'macos', 'linux', 'unknown']).toContain(result.name);
|
|
25
|
+
|
|
26
|
+
// Platform should match os.platform()
|
|
27
|
+
expect(result.platform).toBe(os.platform());
|
|
28
|
+
|
|
29
|
+
// Version should match os.release()
|
|
30
|
+
expect(result.version).toBe(os.release());
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('isWindows()', () => {
|
|
35
|
+
it('should return true on Windows, false otherwise', () => {
|
|
36
|
+
const result = osDetector.isWindows();
|
|
37
|
+
const expected = os.platform() === 'win32';
|
|
38
|
+
|
|
39
|
+
expect(result).toBe(expected);
|
|
40
|
+
expect(typeof result).toBe('boolean');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('isMacOS()', () => {
|
|
45
|
+
it('should return true on macOS, false otherwise', () => {
|
|
46
|
+
const result = osDetector.isMacOS();
|
|
47
|
+
const expected = os.platform() === 'darwin';
|
|
48
|
+
|
|
49
|
+
expect(result).toBe(expected);
|
|
50
|
+
expect(typeof result).toBe('boolean');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('isLinux()', () => {
|
|
55
|
+
it('should return true on Linux, false otherwise', () => {
|
|
56
|
+
const result = osDetector.isLinux();
|
|
57
|
+
const expected = os.platform() === 'linux';
|
|
58
|
+
|
|
59
|
+
expect(result).toBe(expected);
|
|
60
|
+
expect(typeof result).toBe('boolean');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML Utils Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/utils/yaml-utils.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const yamlUtils = require('../../lib/utils/yaml-utils');
|
|
8
|
+
const fileUtils = require('../../lib/utils/file-utils');
|
|
9
|
+
|
|
10
|
+
jest.mock('../../lib/utils/file-utils');
|
|
11
|
+
|
|
12
|
+
describe('YAML Utils', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('parse()', () => {
|
|
18
|
+
it('should parse valid YAML string', () => {
|
|
19
|
+
const yamlString = 'name: test\nvalue: 123';
|
|
20
|
+
|
|
21
|
+
const result = yamlUtils.parse(yamlString);
|
|
22
|
+
|
|
23
|
+
expect(result).toEqual({ name: 'test', value: 123 });
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('dump()', () => {
|
|
28
|
+
it('should dump object to YAML string', () => {
|
|
29
|
+
const obj = { name: 'test', value: 123 };
|
|
30
|
+
|
|
31
|
+
const result = yamlUtils.dump(obj);
|
|
32
|
+
|
|
33
|
+
expect(result).toContain('name: test');
|
|
34
|
+
expect(result).toContain('value: 123');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('readYAML()', () => {
|
|
39
|
+
it('should read and parse YAML file', async () => {
|
|
40
|
+
fileUtils.readFile.mockResolvedValue('name: test\nvalue: 123');
|
|
41
|
+
|
|
42
|
+
const result = await yamlUtils.readYAML('/path/file.yaml');
|
|
43
|
+
|
|
44
|
+
expect(fileUtils.readFile).toHaveBeenCalledWith('/path/file.yaml');
|
|
45
|
+
expect(result).toEqual({ name: 'test', value: 123 });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('writeYAML()', () => {
|
|
50
|
+
it('should dump and write YAML file', async () => {
|
|
51
|
+
fileUtils.writeFile.mockResolvedValue();
|
|
52
|
+
|
|
53
|
+
await yamlUtils.writeYAML('/path/file.yaml', { name: 'test', value: 123 });
|
|
54
|
+
|
|
55
|
+
expect(fileUtils.writeFile).toHaveBeenCalledWith(
|
|
56
|
+
'/path/file.yaml',
|
|
57
|
+
expect.stringContaining('name: test')
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('extractFrontmatter()', () => {
|
|
63
|
+
it('should extract frontmatter and content from markdown', () => {
|
|
64
|
+
const markdown = `---
|
|
65
|
+
name: test
|
|
66
|
+
value: 123
|
|
67
|
+
---
|
|
68
|
+
# Content here`;
|
|
69
|
+
|
|
70
|
+
const result = yamlUtils.extractFrontmatter(markdown);
|
|
71
|
+
|
|
72
|
+
expect(result.frontmatter).toEqual({ name: 'test', value: 123 });
|
|
73
|
+
expect(result.content).toBe('# Content here');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should return null frontmatter when no frontmatter exists', () => {
|
|
77
|
+
const markdown = '# Content without frontmatter';
|
|
78
|
+
|
|
79
|
+
const result = yamlUtils.extractFrontmatter(markdown);
|
|
80
|
+
|
|
81
|
+
expect(result.frontmatter).toBeNull();
|
|
82
|
+
expect(result.content).toBe(markdown);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|