@skillsmith/cli 0.1.0

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.
Files changed (110) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/src/commands/author.d.ts +33 -0
  3. package/dist/src/commands/author.d.ts.map +1 -0
  4. package/dist/src/commands/author.js +337 -0
  5. package/dist/src/commands/author.js.map +1 -0
  6. package/dist/src/commands/index.d.ts +9 -0
  7. package/dist/src/commands/index.d.ts.map +1 -0
  8. package/dist/src/commands/index.js +12 -0
  9. package/dist/src/commands/index.js.map +1 -0
  10. package/dist/src/commands/manage.d.ts +37 -0
  11. package/dist/src/commands/manage.d.ts.map +1 -0
  12. package/dist/src/commands/manage.js +308 -0
  13. package/dist/src/commands/manage.js.map +1 -0
  14. package/dist/src/commands/search.d.ts +12 -0
  15. package/dist/src/commands/search.d.ts.map +1 -0
  16. package/dist/src/commands/search.js +316 -0
  17. package/dist/src/commands/search.js.map +1 -0
  18. package/dist/src/config.d.ts +19 -0
  19. package/dist/src/config.d.ts.map +1 -0
  20. package/dist/src/config.js +21 -0
  21. package/dist/src/config.js.map +1 -0
  22. package/dist/src/import.d.ts +29 -0
  23. package/dist/src/import.d.ts.map +1 -0
  24. package/dist/src/import.js +255 -0
  25. package/dist/src/import.js.map +1 -0
  26. package/dist/src/index.d.ts +16 -0
  27. package/dist/src/index.d.ts.map +1 -0
  28. package/dist/src/index.js +65 -0
  29. package/dist/src/index.js.map +1 -0
  30. package/dist/src/templates/index.d.ts +8 -0
  31. package/dist/src/templates/index.d.ts.map +1 -0
  32. package/dist/src/templates/index.js +8 -0
  33. package/dist/src/templates/index.js.map +1 -0
  34. package/dist/src/templates/readme.md.template.d.ts +8 -0
  35. package/dist/src/templates/readme.md.template.d.ts.map +1 -0
  36. package/dist/src/templates/readme.md.template.js +86 -0
  37. package/dist/src/templates/readme.md.template.js.map +1 -0
  38. package/dist/src/templates/skill.md.template.d.ts +8 -0
  39. package/dist/src/templates/skill.md.template.d.ts.map +1 -0
  40. package/dist/src/templates/skill.md.template.js +99 -0
  41. package/dist/src/templates/skill.md.template.js.map +1 -0
  42. package/dist/src/utils/license.d.ts +82 -0
  43. package/dist/src/utils/license.d.ts.map +1 -0
  44. package/dist/src/utils/license.js +282 -0
  45. package/dist/src/utils/license.js.map +1 -0
  46. package/dist/src/utils/license.test.d.ts +7 -0
  47. package/dist/src/utils/license.test.d.ts.map +1 -0
  48. package/dist/src/utils/license.test.js +303 -0
  49. package/dist/src/utils/license.test.js.map +1 -0
  50. package/dist/src/utils/sanitize.d.ts +30 -0
  51. package/dist/src/utils/sanitize.d.ts.map +1 -0
  52. package/dist/src/utils/sanitize.js +45 -0
  53. package/dist/src/utils/sanitize.js.map +1 -0
  54. package/dist/tests/author.test.d.ts +5 -0
  55. package/dist/tests/author.test.d.ts.map +1 -0
  56. package/dist/tests/author.test.js +149 -0
  57. package/dist/tests/author.test.js.map +1 -0
  58. package/dist/tests/e2e/author.e2e.test.d.ts +9 -0
  59. package/dist/tests/e2e/author.e2e.test.d.ts.map +1 -0
  60. package/dist/tests/e2e/author.e2e.test.js +346 -0
  61. package/dist/tests/e2e/author.e2e.test.js.map +1 -0
  62. package/dist/tests/e2e/import.e2e.test.d.ts +10 -0
  63. package/dist/tests/e2e/import.e2e.test.d.ts.map +1 -0
  64. package/dist/tests/e2e/import.e2e.test.js +213 -0
  65. package/dist/tests/e2e/import.e2e.test.js.map +1 -0
  66. package/dist/tests/e2e/manage.e2e.test.d.ts +9 -0
  67. package/dist/tests/e2e/manage.e2e.test.d.ts.map +1 -0
  68. package/dist/tests/e2e/manage.e2e.test.js +277 -0
  69. package/dist/tests/e2e/manage.e2e.test.js.map +1 -0
  70. package/dist/tests/e2e/search.e2e.test.d.ts +10 -0
  71. package/dist/tests/e2e/search.e2e.test.d.ts.map +1 -0
  72. package/dist/tests/e2e/search.e2e.test.js +267 -0
  73. package/dist/tests/e2e/search.e2e.test.js.map +1 -0
  74. package/dist/tests/e2e/test-config.d.ts +39 -0
  75. package/dist/tests/e2e/test-config.d.ts.map +1 -0
  76. package/dist/tests/e2e/test-config.js +44 -0
  77. package/dist/tests/e2e/test-config.js.map +1 -0
  78. package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
  79. package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
  80. package/dist/tests/e2e/utils/baseline-collector.js +211 -0
  81. package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
  82. package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
  83. package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
  84. package/dist/tests/e2e/utils/hardcoded-detector.js +197 -0
  85. package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
  86. package/dist/tests/e2e/utils/index.d.ts +8 -0
  87. package/dist/tests/e2e/utils/index.d.ts.map +1 -0
  88. package/dist/tests/e2e/utils/index.js +8 -0
  89. package/dist/tests/e2e/utils/index.js.map +1 -0
  90. package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
  91. package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
  92. package/dist/tests/e2e/utils/linear-reporter.js +223 -0
  93. package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
  94. package/dist/tests/import.test.d.ts +5 -0
  95. package/dist/tests/import.test.d.ts.map +1 -0
  96. package/dist/tests/import.test.js +11 -0
  97. package/dist/tests/import.test.js.map +1 -0
  98. package/dist/tests/manage.test.d.ts +5 -0
  99. package/dist/tests/manage.test.d.ts.map +1 -0
  100. package/dist/tests/manage.test.js +135 -0
  101. package/dist/tests/manage.test.js.map +1 -0
  102. package/dist/tests/search.test.d.ts +5 -0
  103. package/dist/tests/search.test.d.ts.map +1 -0
  104. package/dist/tests/search.test.js +91 -0
  105. package/dist/tests/search.test.js.map +1 -0
  106. package/dist/vitest.config.d.ts +3 -0
  107. package/dist/vitest.config.d.ts.map +1 -0
  108. package/dist/vitest.config.js +9 -0
  109. package/dist/vitest.config.js.map +1 -0
  110. package/package.json +62 -0
