@skillsmith/cli 0.5.0 → 0.5.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/dist/.tsbuildinfo +1 -1
- package/dist/src/commands/audit.test.js +1 -1
- package/dist/src/commands/audit.test.js.map +1 -1
- package/dist/src/commands/create.d.ts.map +1 -1
- package/dist/src/commands/create.js +1 -1
- package/dist/src/commands/create.js.map +1 -1
- package/dist/src/commands/index.d.ts +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +3 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/install-skill.d.ts.map +1 -1
- package/dist/src/commands/install-skill.js +10 -3
- package/dist/src/commands/install-skill.js.map +1 -1
- package/dist/src/commands/install.d.ts +13 -0
- package/dist/src/commands/install.d.ts.map +1 -0
- package/dist/src/commands/install.js +213 -0
- package/dist/src/commands/install.js.map +1 -0
- package/dist/src/commands/manage.d.ts.map +1 -1
- package/dist/src/commands/manage.js +55 -19
- package/dist/src/commands/manage.js.map +1 -1
- package/dist/src/commands/pin.js +1 -1
- package/dist/src/commands/pin.js.map +1 -1
- package/dist/src/commands/search.d.ts.map +1 -1
- package/dist/src/commands/search.js +43 -3
- package/dist/src/commands/search.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/templates/readme.md.template.d.ts +1 -1
- package/dist/src/templates/readme.md.template.d.ts.map +1 -1
- package/dist/src/templates/readme.md.template.js +1 -1
- package/dist/src/templates/skill.md.template.d.ts +1 -1
- package/dist/src/templates/skill.md.template.d.ts.map +1 -1
- package/dist/src/templates/skill.md.template.js +1 -1
- package/dist/src/utils/skills-directory.d.ts.map +1 -1
- package/dist/src/utils/skills-directory.js +3 -2
- package/dist/src/utils/skills-directory.js.map +1 -1
- package/dist/tests/install-skill.test.js +9 -4
- package/dist/tests/install-skill.test.js.map +1 -1
- package/dist/tests/license-validation.test.d.ts +8 -0
- package/dist/tests/license-validation.test.d.ts.map +1 -0
- package/dist/tests/license-validation.test.js +186 -0
- package/dist/tests/license-validation.test.js.map +1 -0
- package/dist/tests/manage.test.js +84 -0
- package/dist/tests/manage.test.js.map +1 -1
- package/dist/tests/recommend-helpers.test.d.ts +9 -0
- package/dist/tests/recommend-helpers.test.d.ts.map +1 -0
- package/dist/tests/recommend-helpers.test.js +308 -0
- package/dist/tests/recommend-helpers.test.js.map +1 -0
- package/dist/tests/recommend-scoring.test.d.ts +8 -0
- package/dist/tests/recommend-scoring.test.d.ts.map +1 -0
- package/dist/tests/recommend-scoring.test.js +184 -0
- package/dist/tests/recommend-scoring.test.js.map +1 -0
- package/dist/tests/tool-analyzer.test.d.ts +8 -0
- package/dist/tests/tool-analyzer.test.d.ts.map +1 -0
- package/dist/tests/tool-analyzer.test.js +149 -0
- package/dist/tests/tool-analyzer.test.js.map +1 -0
- package/dist/tests/unit/commands/install.test.d.ts +7 -0
- package/dist/tests/unit/commands/install.test.d.ts.map +1 -0
- package/dist/tests/unit/commands/install.test.js +407 -0
- package/dist/tests/unit/commands/install.test.js.map +1 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +9 -3
- package/dist/vitest.config.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for tool-analyzer.ts pure logic functions
|
|
3
|
+
*
|
|
4
|
+
* Tests analyzeToolRequirements, formatToolList, parseToolsString, validateTools.
|
|
5
|
+
* No mocking required — all functions are pure.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect } from 'vitest';
|
|
8
|
+
import { analyzeToolRequirements, formatToolList, parseToolsString, validateTools, TOOL_PATTERNS, } from '../src/utils/tool-analyzer.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// analyzeToolRequirements
|
|
11
|
+
// ============================================================================
|
|
12
|
+
describe('analyzeToolRequirements', () => {
|
|
13
|
+
it('always includes Read tool', () => {
|
|
14
|
+
const result = analyzeToolRequirements('');
|
|
15
|
+
expect(result.requiredTools).toContain('Read');
|
|
16
|
+
});
|
|
17
|
+
it('detects Write from content', () => {
|
|
18
|
+
const result = analyzeToolRequirements('This skill will write files to disk');
|
|
19
|
+
expect(result.requiredTools).toContain('Write');
|
|
20
|
+
});
|
|
21
|
+
it('detects Edit from content', () => {
|
|
22
|
+
const result = analyzeToolRequirements('Modify existing configuration files');
|
|
23
|
+
expect(result.requiredTools).toContain('Edit');
|
|
24
|
+
});
|
|
25
|
+
it('detects Bash from npm keyword', () => {
|
|
26
|
+
const result = analyzeToolRequirements('Run npm install to set up dependencies');
|
|
27
|
+
expect(result.requiredTools).toContain('Bash');
|
|
28
|
+
});
|
|
29
|
+
it('detects Bash from docker keyword', () => {
|
|
30
|
+
const result = analyzeToolRequirements('Execute docker compose up');
|
|
31
|
+
expect(result.requiredTools).toContain('Bash');
|
|
32
|
+
});
|
|
33
|
+
it('detects Bash from git keyword', () => {
|
|
34
|
+
const result = analyzeToolRequirements('Use git commit to save changes');
|
|
35
|
+
expect(result.requiredTools).toContain('Bash');
|
|
36
|
+
});
|
|
37
|
+
it('detects Grep from search keywords', () => {
|
|
38
|
+
const result = analyzeToolRequirements('Search for all TODO comments');
|
|
39
|
+
expect(result.requiredTools).toContain('Grep');
|
|
40
|
+
});
|
|
41
|
+
it('detects Glob from file pattern keywords', () => {
|
|
42
|
+
const result = analyzeToolRequirements('Find files matching the pattern');
|
|
43
|
+
expect(result.requiredTools).toContain('Glob');
|
|
44
|
+
});
|
|
45
|
+
it('detects WebFetch from http keywords', () => {
|
|
46
|
+
const result = analyzeToolRequirements('Fetch data from http endpoints');
|
|
47
|
+
expect(result.requiredTools).toContain('WebFetch');
|
|
48
|
+
});
|
|
49
|
+
it('detects WebSearch from search online keywords', () => {
|
|
50
|
+
const result = analyzeToolRequirements('Search online for best practices');
|
|
51
|
+
expect(result.requiredTools).toContain('WebSearch');
|
|
52
|
+
});
|
|
53
|
+
it('returns high confidence for 3+ pattern matches', () => {
|
|
54
|
+
const result = analyzeToolRequirements('Write files, run npm commands, and search for patterns in the codebase');
|
|
55
|
+
expect(result.confidence).toBe('high');
|
|
56
|
+
});
|
|
57
|
+
it('returns medium confidence for 1-2 pattern matches', () => {
|
|
58
|
+
const result = analyzeToolRequirements('Edit a single configuration file');
|
|
59
|
+
expect(result.confidence).toBe('medium');
|
|
60
|
+
});
|
|
61
|
+
it('returns low confidence for no pattern matches', () => {
|
|
62
|
+
const result = analyzeToolRequirements('A purely informational skill');
|
|
63
|
+
expect(result.confidence).toBe('low');
|
|
64
|
+
});
|
|
65
|
+
it('records detected patterns', () => {
|
|
66
|
+
const result = analyzeToolRequirements('Write output to file and run npm build');
|
|
67
|
+
expect(result.detectedPatterns.length).toBeGreaterThan(0);
|
|
68
|
+
expect(result.detectedPatterns.some((p) => p.startsWith('Write:'))).toBe(true);
|
|
69
|
+
expect(result.detectedPatterns.some((p) => p.startsWith('Bash:'))).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('only matches one pattern per tool', () => {
|
|
72
|
+
const result = analyzeToolRequirements('Write to file, save data, create file, generate file');
|
|
73
|
+
const writePatterns = result.detectedPatterns.filter((p) => p.startsWith('Write:'));
|
|
74
|
+
expect(writePatterns).toHaveLength(1);
|
|
75
|
+
});
|
|
76
|
+
it('is case-insensitive', () => {
|
|
77
|
+
const result = analyzeToolRequirements('NPM INSTALL and DOCKER BUILD');
|
|
78
|
+
expect(result.requiredTools).toContain('Bash');
|
|
79
|
+
});
|
|
80
|
+
it('requiredTools and recommendedTools are identical', () => {
|
|
81
|
+
const result = analyzeToolRequirements('Write, edit, search, and run commands');
|
|
82
|
+
expect(result.requiredTools).toEqual(result.recommendedTools);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// formatToolList
|
|
87
|
+
// ============================================================================
|
|
88
|
+
describe('formatToolList', () => {
|
|
89
|
+
it('returns "Read" for empty array', () => {
|
|
90
|
+
expect(formatToolList([])).toBe('Read');
|
|
91
|
+
});
|
|
92
|
+
it('joins tools with comma and space', () => {
|
|
93
|
+
expect(formatToolList(['Read', 'Write', 'Bash'])).toBe('Read, Write, Bash');
|
|
94
|
+
});
|
|
95
|
+
it('returns single tool as-is', () => {
|
|
96
|
+
expect(formatToolList(['Edit'])).toBe('Edit');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// parseToolsString
|
|
101
|
+
// ============================================================================
|
|
102
|
+
describe('parseToolsString', () => {
|
|
103
|
+
it('parses comma-separated tools', () => {
|
|
104
|
+
expect(parseToolsString('Read, Write, Bash')).toEqual(['Read', 'Write', 'Bash']);
|
|
105
|
+
});
|
|
106
|
+
it('trims whitespace', () => {
|
|
107
|
+
expect(parseToolsString(' Read , Write ')).toEqual(['Read', 'Write']);
|
|
108
|
+
});
|
|
109
|
+
it('filters empty strings', () => {
|
|
110
|
+
expect(parseToolsString('Read,,Write,')).toEqual(['Read', 'Write']);
|
|
111
|
+
});
|
|
112
|
+
it('handles single tool', () => {
|
|
113
|
+
expect(parseToolsString('Read')).toEqual(['Read']);
|
|
114
|
+
});
|
|
115
|
+
it('returns empty array for empty string', () => {
|
|
116
|
+
expect(parseToolsString('')).toEqual([]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// validateTools
|
|
121
|
+
// ============================================================================
|
|
122
|
+
describe('validateTools', () => {
|
|
123
|
+
it('validates known tools', () => {
|
|
124
|
+
const result = validateTools(['Read', 'Write', 'Bash']);
|
|
125
|
+
expect(result.valid).toBe(true);
|
|
126
|
+
expect(result.unrecognized).toEqual([]);
|
|
127
|
+
});
|
|
128
|
+
it('reports unrecognized tools', () => {
|
|
129
|
+
const result = validateTools(['Read', 'FlyToMoon']);
|
|
130
|
+
expect(result.valid).toBe(false);
|
|
131
|
+
expect(result.unrecognized).toEqual(['FlyToMoon']);
|
|
132
|
+
});
|
|
133
|
+
it('validates all TOOL_PATTERNS keys', () => {
|
|
134
|
+
const allTools = Object.keys(TOOL_PATTERNS);
|
|
135
|
+
const result = validateTools(allTools);
|
|
136
|
+
expect(result.valid).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
it('handles empty array', () => {
|
|
139
|
+
const result = validateTools([]);
|
|
140
|
+
expect(result.valid).toBe(true);
|
|
141
|
+
expect(result.unrecognized).toEqual([]);
|
|
142
|
+
});
|
|
143
|
+
it('reports multiple unrecognized tools', () => {
|
|
144
|
+
const result = validateTools(['FlyToMoon', 'TimeTravel']);
|
|
145
|
+
expect(result.valid).toBe(false);
|
|
146
|
+
expect(result.unrecognized).toHaveLength(2);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=tool-analyzer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-analyzer.test.js","sourceRoot":"","sources":["../../tests/tool-analyzer.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,+BAA+B,CAAA;AAEtC,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,uBAAuB,CAAC,EAAE,CAAC,CAAA;QAC1C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,uBAAuB,CAAC,qCAAqC,CAAC,CAAA;QAC7E,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,uBAAuB,CAAC,qCAAqC,CAAC,CAAA;QAC7E,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,uBAAuB,CAAC,wCAAwC,CAAC,CAAA;QAChF,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAG,uBAAuB,CAAC,2BAA2B,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,uBAAuB,CAAC,gCAAgC,CAAC,CAAA;QACxE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,uBAAuB,CAAC,8BAA8B,CAAC,CAAA;QACtE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,uBAAuB,CAAC,iCAAiC,CAAC,CAAA;QACzE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,uBAAuB,CAAC,gCAAgC,CAAC,CAAA;QACxE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,uBAAuB,CAAC,kCAAkC,CAAC,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,uBAAuB,CACpC,wEAAwE,CACzE,CAAA;QACD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,uBAAuB,CAAC,kCAAkC,CAAC,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,uBAAuB,CAAC,8BAA8B,CAAC,CAAA;QACtE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,uBAAuB,CAAC,wCAAwC,CAAC,CAAA;QAChF,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9E,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,uBAAuB,CAAC,sDAAsD,CAAC,CAAA;QAC9F,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnF,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,uBAAuB,CAAC,8BAA8B,CAAC,CAAA;QACtE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,uBAAuB,CAAC,uCAAuC,CAAC,CAAA;QAC/E,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;IAClF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/B,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/B,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/commands/install.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-3484: CLI Install Command Tests (Wave 1)
|
|
3
|
+
*
|
|
4
|
+
* Tests for the install command that installs skills from registry/GitHub.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Mock Setup - Must be before imports
|
|
10
|
+
// ============================================================================
|
|
11
|
+
const mocks = vi.hoisted(() => ({
|
|
12
|
+
spinner: {
|
|
13
|
+
start: vi.fn().mockReturnThis(),
|
|
14
|
+
stop: vi.fn().mockReturnThis(),
|
|
15
|
+
succeed: vi.fn().mockReturnThis(),
|
|
16
|
+
fail: vi.fn().mockReturnThis(),
|
|
17
|
+
warn: vi.fn().mockReturnThis(),
|
|
18
|
+
text: '',
|
|
19
|
+
},
|
|
20
|
+
installFn: vi.fn(),
|
|
21
|
+
createDatabaseAsync: vi.fn(),
|
|
22
|
+
initializeSchema: vi.fn(),
|
|
23
|
+
dbClose: vi.fn(),
|
|
24
|
+
}));
|
|
25
|
+
vi.mock('ora', () => ({
|
|
26
|
+
default: () => mocks.spinner,
|
|
27
|
+
}));
|
|
28
|
+
vi.mock('@skillsmith/core', () => ({
|
|
29
|
+
createDatabaseAsync: (...args) => mocks.createDatabaseAsync(...args),
|
|
30
|
+
initializeSchema: (...args) => mocks.initializeSchema(...args),
|
|
31
|
+
SkillRepository: vi.fn().mockImplementation(function () {
|
|
32
|
+
return {
|
|
33
|
+
findById: vi.fn(() => null),
|
|
34
|
+
findAll: vi.fn(() => ({ items: [], total: 0, limit: 1000, offset: 0, hasMore: false })),
|
|
35
|
+
};
|
|
36
|
+
}),
|
|
37
|
+
SkillDependencyRepository: vi.fn().mockImplementation(function () {
|
|
38
|
+
return {
|
|
39
|
+
clearAll: vi.fn(),
|
|
40
|
+
};
|
|
41
|
+
}),
|
|
42
|
+
SkillInstallationService: vi.fn().mockImplementation(function () {
|
|
43
|
+
return {
|
|
44
|
+
install: mocks.installFn,
|
|
45
|
+
};
|
|
46
|
+
}),
|
|
47
|
+
isGitHubUrl: vi.fn((url) => url.startsWith('https://github.com/')),
|
|
48
|
+
}));
|
|
49
|
+
// Mock console and process.exit
|
|
50
|
+
const originalConsoleLog = console.log;
|
|
51
|
+
const originalConsoleError = console.error;
|
|
52
|
+
const mockConsoleLog = vi.fn();
|
|
53
|
+
const mockConsoleError = vi.fn();
|
|
54
|
+
const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Tests
|
|
57
|
+
// ============================================================================
|
|
58
|
+
describe('SMI-3484: CLI Install Command', () => {
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
vi.clearAllMocks();
|
|
61
|
+
console.log = mockConsoleLog;
|
|
62
|
+
console.error = mockConsoleError;
|
|
63
|
+
// Default: database opens and closes successfully
|
|
64
|
+
const mockDb = { close: mocks.dbClose };
|
|
65
|
+
mocks.createDatabaseAsync.mockResolvedValue(mockDb);
|
|
66
|
+
// Default: install succeeds
|
|
67
|
+
mocks.installFn.mockResolvedValue({
|
|
68
|
+
success: true,
|
|
69
|
+
skillId: 'community/jest-helper',
|
|
70
|
+
installPath: '/tmp/.claude/skills/jest-helper',
|
|
71
|
+
trustTier: 'community',
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
afterEach(() => {
|
|
75
|
+
console.log = originalConsoleLog;
|
|
76
|
+
console.error = originalConsoleError;
|
|
77
|
+
});
|
|
78
|
+
// ==========================================================================
|
|
79
|
+
// Command Registration
|
|
80
|
+
// ==========================================================================
|
|
81
|
+
describe('command registration', () => {
|
|
82
|
+
it('should create a Command instance named "install"', async () => {
|
|
83
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
84
|
+
const cmd = createInstallCommand();
|
|
85
|
+
expect(cmd).toBeInstanceOf(Command);
|
|
86
|
+
expect(cmd.name()).toBe('install');
|
|
87
|
+
});
|
|
88
|
+
it('should have a description mentioning install', async () => {
|
|
89
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
90
|
+
const cmd = createInstallCommand();
|
|
91
|
+
expect(cmd.description().toLowerCase()).toContain('install');
|
|
92
|
+
});
|
|
93
|
+
it('should have --force option with short flag -f', async () => {
|
|
94
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
95
|
+
const cmd = createInstallCommand();
|
|
96
|
+
const forceOpt = cmd.options.find((o) => o.short === '-f');
|
|
97
|
+
expect(forceOpt).toBeDefined();
|
|
98
|
+
expect(forceOpt?.long).toBe('--force');
|
|
99
|
+
});
|
|
100
|
+
it('should have --skip-scan option', async () => {
|
|
101
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
102
|
+
const cmd = createInstallCommand();
|
|
103
|
+
const opt = cmd.options.find((o) => o.long === '--skip-scan');
|
|
104
|
+
expect(opt).toBeDefined();
|
|
105
|
+
});
|
|
106
|
+
it('should have --skip-optimize option', async () => {
|
|
107
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
108
|
+
const cmd = createInstallCommand();
|
|
109
|
+
const opt = cmd.options.find((o) => o.long === '--skip-optimize');
|
|
110
|
+
expect(opt).toBeDefined();
|
|
111
|
+
});
|
|
112
|
+
it('should have --quiet option with short flag -q', async () => {
|
|
113
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
114
|
+
const cmd = createInstallCommand();
|
|
115
|
+
const opt = cmd.options.find((o) => o.short === '-q');
|
|
116
|
+
expect(opt).toBeDefined();
|
|
117
|
+
expect(opt?.long).toBe('--quiet');
|
|
118
|
+
});
|
|
119
|
+
it('should have --json option', async () => {
|
|
120
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
121
|
+
const cmd = createInstallCommand();
|
|
122
|
+
const opt = cmd.options.find((o) => o.long === '--json');
|
|
123
|
+
expect(opt).toBeDefined();
|
|
124
|
+
});
|
|
125
|
+
it('should have --db option with short flag -d', async () => {
|
|
126
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
127
|
+
const cmd = createInstallCommand();
|
|
128
|
+
const opt = cmd.options.find((o) => o.short === '-d');
|
|
129
|
+
expect(opt).toBeDefined();
|
|
130
|
+
expect(opt?.long).toBe('--db');
|
|
131
|
+
});
|
|
132
|
+
it('should require a skillId argument', async () => {
|
|
133
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
134
|
+
const cmd = createInstallCommand();
|
|
135
|
+
expect(cmd.registeredArguments.length).toBe(1);
|
|
136
|
+
expect(cmd.registeredArguments[0]?.required).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
// ==========================================================================
|
|
140
|
+
// Argument Parsing
|
|
141
|
+
// ==========================================================================
|
|
142
|
+
describe('argument parsing', () => {
|
|
143
|
+
it('should accept valid author/name format', async () => {
|
|
144
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
145
|
+
const cmd = createInstallCommand();
|
|
146
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
147
|
+
expect(mocks.installFn).toHaveBeenCalledWith('community/jest-helper', expect.any(Object));
|
|
148
|
+
});
|
|
149
|
+
it('should accept GitHub URL', async () => {
|
|
150
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
151
|
+
const cmd = createInstallCommand();
|
|
152
|
+
const url = 'https://github.com/owner/repo';
|
|
153
|
+
await cmd.parseAsync(['node', 'test', url]);
|
|
154
|
+
expect(mocks.installFn).toHaveBeenCalledWith(url, expect.any(Object));
|
|
155
|
+
});
|
|
156
|
+
it('should reject bare name without author prefix', async () => {
|
|
157
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
158
|
+
const cmd = createInstallCommand();
|
|
159
|
+
await cmd.parseAsync(['node', 'test', 'jest-helper']);
|
|
160
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
161
|
+
expect(mocks.installFn).not.toHaveBeenCalled();
|
|
162
|
+
});
|
|
163
|
+
it('should reject invalid format with multiple slashes', async () => {
|
|
164
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
165
|
+
const cmd = createInstallCommand();
|
|
166
|
+
await cmd.parseAsync(['node', 'test', 'a/b/c']);
|
|
167
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
168
|
+
expect(mocks.installFn).not.toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
it('should reject empty author segment', async () => {
|
|
171
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
172
|
+
const cmd = createInstallCommand();
|
|
173
|
+
await cmd.parseAsync(['node', 'test', '/name']);
|
|
174
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
175
|
+
expect(mocks.installFn).not.toHaveBeenCalled();
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
// ==========================================================================
|
|
179
|
+
// Happy Path
|
|
180
|
+
// ==========================================================================
|
|
181
|
+
describe('happy path', () => {
|
|
182
|
+
it('should install a skill and show success', async () => {
|
|
183
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
184
|
+
const cmd = createInstallCommand();
|
|
185
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
186
|
+
expect(mocks.spinner.succeed).toHaveBeenCalledWith('Skill installed');
|
|
187
|
+
expect(mocks.dbClose).toHaveBeenCalled();
|
|
188
|
+
});
|
|
189
|
+
it('should pass --force option to install service', async () => {
|
|
190
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
191
|
+
const cmd = createInstallCommand();
|
|
192
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--force']);
|
|
193
|
+
expect(mocks.installFn).toHaveBeenCalledWith('community/jest-helper', expect.objectContaining({ force: true }));
|
|
194
|
+
});
|
|
195
|
+
it('should pass --skip-scan option to install service', async () => {
|
|
196
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
197
|
+
const cmd = createInstallCommand();
|
|
198
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--skip-scan']);
|
|
199
|
+
expect(mocks.installFn).toHaveBeenCalledWith('community/jest-helper', expect.objectContaining({ skipScan: true }));
|
|
200
|
+
});
|
|
201
|
+
it('should pass --skip-optimize option to install service', async () => {
|
|
202
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
203
|
+
const cmd = createInstallCommand();
|
|
204
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--skip-optimize']);
|
|
205
|
+
expect(mocks.installFn).toHaveBeenCalledWith('community/jest-helper', expect.objectContaining({ skipOptimize: true }));
|
|
206
|
+
});
|
|
207
|
+
it('should close database after successful install', async () => {
|
|
208
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
209
|
+
const cmd = createInstallCommand();
|
|
210
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
211
|
+
expect(mocks.dbClose).toHaveBeenCalled();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
// ==========================================================================
|
|
215
|
+
// Already Installed
|
|
216
|
+
// ==========================================================================
|
|
217
|
+
describe('already installed', () => {
|
|
218
|
+
it('should fail when skill is already installed', async () => {
|
|
219
|
+
mocks.installFn.mockResolvedValue({
|
|
220
|
+
success: false,
|
|
221
|
+
skillId: 'community/jest-helper',
|
|
222
|
+
installPath: '/tmp/.claude/skills/jest-helper',
|
|
223
|
+
error: 'Skill "jest-helper" is already installed. Use force=true to reinstall.',
|
|
224
|
+
});
|
|
225
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
226
|
+
const cmd = createInstallCommand();
|
|
227
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
228
|
+
expect(mocks.spinner.fail).toHaveBeenCalledWith('Installation failed');
|
|
229
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
230
|
+
});
|
|
231
|
+
it('should succeed with --force when already installed', async () => {
|
|
232
|
+
mocks.installFn.mockResolvedValue({
|
|
233
|
+
success: true,
|
|
234
|
+
skillId: 'community/jest-helper',
|
|
235
|
+
installPath: '/tmp/.claude/skills/jest-helper',
|
|
236
|
+
});
|
|
237
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
238
|
+
const cmd = createInstallCommand();
|
|
239
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--force']);
|
|
240
|
+
expect(mocks.installFn).toHaveBeenCalledWith('community/jest-helper', expect.objectContaining({ force: true }));
|
|
241
|
+
expect(mocks.spinner.succeed).toHaveBeenCalled();
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
// ==========================================================================
|
|
245
|
+
// --quiet Flag
|
|
246
|
+
// ==========================================================================
|
|
247
|
+
describe('--quiet flag', () => {
|
|
248
|
+
it('should suppress advisory output when --quiet is set', async () => {
|
|
249
|
+
mocks.installFn.mockResolvedValue({
|
|
250
|
+
success: true,
|
|
251
|
+
skillId: 'community/jest-helper',
|
|
252
|
+
installPath: '/tmp/.claude/skills/jest-helper',
|
|
253
|
+
tips: ['Tip: Use the skill by invoking /jest-helper'],
|
|
254
|
+
optimization: {
|
|
255
|
+
optimized: true,
|
|
256
|
+
tokenReductionPercent: 30,
|
|
257
|
+
subSkills: ['sub1.md'],
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
261
|
+
const cmd = createInstallCommand();
|
|
262
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--quiet']);
|
|
263
|
+
// Tips and optimization info should be suppressed
|
|
264
|
+
const allOutput = mockConsoleLog.mock.calls.map((c) => c.join(' ')).join('\n');
|
|
265
|
+
expect(allOutput).not.toContain('Tip:');
|
|
266
|
+
expect(allOutput).not.toContain('reduction');
|
|
267
|
+
});
|
|
268
|
+
it('should still show security-critical errors when --quiet is set', async () => {
|
|
269
|
+
mocks.installFn.mockResolvedValue({
|
|
270
|
+
success: false,
|
|
271
|
+
skillId: 'community/dangerous-skill',
|
|
272
|
+
installPath: '',
|
|
273
|
+
error: 'Security scan failed with 2 critical/high findings',
|
|
274
|
+
securityReport: {
|
|
275
|
+
passed: false,
|
|
276
|
+
riskScore: 85,
|
|
277
|
+
findings: [{ severity: 'critical', message: 'Dangerous command execution detected' }],
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
281
|
+
const cmd = createInstallCommand();
|
|
282
|
+
await cmd.parseAsync(['node', 'test', 'community/dangerous-skill', '--quiet']);
|
|
283
|
+
const errorOutput = mockConsoleError.mock.calls.map((c) => c.join(' ')).join('\n');
|
|
284
|
+
expect(errorOutput).toContain('Security scan failed');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
// ==========================================================================
|
|
288
|
+
// --json Flag
|
|
289
|
+
// ==========================================================================
|
|
290
|
+
describe('--json flag', () => {
|
|
291
|
+
it('should output structured JSON on success', async () => {
|
|
292
|
+
mocks.installFn.mockResolvedValue({
|
|
293
|
+
success: true,
|
|
294
|
+
skillId: 'community/jest-helper',
|
|
295
|
+
installPath: '/tmp/.claude/skills/jest-helper',
|
|
296
|
+
trustTier: 'community',
|
|
297
|
+
});
|
|
298
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
299
|
+
const cmd = createInstallCommand();
|
|
300
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--json']);
|
|
301
|
+
// Find the JSON output call
|
|
302
|
+
const jsonCalls = mockConsoleLog.mock.calls.filter((c) => {
|
|
303
|
+
try {
|
|
304
|
+
JSON.parse(c[0]);
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
expect(jsonCalls.length).toBeGreaterThan(0);
|
|
312
|
+
const parsed = JSON.parse(jsonCalls[0][0]);
|
|
313
|
+
expect(parsed.success).toBe(true);
|
|
314
|
+
expect(parsed.skillId).toBe('community/jest-helper');
|
|
315
|
+
expect(parsed.installPath).toBe('/tmp/.claude/skills/jest-helper');
|
|
316
|
+
});
|
|
317
|
+
it('should output structured JSON on failure', async () => {
|
|
318
|
+
mocks.installFn.mockResolvedValue({
|
|
319
|
+
success: false,
|
|
320
|
+
skillId: 'community/missing',
|
|
321
|
+
installPath: '',
|
|
322
|
+
error: 'Skill not found',
|
|
323
|
+
});
|
|
324
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
325
|
+
const cmd = createInstallCommand();
|
|
326
|
+
await cmd.parseAsync(['node', 'test', 'community/missing', '--json']);
|
|
327
|
+
const jsonCalls = mockConsoleLog.mock.calls.filter((c) => {
|
|
328
|
+
try {
|
|
329
|
+
JSON.parse(c[0]);
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
expect(jsonCalls.length).toBeGreaterThan(0);
|
|
337
|
+
const parsed = JSON.parse(jsonCalls[0][0]);
|
|
338
|
+
expect(parsed.success).toBe(false);
|
|
339
|
+
expect(parsed.error).toBe('Skill not found');
|
|
340
|
+
});
|
|
341
|
+
it('should output JSON for invalid format errors', async () => {
|
|
342
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
343
|
+
const cmd = createInstallCommand();
|
|
344
|
+
await cmd.parseAsync(['node', 'test', 'invalid', '--json']);
|
|
345
|
+
const jsonCalls = mockConsoleLog.mock.calls.filter((c) => {
|
|
346
|
+
try {
|
|
347
|
+
JSON.parse(c[0]);
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
expect(jsonCalls.length).toBeGreaterThan(0);
|
|
355
|
+
const parsed = JSON.parse(jsonCalls[0][0]);
|
|
356
|
+
expect(parsed.success).toBe(false);
|
|
357
|
+
expect(parsed.error).toContain('Invalid skill ID format');
|
|
358
|
+
});
|
|
359
|
+
it('should not show spinner when --json is set', async () => {
|
|
360
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
361
|
+
const cmd = createInstallCommand();
|
|
362
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper', '--json']);
|
|
363
|
+
// Spinner should not be started in JSON mode
|
|
364
|
+
expect(mocks.spinner.start).not.toHaveBeenCalled();
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
// ==========================================================================
|
|
368
|
+
// Error Handling
|
|
369
|
+
// ==========================================================================
|
|
370
|
+
describe('error handling', () => {
|
|
371
|
+
it('should exit with code 1 on install failure', async () => {
|
|
372
|
+
mocks.installFn.mockResolvedValue({
|
|
373
|
+
success: false,
|
|
374
|
+
skillId: 'community/missing',
|
|
375
|
+
installPath: '',
|
|
376
|
+
error: 'Skill not found',
|
|
377
|
+
});
|
|
378
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
379
|
+
const cmd = createInstallCommand();
|
|
380
|
+
await cmd.parseAsync(['node', 'test', 'community/missing']);
|
|
381
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
382
|
+
});
|
|
383
|
+
it('should handle database connection errors', async () => {
|
|
384
|
+
mocks.createDatabaseAsync.mockRejectedValue(new Error('Database locked'));
|
|
385
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
386
|
+
const cmd = createInstallCommand();
|
|
387
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
388
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
389
|
+
});
|
|
390
|
+
it('should sanitize error messages', async () => {
|
|
391
|
+
mocks.createDatabaseAsync.mockRejectedValue(new Error('Error at /Users/testuser/secret/path'));
|
|
392
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
393
|
+
const cmd = createInstallCommand();
|
|
394
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
395
|
+
const errorOutput = mockConsoleError.mock.calls.map((c) => c.join(' ')).join(' ');
|
|
396
|
+
expect(errorOutput).not.toContain('/Users/testuser/');
|
|
397
|
+
});
|
|
398
|
+
it('should close database even on error', async () => {
|
|
399
|
+
mocks.installFn.mockRejectedValue(new Error('Unexpected error'));
|
|
400
|
+
const { createInstallCommand } = await import('../../../src/commands/install.js');
|
|
401
|
+
const cmd = createInstallCommand();
|
|
402
|
+
await cmd.parseAsync(['node', 'test', 'community/jest-helper']);
|
|
403
|
+
expect(mocks.dbClose).toHaveBeenCalled();
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
//# sourceMappingURL=install.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../../../tests/unit/commands/install.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":";AAMA,wBAQE"}
|
package/dist/vitest.config.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
// SMI-3502: CLI coverage thresholds intentionally omitted.
|
|
2
|
+
// Root config excludes packages/cli/** from aggregate coverage (CLI is integration-tested).
|
|
3
|
+
// CLI unit coverage is ~45% — insufficient for thresholds. E2E tests cover CLI behavior.
|
|
1
4
|
import { defineConfig } from 'vitest/config';
|
|
5
|
+
import { sharedTestConfig, coverageDefaults } from '../../vitest.preset';
|
|
2
6
|
export default defineConfig({
|
|
3
7
|
test: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
...sharedTestConfig,
|
|
9
|
+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts', 'src/**/*.spec.ts'],
|
|
10
|
+
coverage: {
|
|
11
|
+
...coverageDefaults,
|
|
12
|
+
},
|
|
7
13
|
},
|
|
8
14
|
});
|
|
9
15
|
//# sourceMappingURL=vitest.config.js.map
|