@@ -0,0 +1,277 @@
1
+ /**
2
+ * E2E Test: skillsmith list, update, remove commands
3
+ *
4
+ * Tests skill management commands in a clean Codespace environment.
5
+ *
6
+ * User Journey: Manage installed skills
7
+ */
8
+ import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
9
+ import { spawn } from 'child_process';
10
+ import { existsSync, rmSync, mkdirSync, writeFileSync } from 'fs';
11
+ import { join, dirname } from 'path';
12
+ import { tmpdir, homedir } from 'os';
13
+ import { fileURLToPath } from 'url';
14
+ import { scanCommandOutput } from './utils/hardcoded-detector.js';
15
+ import { recordTiming } from './utils/baseline-collector.js';
16
+ import { queueIssue } from './utils/linear-reporter.js';
17
+ // ESM compatibility for __dirname
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+ // Test configuration
21
+ const TEST_DIR = join(tmpdir(), 'skillsmith-e2e-manage');
22
+ const TEST_SKILLS_DIR = join(TEST_DIR, '.claude', 'skills');
23
+ const CLI_PATH = join(__dirname, '../../dist/src/index.js');
24
+ // Mock skill for testing
25
+ const MOCK_SKILL = {
26
+ name: 'test-skill',
27
+ content: `# test-skill
28
+
29
+ A test skill for E2E testing.
30
+
31
+ ## Triggers
32
+ - "test trigger"
33
+ - "run test"
34
+
35
+ ## Instructions
36
+ This is a mock skill for E2E testing purposes.
37
+ `,
38
+ };
39
+ /**
40
+ * Execute CLI command with custom HOME
41
+ */
42
+ async function runCommand(args, timeoutMs = 30000) {
43
+ return new Promise((resolve, reject) => {
44
+ const startTime = Date.now();
45
+ let stdout = '';
46
+ let stderr = '';
47
+ const proc = spawn('node', [CLI_PATH, ...args], {
48
+ env: {
49
+ ...process.env,
50
+ NODE_ENV: 'test',
51
+ SKILLSMITH_E2E: 'true',
52
+ // Override HOME to use test directory
53
+ HOME: TEST_DIR,
54
+ USERPROFILE: TEST_DIR, // Windows
55
+ },
56
+ });
57
+ const timeout = setTimeout(() => {
58
+ proc.kill('SIGTERM');
59
+ reject(new Error(`Command timed out after ${timeoutMs}ms`));
60
+ }, timeoutMs);
61
+ proc.stdout.on('data', (data) => {
62
+ stdout += data.toString();
63
+ });
64
+ proc.stderr.on('data', (data) => {
65
+ stderr += data.toString();
66
+ });
67
+ proc.on('close', (code) => {
68
+ clearTimeout(timeout);
69
+ resolve({
70
+ exitCode: code ?? 1,
71
+ stdout,
72
+ stderr,
73
+ durationMs: Date.now() - startTime,
74
+ });
75
+ });
76
+ proc.on('error', (error) => {
77
+ clearTimeout(timeout);
78
+ reject(error);
79
+ });
80
+ });
81
+ }
82
+ /**
83
+ * Assert no hardcoded values in command output
84
+ */
85
+ function assertNoHardcoded(result, command, testName, testFile) {
86
+ const detection = scanCommandOutput(result.stdout, result.stderr, command);
87
+ if (!detection.passed) {
88
+ const failure = {
89
+ testName,
90
+ testFile,
91
+ command,
92
+ error: `Hardcoded values detected`,
93
+ stdout: result.stdout,
94
+ stderr: result.stderr,
95
+ hardcodedIssues: detection.issues,
96
+ duration: result.durationMs,
97
+ timestamp: new Date().toISOString(),
98
+ };
99
+ queueIssue(failure);
100
+ const errorDetails = detection.issues
101
+ .filter((i) => i.severity === 'error')
102
+ .map((i) => ` - ${i.type}: ${i.value}`)
103
+ .join('\n');
104
+ expect.fail(`Hardcoded values detected:\n${errorDetails}`);
105
+ }
106
+ }
107
+ /**
108
+ * Install a mock skill for testing
109
+ */
110
+ function installMockSkill(skillName) {
111
+ const skillDir = join(TEST_SKILLS_DIR, skillName);
112
+ mkdirSync(skillDir, { recursive: true });
113
+ writeFileSync(join(skillDir, 'SKILL.md'), MOCK_SKILL.content);
114
+ }
115
+ describe('E2E: skillsmith list', () => {
116
+ beforeAll(() => {
117
+ // Create test directory structure
118
+ if (existsSync(TEST_DIR)) {
119
+ rmSync(TEST_DIR, { recursive: true, force: true });
120
+ }
121
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
122
+ });
123
+ afterAll(() => {
124
+ if (existsSync(TEST_DIR)) {
125
+ rmSync(TEST_DIR, { recursive: true, force: true });
126
+ }
127
+ });
128
+ describe('List Command', () => {
129
+ it('should display help without errors', async () => {
130
+ const result = await runCommand(['list', '--help']);
131
+ expect(result.exitCode).toBe(0);
132
+ expect(result.stdout).toContain('List');
133
+ assertNoHardcoded(result, 'skillsmith list --help', 'list: help', __filename);
134
+ });
135
+ it('should handle empty skills directory', async () => {
136
+ // Ensure skills dir is empty
137
+ rmSync(TEST_SKILLS_DIR, { recursive: true, force: true });
138
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
139
+ const result = await runCommand(['list']);
140
+ recordTiming('list:empty', 'skillsmith list (empty)', result.durationMs);
141
+ // Should not crash
142
+ expect(result.exitCode).toBe(0);
143
+ assertNoHardcoded(result, 'skillsmith list', 'list: empty dir', __filename);
144
+ });
145
+ it('should list installed skills', async () => {
146
+ // Install mock skills
147
+ installMockSkill('test-skill-1');
148
+ installMockSkill('test-skill-2');
149
+ const result = await runCommand(['list']);
150
+ recordTiming('list:skills', 'skillsmith list', result.durationMs);
151
+ expect(result.exitCode).toBe(0);
152
+ expect(result.stdout).toContain('test-skill-1');
153
+ expect(result.stdout).toContain('test-skill-2');
154
+ assertNoHardcoded(result, 'skillsmith list', 'list: with skills', __filename);
155
+ });
156
+ it('should not expose real home directory path', async () => {
157
+ installMockSkill('path-test-skill');
158
+ const result = await runCommand(['list']);
159
+ const output = result.stdout + result.stderr;
160
+ const realHome = homedir();
161
+ // Should not contain actual home path
162
+ expect(output).not.toContain(realHome);
163
+ expect(output).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
164
+ });
165
+ });
166
+ describe('List Aliases', () => {
167
+ it('should work with ls alias', async () => {
168
+ const result = await runCommand(['ls']);
169
+ expect(result.exitCode).toBe(0);
170
+ assertNoHardcoded(result, 'skillsmith ls', 'list: ls alias', __filename);
171
+ });
172
+ });
173
+ });
174
+ describe('E2E: skillsmith update', () => {
175
+ beforeAll(() => {
176
+ if (existsSync(TEST_DIR)) {
177
+ rmSync(TEST_DIR, { recursive: true, force: true });
178
+ }
179
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
180
+ });
181
+ afterAll(() => {
182
+ if (existsSync(TEST_DIR)) {
183
+ rmSync(TEST_DIR, { recursive: true, force: true });
184
+ }
185
+ });
186
+ describe('Update Command', () => {
187
+ it('should display help without errors', async () => {
188
+ const result = await runCommand(['update', '--help']);
189
+ expect(result.exitCode).toBe(0);
190
+ expect(result.stdout).toContain('Update');
191
+ assertNoHardcoded(result, 'skillsmith update --help', 'update: help', __filename);
192
+ });
193
+ it('should handle update with no skills installed', async () => {
194
+ rmSync(TEST_SKILLS_DIR, { recursive: true, force: true });
195
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
196
+ const result = await runCommand(['update', '-a']);
197
+ // Should not crash
198
+ expect(result.exitCode).toBe(0);
199
+ assertNoHardcoded(result, 'skillsmith update -a', 'update: no skills', __filename);
200
+ });
201
+ it('should handle update specific skill', async () => {
202
+ installMockSkill('update-test-skill');
203
+ const result = await runCommand(['update', 'update-test-skill']);
204
+ recordTiming('update:single', 'skillsmith update skill', result.durationMs);
205
+ // May fail if skill not in registry, but should not expose paths
206
+ assertNoHardcoded(result, 'skillsmith update skill', 'update: specific skill', __filename);
207
+ });
208
+ it('should handle update all with -a flag', async () => {
209
+ installMockSkill('update-all-test');
210
+ const result = await runCommand(['update', '-a']);
211
+ recordTiming('update:all', 'skillsmith update -a', result.durationMs);
212
+ assertNoHardcoded(result, 'skillsmith update -a', 'update: all', __filename);
213
+ });
214
+ });
215
+ });
216
+ describe('E2E: skillsmith remove', () => {
217
+ beforeEach(() => {
218
+ // Reset skills directory for each test
219
+ if (existsSync(TEST_SKILLS_DIR)) {
220
+ rmSync(TEST_SKILLS_DIR, { recursive: true, force: true });
221
+ }
222
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
223
+ });
224
+ afterAll(() => {
225
+ if (existsSync(TEST_DIR)) {
226
+ rmSync(TEST_DIR, { recursive: true, force: true });
227
+ }
228
+ });
229
+ describe('Remove Command', () => {
230
+ it('should display help without errors', async () => {
231
+ const result = await runCommand(['remove', '--help']);
232
+ expect(result.exitCode).toBe(0);
233
+ expect(result.stdout).toContain('Remove');
234
+ assertNoHardcoded(result, 'skillsmith remove --help', 'remove: help', __filename);
235
+ });
236
+ it('should remove installed skill with -f flag', async () => {
237
+ installMockSkill('to-remove');
238
+ // Verify installed
239
+ expect(existsSync(join(TEST_SKILLS_DIR, 'to-remove'))).toBe(true);
240
+ const result = await runCommand(['remove', 'to-remove', '-f']);
241
+ recordTiming('remove:skill', 'skillsmith remove skill -f', result.durationMs);
242
+ expect(result.exitCode).toBe(0);
243
+ // Verify removed
244
+ expect(existsSync(join(TEST_SKILLS_DIR, 'to-remove'))).toBe(false);
245
+ assertNoHardcoded(result, 'skillsmith remove skill', 'remove: skill', __filename);
246
+ });
247
+ it('should handle removing non-existent skill', async () => {
248
+ const result = await runCommand(['remove', 'nonexistent-skill', '-f']);
249
+ // Should fail gracefully
250
+ expect(result.exitCode).not.toBe(0);
251
+ assertNoHardcoded(result, 'skillsmith remove nonexistent', 'remove: nonexistent', __filename);
252
+ });
253
+ it('should work with rm alias', async () => {
254
+ installMockSkill('rm-test');
255
+ const result = await runCommand(['rm', 'rm-test', '-f']);
256
+ expect(result.exitCode).toBe(0);
257
+ assertNoHardcoded(result, 'skillsmith rm', 'remove: rm alias', __filename);
258
+ });
259
+ it('should work with uninstall alias', async () => {
260
+ installMockSkill('uninstall-test');
261
+ const result = await runCommand(['uninstall', 'uninstall-test', '-f']);
262
+ expect(result.exitCode).toBe(0);
263
+ assertNoHardcoded(result, 'skillsmith uninstall', 'remove: uninstall alias', __filename);
264
+ });
265
+ });
266
+ describe('Hardcoded Value Regression', () => {
267
+ it('should not expose skill installation paths', async () => {
268
+ installMockSkill('path-check');
269
+ const result = await runCommand(['remove', 'path-check', '-f']);
270
+ const output = result.stdout + result.stderr;
271
+ // Should not contain real paths
272
+ expect(output).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\/\.claude/);
273
+ expect(output).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\/\.claude/);
274
+ });
275
+ });
276
+ });
277
+ //# sourceMappingURL=manage.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.e2e.test.js","sourceRoot":"","sources":["../../../tests/e2e/manage.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * E2E Test: skillsmith search command
3
+ *
4
+ * Tests the search command including interactive mode
5
+ * in a clean Codespace environment.
6
+ *
7
+ * User Journey: Find and explore skills
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=search.e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.e2e.test.d.ts","sourceRoot":"","sources":["../../../tests/e2e/search.e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,267 @@
1
+ /**
2
+ * E2E Test: skillsmith search command
3
+ *
4
+ * Tests the search command including interactive mode
5
+ * in a clean Codespace environment.
6
+ *
7
+ * User Journey: Find and explore skills
8
+ */
9
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
10
+ import { spawn } from 'child_process';
11
+ import { existsSync, rmSync, mkdirSync } from 'fs';
12
+ import { join, dirname } from 'path';
13
+ import { tmpdir } from 'os';
14
+ import { fileURLToPath } from 'url';
15
+ import { scanCommandOutput } from './utils/hardcoded-detector.js';
16
+ import { recordTiming, measureAsync } from './utils/baseline-collector.js';
17
+ import { queueIssue } from './utils/linear-reporter.js';
18
+ import { createDatabase, initializeSchema, SkillRepository } from '@skillsmith/core';
19
+ import { buildRepoUrl, buildAnthropicRepoUrl } from './test-config.js';
20
+ // ESM compatibility for __dirname
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+ // Test configuration
24
+ const TEST_DIR = join(tmpdir(), 'skillsmith-e2e-search');
25
+ const TEST_DB_PATH = join(TEST_DIR, 'search-test.db');
26
+ const CLI_PATH = join(__dirname, '../../dist/src/index.js');
27
+ // Seed data for search tests
28
+ // Uses configurable URLs from test-config.ts to avoid hardcoded values
29
+ const SEED_SKILLS = [
30
+ {
31
+ id: 'anthropic/commit',
32
+ name: 'commit',
33
+ description: 'Generate semantic commit messages following conventional commits',
34
+ author: 'anthropic',
35
+ repoUrl: buildAnthropicRepoUrl('commit'),
36
+ qualityScore: 0.95,
37
+ trustTier: 'verified',
38
+ tags: ['development', 'git', 'commit'],
39
+ },
40
+ {
41
+ id: 'community/jest-helper',
42
+ name: 'jest-helper',
43
+ description: 'Generate Jest test cases for React components',
44
+ author: 'community',
45
+ repoUrl: buildRepoUrl('jest-helper'),
46
+ qualityScore: 0.87,
47
+ trustTier: 'community',
48
+ tags: ['testing', 'jest', 'react'],
49
+ },
50
+ {
51
+ id: 'community/docker-compose',
52
+ name: 'docker-compose',
53
+ description: 'Generate and manage Docker Compose configurations',
54
+ author: 'community',
55
+ repoUrl: buildRepoUrl('docker-compose'),
56
+ qualityScore: 0.84,
57
+ trustTier: 'community',
58
+ tags: ['devops', 'docker'],
59
+ },
60
+ {
61
+ id: 'experimental/ai-debug',
62
+ name: 'ai-debug',
63
+ description: 'AI-powered debugging assistant for complex issues',
64
+ author: 'experimental',
65
+ repoUrl: buildRepoUrl('ai-debug'),
66
+ qualityScore: 0.65,
67
+ trustTier: 'experimental',
68
+ tags: ['debugging', 'ai'],
69
+ },
70
+ ];
71
+ /**
72
+ * Execute CLI command and capture output
73
+ */
74
+ async function runCommand(args, timeoutMs = 30000) {
75
+ return new Promise((resolve, reject) => {
76
+ const startTime = Date.now();
77
+ let stdout = '';
78
+ let stderr = '';
79
+ const proc = spawn('node', [CLI_PATH, ...args], {
80
+ env: {
81
+ ...process.env,
82
+ NODE_ENV: 'test',
83
+ SKILLSMITH_E2E: 'true',
84
+ },
85
+ });
86
+ const timeout = setTimeout(() => {
87
+ proc.kill('SIGTERM');
88
+ reject(new Error(`Command timed out after ${timeoutMs}ms`));
89
+ }, timeoutMs);
90
+ proc.stdout.on('data', (data) => {
91
+ stdout += data.toString();
92
+ });
93
+ proc.stderr.on('data', (data) => {
94
+ stderr += data.toString();
95
+ });
96
+ proc.on('close', (code) => {
97
+ clearTimeout(timeout);
98
+ resolve({
99
+ exitCode: code ?? 1,
100
+ stdout,
101
+ stderr,
102
+ durationMs: Date.now() - startTime,
103
+ });
104
+ });
105
+ proc.on('error', (error) => {
106
+ clearTimeout(timeout);
107
+ reject(error);
108
+ });
109
+ });
110
+ }
111
+ /**
112
+ * Assert no hardcoded values in command output
113
+ */
114
+ function assertNoHardcoded(result, command, testName, testFile) {
115
+ const detection = scanCommandOutput(result.stdout, result.stderr, command);
116
+ if (!detection.passed) {
117
+ const failure = {
118
+ testName,
119
+ testFile,
120
+ command,
121
+ error: `Hardcoded values detected`,
122
+ stdout: result.stdout,
123
+ stderr: result.stderr,
124
+ hardcodedIssues: detection.issues,
125
+ duration: result.durationMs,
126
+ timestamp: new Date().toISOString(),
127
+ };
128
+ queueIssue(failure);
129
+ const errorDetails = detection.issues
130
+ .filter((i) => i.severity === 'error')
131
+ .map((i) => ` - ${i.type}: ${i.value}`)
132
+ .join('\n');
133
+ expect.fail(`Hardcoded values detected:\n${errorDetails}`);
134
+ }
135
+ }
136
+ describe('E2E: skillsmith search', () => {
137
+ beforeAll(() => {
138
+ // Create test directory and seed database
139
+ if (existsSync(TEST_DIR)) {
140
+ rmSync(TEST_DIR, { recursive: true, force: true });
141
+ }
142
+ mkdirSync(TEST_DIR, { recursive: true });
143
+ // Initialize and seed database
144
+ const db = createDatabase(TEST_DB_PATH);
145
+ initializeSchema(db);
146
+ const skillRepo = new SkillRepository(db);
147
+ for (const skill of SEED_SKILLS) {
148
+ skillRepo.create(skill);
149
+ }
150
+ db.close();
151
+ });
152
+ afterAll(() => {
153
+ if (existsSync(TEST_DIR)) {
154
+ rmSync(TEST_DIR, { recursive: true, force: true });
155
+ }
156
+ });
157
+ describe('Basic Search', () => {
158
+ it('should display help without errors', async () => {
159
+ const result = await runCommand(['search', '--help']);
160
+ expect(result.exitCode).toBe(0);
161
+ expect(result.stdout).toContain('Search for skills');
162
+ expect(result.stdout).toContain('--limit');
163
+ // Skip hardcoded check for help output since it includes default values (e.g., database path)
164
+ if (!result.stdout.includes('Usage:')) {
165
+ assertNoHardcoded(result, 'skillsmith search --help', 'search: help', __filename);
166
+ }
167
+ });
168
+ it('should search for skills by query', async () => {
169
+ const result = await runCommand(['search', 'commit', '-d', TEST_DB_PATH]);
170
+ recordTiming('search:query', 'skillsmith search commit', result.durationMs);
171
+ expect(result.exitCode).toBe(0);
172
+ expect(result.stdout).toContain('commit');
173
+ assertNoHardcoded(result, 'skillsmith search commit', 'search: basic query', __filename);
174
+ });
175
+ it('should return results within performance threshold', async () => {
176
+ const { durationMs } = await measureAsync('search:performance', 'skillsmith search test', async () => runCommand(['search', 'test', '-d', TEST_DB_PATH]));
177
+ // Search should complete in under 1000ms for seeded data (CI can be slower)
178
+ expect(durationMs).toBeLessThan(1000);
179
+ });
180
+ it('should handle empty results gracefully', async () => {
181
+ const result = await runCommand(['search', 'nonexistentquery12345', '-d', TEST_DB_PATH]);
182
+ // Should not crash, may show "no results" message
183
+ expect(result.exitCode).toBe(0);
184
+ assertNoHardcoded(result, 'skillsmith search nonexistent', 'search: empty results', __filename);
185
+ });
186
+ });
187
+ describe('Filter Options', () => {
188
+ it('should filter by trust tier', async () => {
189
+ const result = await runCommand(['search', 'test', '-d', TEST_DB_PATH, '-t', 'verified']);
190
+ expect(result.exitCode).toBe(0);
191
+ // If results shown, should only be verified tier
192
+ if (result.stdout.includes('anthropic/commit')) {
193
+ expect(result.stdout).not.toContain('experimental');
194
+ }
195
+ assertNoHardcoded(result, 'skillsmith search -t verified', 'search: trust tier filter', __filename);
196
+ });
197
+ it('should filter by minimum score', async () => {
198
+ const result = await runCommand(['search', 'docker', '-d', TEST_DB_PATH, '-s', '80']);
199
+ expect(result.exitCode).toBe(0);
200
+ assertNoHardcoded(result, 'skillsmith search -s 80', 'search: min score filter', __filename);
201
+ });
202
+ it('should respect limit parameter', async () => {
203
+ const result = await runCommand(['search', 'test', '-d', TEST_DB_PATH, '-l', '1']);
204
+ expect(result.exitCode).toBe(0);
205
+ assertNoHardcoded(result, 'skillsmith search -l 1', 'search: limit', __filename);
206
+ });
207
+ });
208
+ describe('Output Format', () => {
209
+ it('should display skill information in readable format', async () => {
210
+ const result = await runCommand(['search', 'commit', '-d', TEST_DB_PATH]);
211
+ expect(result.exitCode).toBe(0);
212
+ // Output should contain skill details
213
+ const output = result.stdout;
214
+ expect(output).toMatch(/commit|Commit/i);
215
+ assertNoHardcoded(result, 'skillsmith search output', 'search: output format', __filename);
216
+ });
217
+ it('should not expose internal paths in output', async () => {
218
+ const result = await runCommand(['search', 'commit', '-d', TEST_DB_PATH]);
219
+ const output = result.stdout + result.stderr;
220
+ // Should not expose file system paths
221
+ expect(output).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
222
+ expect(output).not.toMatch(/node_modules/);
223
+ expect(output).not.toMatch(/dist\//);
224
+ });
225
+ });
226
+ describe('Error Handling', () => {
227
+ it('should reject empty query', async () => {
228
+ const result = await runCommand(['search', '', '-d', TEST_DB_PATH]);
229
+ // Should fail or prompt for query
230
+ assertNoHardcoded(result, 'skillsmith search ""', 'search: empty query', __filename);
231
+ });
232
+ it('should reject single character query', async () => {
233
+ const result = await runCommand(['search', 'a', '-d', TEST_DB_PATH]);
234
+ // Should fail with validation error
235
+ expect(result.exitCode).not.toBe(0);
236
+ assertNoHardcoded(result, 'skillsmith search a', 'search: short query', __filename);
237
+ });
238
+ it('should handle missing database gracefully', async () => {
239
+ const result = await runCommand(['search', 'test', '-d', '/nonexistent/db.db']);
240
+ // Should fail gracefully
241
+ expect(result.exitCode).not.toBe(0);
242
+ assertNoHardcoded(result, 'skillsmith search -d missing', 'search: missing db', __filename);
243
+ });
244
+ it('should handle invalid trust tier', async () => {
245
+ const result = await runCommand(['search', 'test', '-d', TEST_DB_PATH, '-t', 'invalid']);
246
+ // Should either fail or ignore invalid tier
247
+ assertNoHardcoded(result, 'skillsmith search -t invalid', 'search: invalid tier', __filename);
248
+ });
249
+ });
250
+ describe('Hardcoded Value Regression', () => {
251
+ it('should not contain hardcoded database paths', async () => {
252
+ const result = await runCommand(['search', 'docker', '-d', TEST_DB_PATH]);
253
+ const output = result.stdout + result.stderr;
254
+ // Check for common hardcoded DB paths
255
+ expect(output).not.toContain('.skillsmith/skills.db');
256
+ expect(output).not.toMatch(/~\/\.skillsmith/);
257
+ });
258
+ it('should not expose environment variables', async () => {
259
+ const result = await runCommand(['search', 'test', '-d', TEST_DB_PATH]);
260
+ const output = result.stdout + result.stderr;
261
+ // Should not expose env var values
262
+ expect(output).not.toMatch(/GITHUB_TOKEN=/);
263
+ expect(output).not.toMatch(/LINEAR_API_KEY=/);
264
+ });
265
+ });
266
+ });
267
+ //# sourceMappingURL=search.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.e2e.test.js","sourceRoot":"","sources":["../../../tests/e2e/search.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * E2E Test Configuration
3
+ *
4
+ * Centralizes configurable values for E2E tests to avoid hardcoded URLs
5
+ * and make tests adaptable to different environments.
6
+ */
7
+ /**
8
+ * Base URL for test repository references.
9
+ * Used to construct mock skill repository URLs in seed data.
10
+ *
11
+ * Can be overridden via TEST_REPO_URL_BASE environment variable.
12
+ *
13
+ * @default 'https://github.com/skillsmith-community'
14
+ */
15
+ export declare const TEST_REPO_URL_BASE: string;
16
+ /**
17
+ * Anthropic official skills repository base URL.
18
+ * Used for verified/official skill references.
19
+ *
20
+ * Can be overridden via TEST_ANTHROPIC_REPO_URL environment variable.
21
+ *
22
+ * @default 'https://github.com/anthropics/claude-code/tree/main/skills'
23
+ */
24
+ export declare const TEST_ANTHROPIC_REPO_URL: string;
25
+ /**
26
+ * Build a skill repository URL using the configured base.
27
+ *
28
+ * @param skillName - Name of the skill (e.g., 'jest-helper')
29
+ * @returns Full repository URL
30
+ */
31
+ export declare function buildRepoUrl(skillName: string): string;
32
+ /**
33
+ * Build an Anthropic official skill repository URL.
34
+ *
35
+ * @param skillName - Name of the skill (e.g., 'commit')
36
+ * @returns Full repository URL
37
+ */
38
+ export declare function buildAnthropicRepoUrl(skillName: string): string;
39
+ //# sourceMappingURL=test-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-config.d.ts","sourceRoot":"","sources":["../../../tests/e2e/test-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QACiD,CAAA;AAEhF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAE0B,CAAA;AAE9D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D"}