@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.
- package/dist/.tsbuildinfo +1 -0
- package/dist/src/commands/author.d.ts +33 -0
- package/dist/src/commands/author.d.ts.map +1 -0
- package/dist/src/commands/author.js +337 -0
- package/dist/src/commands/author.js.map +1 -0
- package/dist/src/commands/index.d.ts +9 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +12 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/manage.d.ts +37 -0
- package/dist/src/commands/manage.d.ts.map +1 -0
- package/dist/src/commands/manage.js +308 -0
- package/dist/src/commands/manage.js.map +1 -0
- package/dist/src/commands/search.d.ts +12 -0
- package/dist/src/commands/search.d.ts.map +1 -0
- package/dist/src/commands/search.js +316 -0
- package/dist/src/commands/search.js.map +1 -0
- package/dist/src/config.d.ts +19 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +21 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/import.d.ts +29 -0
- package/dist/src/import.d.ts.map +1 -0
- package/dist/src/import.js +255 -0
- package/dist/src/import.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +65 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/templates/index.d.ts +8 -0
- package/dist/src/templates/index.d.ts.map +1 -0
- package/dist/src/templates/index.js +8 -0
- package/dist/src/templates/index.js.map +1 -0
- package/dist/src/templates/readme.md.template.d.ts +8 -0
- package/dist/src/templates/readme.md.template.d.ts.map +1 -0
- package/dist/src/templates/readme.md.template.js +86 -0
- package/dist/src/templates/readme.md.template.js.map +1 -0
- package/dist/src/templates/skill.md.template.d.ts +8 -0
- package/dist/src/templates/skill.md.template.d.ts.map +1 -0
- package/dist/src/templates/skill.md.template.js +99 -0
- package/dist/src/templates/skill.md.template.js.map +1 -0
- package/dist/src/utils/license.d.ts +82 -0
- package/dist/src/utils/license.d.ts.map +1 -0
- package/dist/src/utils/license.js +282 -0
- package/dist/src/utils/license.js.map +1 -0
- package/dist/src/utils/license.test.d.ts +7 -0
- package/dist/src/utils/license.test.d.ts.map +1 -0
- package/dist/src/utils/license.test.js +303 -0
- package/dist/src/utils/license.test.js.map +1 -0
- package/dist/src/utils/sanitize.d.ts +30 -0
- package/dist/src/utils/sanitize.d.ts.map +1 -0
- package/dist/src/utils/sanitize.js +45 -0
- package/dist/src/utils/sanitize.js.map +1 -0
- package/dist/tests/author.test.d.ts +5 -0
- package/dist/tests/author.test.d.ts.map +1 -0
- package/dist/tests/author.test.js +149 -0
- package/dist/tests/author.test.js.map +1 -0
- package/dist/tests/e2e/author.e2e.test.d.ts +9 -0
- package/dist/tests/e2e/author.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/author.e2e.test.js +346 -0
- package/dist/tests/e2e/author.e2e.test.js.map +1 -0
- package/dist/tests/e2e/import.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/import.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/import.e2e.test.js +213 -0
- package/dist/tests/e2e/import.e2e.test.js.map +1 -0
- package/dist/tests/e2e/manage.e2e.test.d.ts +9 -0
- package/dist/tests/e2e/manage.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/manage.e2e.test.js +277 -0
- package/dist/tests/e2e/manage.e2e.test.js.map +1 -0
- package/dist/tests/e2e/search.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/search.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/search.e2e.test.js +267 -0
- package/dist/tests/e2e/search.e2e.test.js.map +1 -0
- package/dist/tests/e2e/test-config.d.ts +39 -0
- package/dist/tests/e2e/test-config.d.ts.map +1 -0
- package/dist/tests/e2e/test-config.js +44 -0
- package/dist/tests/e2e/test-config.js.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.js +211 -0
- package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js +197 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
- package/dist/tests/e2e/utils/index.d.ts +8 -0
- package/dist/tests/e2e/utils/index.d.ts.map +1 -0
- package/dist/tests/e2e/utils/index.js +8 -0
- package/dist/tests/e2e/utils/index.js.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.js +223 -0
- package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
- package/dist/tests/import.test.d.ts +5 -0
- package/dist/tests/import.test.d.ts.map +1 -0
- package/dist/tests/import.test.js +11 -0
- package/dist/tests/import.test.js.map +1 -0
- package/dist/tests/manage.test.d.ts +5 -0
- package/dist/tests/manage.test.d.ts.map +1 -0
- package/dist/tests/manage.test.js +135 -0
- package/dist/tests/manage.test.js.map +1 -0
- package/dist/tests/search.test.d.ts +5 -0
- package/dist/tests/search.test.d.ts.map +1 -0
- package/dist/tests/search.test.js +91 -0
- package/dist/tests/search.test.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +9 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Test: skillsmith init, validate, publish commands
|
|
3
|
+
*
|
|
4
|
+
* Tests skill authoring commands in a clean Codespace environment.
|
|
5
|
+
*
|
|
6
|
+
* User Journey: Create and publish custom skills
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
9
|
+
import { spawn } from 'child_process';
|
|
10
|
+
import { existsSync, rmSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
11
|
+
import { join, dirname } from 'path';
|
|
12
|
+
import { tmpdir } 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-author');
|
|
22
|
+
const CLI_PATH = join(__dirname, '../../dist/src/index.js');
|
|
23
|
+
// Valid SKILL.md content for validation tests
|
|
24
|
+
const VALID_SKILL_MD = `---
|
|
25
|
+
name: test-skill
|
|
26
|
+
version: 1.0.0
|
|
27
|
+
description: A test skill for E2E testing
|
|
28
|
+
author: test-author
|
|
29
|
+
triggers:
|
|
30
|
+
- test trigger
|
|
31
|
+
- run test
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# test-skill
|
|
35
|
+
|
|
36
|
+
A test skill for E2E testing purposes.
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
Use this skill to test things.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
\`\`\`
|
|
45
|
+
test example
|
|
46
|
+
\`\`\`
|
|
47
|
+
`;
|
|
48
|
+
// Invalid SKILL.md for error testing
|
|
49
|
+
const INVALID_SKILL_MD = `
|
|
50
|
+
# Missing Frontmatter
|
|
51
|
+
|
|
52
|
+
This skill has no frontmatter and should fail validation.
|
|
53
|
+
`;
|
|
54
|
+
/**
|
|
55
|
+
* Execute CLI command
|
|
56
|
+
*/
|
|
57
|
+
async function runCommand(args, cwd, timeoutMs = 30000) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
let stdout = '';
|
|
61
|
+
let stderr = '';
|
|
62
|
+
const proc = spawn('node', [CLI_PATH, ...args], {
|
|
63
|
+
cwd: cwd || TEST_DIR,
|
|
64
|
+
env: {
|
|
65
|
+
...process.env,
|
|
66
|
+
NODE_ENV: 'test',
|
|
67
|
+
SKILLSMITH_E2E: 'true',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
const timeout = setTimeout(() => {
|
|
71
|
+
proc.kill('SIGTERM');
|
|
72
|
+
reject(new Error(`Command timed out after ${timeoutMs}ms`));
|
|
73
|
+
}, timeoutMs);
|
|
74
|
+
proc.stdout.on('data', (data) => {
|
|
75
|
+
stdout += data.toString();
|
|
76
|
+
});
|
|
77
|
+
proc.stderr.on('data', (data) => {
|
|
78
|
+
stderr += data.toString();
|
|
79
|
+
});
|
|
80
|
+
proc.on('close', (code) => {
|
|
81
|
+
clearTimeout(timeout);
|
|
82
|
+
resolve({
|
|
83
|
+
exitCode: code ?? 1,
|
|
84
|
+
stdout,
|
|
85
|
+
stderr,
|
|
86
|
+
durationMs: Date.now() - startTime,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
proc.on('error', (error) => {
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
reject(error);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Assert no hardcoded values in command output
|
|
97
|
+
*/
|
|
98
|
+
function assertNoHardcoded(result, command, testName, testFile) {
|
|
99
|
+
const detection = scanCommandOutput(result.stdout, result.stderr, command);
|
|
100
|
+
if (!detection.passed) {
|
|
101
|
+
const failure = {
|
|
102
|
+
testName,
|
|
103
|
+
testFile,
|
|
104
|
+
command,
|
|
105
|
+
error: `Hardcoded values detected`,
|
|
106
|
+
stdout: result.stdout,
|
|
107
|
+
stderr: result.stderr,
|
|
108
|
+
hardcodedIssues: detection.issues,
|
|
109
|
+
duration: result.durationMs,
|
|
110
|
+
timestamp: new Date().toISOString(),
|
|
111
|
+
};
|
|
112
|
+
queueIssue(failure);
|
|
113
|
+
const errorDetails = detection.issues
|
|
114
|
+
.filter((i) => i.severity === 'error')
|
|
115
|
+
.map((i) => ` - ${i.type}: ${i.value}`)
|
|
116
|
+
.join('\n');
|
|
117
|
+
expect.fail(`Hardcoded values detected:\n${errorDetails}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
describe('E2E: skillsmith init', () => {
|
|
121
|
+
beforeEach(() => {
|
|
122
|
+
// Reset test directory for each test
|
|
123
|
+
if (existsSync(TEST_DIR)) {
|
|
124
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
127
|
+
});
|
|
128
|
+
afterAll(() => {
|
|
129
|
+
if (existsSync(TEST_DIR)) {
|
|
130
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
describe('Init Command', () => {
|
|
134
|
+
it('should display help without errors', async () => {
|
|
135
|
+
const result = await runCommand(['init', '--help']);
|
|
136
|
+
expect(result.exitCode).toBe(0);
|
|
137
|
+
expect(result.stdout).toContain('Initialize');
|
|
138
|
+
assertNoHardcoded(result, 'skillsmith init --help', 'init: help', __filename);
|
|
139
|
+
});
|
|
140
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
141
|
+
it.skip('should create skill scaffold with name', async () => {
|
|
142
|
+
const result = await runCommand(['init', 'my-new-skill']);
|
|
143
|
+
recordTiming('init:named', 'skillsmith init name', result.durationMs);
|
|
144
|
+
expect(result.exitCode).toBe(0);
|
|
145
|
+
// Verify created files
|
|
146
|
+
const skillDir = join(TEST_DIR, 'my-new-skill');
|
|
147
|
+
expect(existsSync(skillDir)).toBe(true);
|
|
148
|
+
expect(existsSync(join(skillDir, 'SKILL.md'))).toBe(true);
|
|
149
|
+
expect(existsSync(join(skillDir, 'README.md'))).toBe(true);
|
|
150
|
+
assertNoHardcoded(result, 'skillsmith init name', 'init: create skill', __filename);
|
|
151
|
+
});
|
|
152
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
153
|
+
it.skip('should create skill scaffold with custom path', async () => {
|
|
154
|
+
const customPath = join(TEST_DIR, 'custom-skills');
|
|
155
|
+
mkdirSync(customPath, { recursive: true });
|
|
156
|
+
const result = await runCommand(['init', 'path-skill', '-p', customPath]);
|
|
157
|
+
expect(result.exitCode).toBe(0);
|
|
158
|
+
// Verify created at custom path
|
|
159
|
+
expect(existsSync(join(customPath, 'path-skill', 'SKILL.md'))).toBe(true);
|
|
160
|
+
assertNoHardcoded(result, 'skillsmith init -p custom', 'init: custom path', __filename);
|
|
161
|
+
});
|
|
162
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
163
|
+
it.skip('should create resources directory', async () => {
|
|
164
|
+
const result = await runCommand(['init', 'resource-skill']);
|
|
165
|
+
expect(result.exitCode).toBe(0);
|
|
166
|
+
const resourceDir = join(TEST_DIR, 'resource-skill', 'resources');
|
|
167
|
+
expect(existsSync(resourceDir)).toBe(true);
|
|
168
|
+
assertNoHardcoded(result, 'skillsmith init resources', 'init: resources dir', __filename);
|
|
169
|
+
});
|
|
170
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
171
|
+
it.skip('should create scripts directory with example', async () => {
|
|
172
|
+
const result = await runCommand(['init', 'script-skill']);
|
|
173
|
+
expect(result.exitCode).toBe(0);
|
|
174
|
+
const scriptsDir = join(TEST_DIR, 'script-skill', 'scripts');
|
|
175
|
+
expect(existsSync(scriptsDir)).toBe(true);
|
|
176
|
+
expect(existsSync(join(scriptsDir, 'example.js'))).toBe(true);
|
|
177
|
+
assertNoHardcoded(result, 'skillsmith init scripts', 'init: scripts dir', __filename);
|
|
178
|
+
});
|
|
179
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
180
|
+
it.skip('should handle existing directory gracefully', async () => {
|
|
181
|
+
// Create skill first
|
|
182
|
+
await runCommand(['init', 'existing-skill']);
|
|
183
|
+
// Try to create again
|
|
184
|
+
const result = await runCommand(['init', 'existing-skill']);
|
|
185
|
+
// Should fail or warn
|
|
186
|
+
assertNoHardcoded(result, 'skillsmith init existing', 'init: existing dir', __filename);
|
|
187
|
+
});
|
|
188
|
+
// Skip: The init command uses inquirer for interactive prompts which cannot be automated in E2E tests
|
|
189
|
+
it.skip('should not contain hardcoded paths in generated files', async () => {
|
|
190
|
+
const result = await runCommand(['init', 'path-check-skill']);
|
|
191
|
+
expect(result.exitCode).toBe(0);
|
|
192
|
+
// Read generated SKILL.md
|
|
193
|
+
const skillMd = readFileSync(join(TEST_DIR, 'path-check-skill', 'SKILL.md'), 'utf-8');
|
|
194
|
+
// Should not contain hardcoded paths
|
|
195
|
+
expect(skillMd).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
|
|
196
|
+
expect(skillMd).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\//);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('E2E: skillsmith validate', () => {
|
|
201
|
+
beforeAll(() => {
|
|
202
|
+
if (existsSync(TEST_DIR)) {
|
|
203
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
204
|
+
}
|
|
205
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
206
|
+
});
|
|
207
|
+
afterAll(() => {
|
|
208
|
+
if (existsSync(TEST_DIR)) {
|
|
209
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
describe('Validate Command', () => {
|
|
213
|
+
it('should display help without errors', async () => {
|
|
214
|
+
const result = await runCommand(['validate', '--help']);
|
|
215
|
+
expect(result.exitCode).toBe(0);
|
|
216
|
+
expect(result.stdout).toContain('Validate');
|
|
217
|
+
assertNoHardcoded(result, 'skillsmith validate --help', 'validate: help', __filename);
|
|
218
|
+
});
|
|
219
|
+
it('should validate valid SKILL.md', async () => {
|
|
220
|
+
// Create valid skill
|
|
221
|
+
const skillDir = join(TEST_DIR, 'valid-skill');
|
|
222
|
+
mkdirSync(skillDir, { recursive: true });
|
|
223
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
224
|
+
const result = await runCommand(['validate', skillDir]);
|
|
225
|
+
recordTiming('validate:valid', 'skillsmith validate valid', result.durationMs);
|
|
226
|
+
expect(result.exitCode).toBe(0);
|
|
227
|
+
assertNoHardcoded(result, 'skillsmith validate valid', 'validate: valid skill', __filename);
|
|
228
|
+
});
|
|
229
|
+
it('should reject invalid SKILL.md', async () => {
|
|
230
|
+
// Create invalid skill
|
|
231
|
+
const skillDir = join(TEST_DIR, 'invalid-skill');
|
|
232
|
+
mkdirSync(skillDir, { recursive: true });
|
|
233
|
+
writeFileSync(join(skillDir, 'SKILL.md'), INVALID_SKILL_MD);
|
|
234
|
+
const result = await runCommand(['validate', skillDir]);
|
|
235
|
+
recordTiming('validate:invalid', 'skillsmith validate invalid', result.durationMs);
|
|
236
|
+
// Should fail
|
|
237
|
+
expect(result.exitCode).not.toBe(0);
|
|
238
|
+
assertNoHardcoded(result, 'skillsmith validate invalid', 'validate: invalid skill', __filename);
|
|
239
|
+
});
|
|
240
|
+
it('should handle missing SKILL.md', async () => {
|
|
241
|
+
const emptyDir = join(TEST_DIR, 'empty-dir');
|
|
242
|
+
mkdirSync(emptyDir, { recursive: true });
|
|
243
|
+
const result = await runCommand(['validate', emptyDir]);
|
|
244
|
+
// Should fail with appropriate error
|
|
245
|
+
expect(result.exitCode).not.toBe(0);
|
|
246
|
+
assertNoHardcoded(result, 'skillsmith validate missing', 'validate: missing file', __filename);
|
|
247
|
+
});
|
|
248
|
+
it('should validate current directory by default', async () => {
|
|
249
|
+
// Create skill in test dir root
|
|
250
|
+
writeFileSync(join(TEST_DIR, 'SKILL.md'), VALID_SKILL_MD);
|
|
251
|
+
const result = await runCommand(['validate'], TEST_DIR);
|
|
252
|
+
expect(result.exitCode).toBe(0);
|
|
253
|
+
assertNoHardcoded(result, 'skillsmith validate .', 'validate: current dir', __filename);
|
|
254
|
+
});
|
|
255
|
+
it('should output parsed metadata', async () => {
|
|
256
|
+
const skillDir = join(TEST_DIR, 'metadata-skill');
|
|
257
|
+
mkdirSync(skillDir, { recursive: true });
|
|
258
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
259
|
+
const result = await runCommand(['validate', skillDir]);
|
|
260
|
+
expect(result.exitCode).toBe(0);
|
|
261
|
+
// Should show parsed metadata
|
|
262
|
+
const output = result.stdout;
|
|
263
|
+
expect(output).toContain('test-skill');
|
|
264
|
+
assertNoHardcoded(result, 'skillsmith validate metadata', 'validate: metadata output', __filename);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
describe('E2E: skillsmith publish', () => {
|
|
269
|
+
beforeEach(() => {
|
|
270
|
+
if (existsSync(TEST_DIR)) {
|
|
271
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
272
|
+
}
|
|
273
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
274
|
+
});
|
|
275
|
+
afterAll(() => {
|
|
276
|
+
if (existsSync(TEST_DIR)) {
|
|
277
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
describe('Publish Command', () => {
|
|
281
|
+
it('should display help without errors', async () => {
|
|
282
|
+
const result = await runCommand(['publish', '--help']);
|
|
283
|
+
expect(result.exitCode).toBe(0);
|
|
284
|
+
expect(result.stdout).toContain('Prepare');
|
|
285
|
+
assertNoHardcoded(result, 'skillsmith publish --help', 'publish: help', __filename);
|
|
286
|
+
});
|
|
287
|
+
it('should prepare valid skill for publishing', async () => {
|
|
288
|
+
// Create valid skill
|
|
289
|
+
const skillDir = join(TEST_DIR, 'publish-skill');
|
|
290
|
+
mkdirSync(skillDir, { recursive: true });
|
|
291
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
292
|
+
const result = await runCommand(['publish', skillDir]);
|
|
293
|
+
recordTiming('publish:prepare', 'skillsmith publish', result.durationMs);
|
|
294
|
+
expect(result.exitCode).toBe(0);
|
|
295
|
+
// Should create publish manifest
|
|
296
|
+
expect(existsSync(join(skillDir, '.skillsmith-publish.json'))).toBe(true);
|
|
297
|
+
assertNoHardcoded(result, 'skillsmith publish', 'publish: prepare skill', __filename);
|
|
298
|
+
});
|
|
299
|
+
it('should generate checksum', async () => {
|
|
300
|
+
const skillDir = join(TEST_DIR, 'checksum-skill');
|
|
301
|
+
mkdirSync(skillDir, { recursive: true });
|
|
302
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
303
|
+
const result = await runCommand(['publish', skillDir]);
|
|
304
|
+
expect(result.exitCode).toBe(0);
|
|
305
|
+
// Read manifest
|
|
306
|
+
const manifest = JSON.parse(readFileSync(join(skillDir, '.skillsmith-publish.json'), 'utf-8'));
|
|
307
|
+
expect(manifest.checksum).toBeDefined();
|
|
308
|
+
expect(typeof manifest.checksum).toBe('string');
|
|
309
|
+
assertNoHardcoded(result, 'skillsmith publish checksum', 'publish: checksum', __filename);
|
|
310
|
+
});
|
|
311
|
+
it('should reject invalid skill', async () => {
|
|
312
|
+
const skillDir = join(TEST_DIR, 'invalid-publish');
|
|
313
|
+
mkdirSync(skillDir, { recursive: true });
|
|
314
|
+
writeFileSync(join(skillDir, 'SKILL.md'), INVALID_SKILL_MD);
|
|
315
|
+
const result = await runCommand(['publish', skillDir]);
|
|
316
|
+
// Should fail validation before publishing
|
|
317
|
+
expect(result.exitCode).not.toBe(0);
|
|
318
|
+
assertNoHardcoded(result, 'skillsmith publish invalid', 'publish: invalid skill', __filename);
|
|
319
|
+
});
|
|
320
|
+
it('should include publishing instructions', async () => {
|
|
321
|
+
const skillDir = join(TEST_DIR, 'instructions-skill');
|
|
322
|
+
mkdirSync(skillDir, { recursive: true });
|
|
323
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
324
|
+
const result = await runCommand(['publish', skillDir]);
|
|
325
|
+
expect(result.exitCode).toBe(0);
|
|
326
|
+
// Output should contain publishing instructions
|
|
327
|
+
const output = result.stdout;
|
|
328
|
+
expect(output).toMatch(/github|manual|archive/i);
|
|
329
|
+
assertNoHardcoded(result, 'skillsmith publish instructions', 'publish: instructions', __filename);
|
|
330
|
+
});
|
|
331
|
+
it('should not expose local paths in manifest', async () => {
|
|
332
|
+
const skillDir = join(TEST_DIR, 'path-manifest');
|
|
333
|
+
mkdirSync(skillDir, { recursive: true });
|
|
334
|
+
writeFileSync(join(skillDir, 'SKILL.md'), VALID_SKILL_MD);
|
|
335
|
+
const result = await runCommand(['publish', skillDir]);
|
|
336
|
+
expect(result.exitCode).toBe(0);
|
|
337
|
+
// Read manifest
|
|
338
|
+
const manifest = readFileSync(join(skillDir, '.skillsmith-publish.json'), 'utf-8');
|
|
339
|
+
// Should not contain local paths
|
|
340
|
+
expect(manifest).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
|
|
341
|
+
expect(manifest).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\//);
|
|
342
|
+
expect(manifest).not.toContain(TEST_DIR);
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
//# sourceMappingURL=author.e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author.e2e.test.js","sourceRoot":"","sources":["../../../tests/e2e/author.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Test: skillsmith import command
|
|
3
|
+
*
|
|
4
|
+
* Tests the import command against real GitHub repositories
|
|
5
|
+
* in a clean Codespace environment.
|
|
6
|
+
*
|
|
7
|
+
* User Journey: Import skills from GitHub topic
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=import.e2e.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.e2e.test.d.ts","sourceRoot":"","sources":["../../../tests/e2e/import.e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E Test: skillsmith import command
|
|
3
|
+
*
|
|
4
|
+
* Tests the import command against real GitHub repositories
|
|
5
|
+
* in a clean Codespace environment.
|
|
6
|
+
*
|
|
7
|
+
* User Journey: Import skills from GitHub topic
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } 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 { measureAsync, recordTiming } from './utils/baseline-collector.js';
|
|
17
|
+
import { queueIssue } from './utils/linear-reporter.js';
|
|
18
|
+
// ESM compatibility for __dirname
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
// Test configuration
|
|
22
|
+
const TEST_DIR = join(tmpdir(), 'skillsmith-e2e-import');
|
|
23
|
+
const TEST_DB_PATH = join(TEST_DIR, 'test-skills.db');
|
|
24
|
+
const CLI_PATH = join(__dirname, '../../dist/src/index.js');
|
|
25
|
+
/**
|
|
26
|
+
* Execute CLI command and capture output
|
|
27
|
+
*/
|
|
28
|
+
async function runCommand(args, timeoutMs = 60000) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const startTime = Date.now();
|
|
31
|
+
let stdout = '';
|
|
32
|
+
let stderr = '';
|
|
33
|
+
const proc = spawn('node', [CLI_PATH, ...args], {
|
|
34
|
+
env: {
|
|
35
|
+
...process.env,
|
|
36
|
+
NODE_ENV: 'test',
|
|
37
|
+
SKILLSMITH_E2E: 'true',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const timeout = setTimeout(() => {
|
|
41
|
+
proc.kill('SIGTERM');
|
|
42
|
+
reject(new Error(`Command timed out after ${timeoutMs}ms`));
|
|
43
|
+
}, timeoutMs);
|
|
44
|
+
proc.stdout.on('data', (data) => {
|
|
45
|
+
stdout += data.toString();
|
|
46
|
+
});
|
|
47
|
+
proc.stderr.on('data', (data) => {
|
|
48
|
+
stderr += data.toString();
|
|
49
|
+
});
|
|
50
|
+
proc.on('close', (code) => {
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
resolve({
|
|
53
|
+
exitCode: code ?? 1,
|
|
54
|
+
stdout,
|
|
55
|
+
stderr,
|
|
56
|
+
durationMs: Date.now() - startTime,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
proc.on('error', (error) => {
|
|
60
|
+
clearTimeout(timeout);
|
|
61
|
+
reject(error);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Assert no hardcoded values in command output
|
|
67
|
+
*/
|
|
68
|
+
function assertNoHardcoded(result, command, testName, testFile) {
|
|
69
|
+
const detection = scanCommandOutput(result.stdout, result.stderr, command);
|
|
70
|
+
if (!detection.passed) {
|
|
71
|
+
// Queue Linear issue for hardcoded detection
|
|
72
|
+
const failure = {
|
|
73
|
+
testName,
|
|
74
|
+
testFile,
|
|
75
|
+
command,
|
|
76
|
+
error: `Hardcoded values detected: ${detection.issues.map((i) => i.pattern).join(', ')}`,
|
|
77
|
+
stdout: result.stdout,
|
|
78
|
+
stderr: result.stderr,
|
|
79
|
+
hardcodedIssues: detection.issues,
|
|
80
|
+
duration: result.durationMs,
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
queueIssue(failure);
|
|
84
|
+
// Fail test with details
|
|
85
|
+
const errorDetails = detection.issues
|
|
86
|
+
.filter((i) => i.severity === 'error')
|
|
87
|
+
.map((i) => ` - ${i.type}: ${i.value} (${i.pattern})`)
|
|
88
|
+
.join('\n');
|
|
89
|
+
expect.fail(`Hardcoded values detected:\n${errorDetails}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
describe('E2E: skillsmith import', () => {
|
|
93
|
+
beforeAll(() => {
|
|
94
|
+
// Create isolated test directory
|
|
95
|
+
if (existsSync(TEST_DIR)) {
|
|
96
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
99
|
+
});
|
|
100
|
+
afterAll(() => {
|
|
101
|
+
// Cleanup test directory
|
|
102
|
+
if (existsSync(TEST_DIR)) {
|
|
103
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
// Ensure clean database for each test
|
|
108
|
+
if (existsSync(TEST_DB_PATH)) {
|
|
109
|
+
rmSync(TEST_DB_PATH, { force: true });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
describe('Basic Import', () => {
|
|
113
|
+
it('should display help without errors', async () => {
|
|
114
|
+
const result = await runCommand(['import', '--help']);
|
|
115
|
+
expect(result.exitCode).toBe(0);
|
|
116
|
+
expect(result.stdout).toContain('Import skills from GitHub');
|
|
117
|
+
expect(result.stdout).toContain('--topic');
|
|
118
|
+
expect(result.stdout).toContain('--max');
|
|
119
|
+
// Skip hardcoded check for help output since it includes default values (e.g., database path)
|
|
120
|
+
if (!result.stdout.includes('Usage:')) {
|
|
121
|
+
assertNoHardcoded(result, 'skillsmith import --help', 'import: help displays correctly', __filename);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// Skip: Requires GitHub API access which may not be available in all CI environments
|
|
125
|
+
it.skip('should import skills with default topic', async () => {
|
|
126
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', '5', '-v'], 120000);
|
|
127
|
+
// Record timing baseline
|
|
128
|
+
recordTiming('import:default', 'skillsmith import -m 5', result.durationMs);
|
|
129
|
+
// Should complete (may have 0 results if no network or topic empty)
|
|
130
|
+
expect(result.exitCode).toBe(0);
|
|
131
|
+
assertNoHardcoded(result, 'skillsmith import -m 5', 'import: default topic import', __filename);
|
|
132
|
+
});
|
|
133
|
+
// Skip: Requires GitHub API access which may not be available in all CI environments
|
|
134
|
+
it.skip('should create database at specified path', async () => {
|
|
135
|
+
const customDbPath = join(TEST_DIR, 'custom-db.db');
|
|
136
|
+
const result = await runCommand(['import', '-d', customDbPath, '-m', '1'], 60000);
|
|
137
|
+
// Database should be created (even if empty)
|
|
138
|
+
// Note: If import fails due to network, db might not be created
|
|
139
|
+
if (result.exitCode === 0) {
|
|
140
|
+
expect(existsSync(customDbPath)).toBe(true);
|
|
141
|
+
}
|
|
142
|
+
assertNoHardcoded(result, 'skillsmith import -d custom', 'import: custom database path', __filename);
|
|
143
|
+
});
|
|
144
|
+
// Skip: Requires GitHub API access which may not be available in all CI environments
|
|
145
|
+
it.skip('should handle custom topic parameter', async () => {
|
|
146
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-t', 'claude-code', '-m', '3'], 60000);
|
|
147
|
+
expect(result.stdout + result.stderr).toContain('claude-code');
|
|
148
|
+
assertNoHardcoded(result, 'skillsmith import -t claude-code', 'import: custom topic', __filename);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('Verbose Output', () => {
|
|
152
|
+
// Skip: Requires GitHub API access and can timeout waiting for network response
|
|
153
|
+
it.skip('should show progress in verbose mode', async () => {
|
|
154
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', '2', '-v'], 60000);
|
|
155
|
+
// Should not contain hardcoded paths
|
|
156
|
+
assertNoHardcoded(result, 'skillsmith import -v', 'import: verbose mode output', __filename);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe('Error Handling', () => {
|
|
160
|
+
it('should handle invalid max value gracefully', async () => {
|
|
161
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', 'invalid']);
|
|
162
|
+
// Should either fail gracefully or use default
|
|
163
|
+
assertNoHardcoded(result, 'skillsmith import -m invalid', 'import: invalid max value', __filename);
|
|
164
|
+
});
|
|
165
|
+
it('should handle inaccessible database path', async () => {
|
|
166
|
+
const invalidPath = '/nonexistent/path/db.db';
|
|
167
|
+
const result = await runCommand(['import', '-d', invalidPath, '-m', '1']);
|
|
168
|
+
// Should fail with appropriate error
|
|
169
|
+
expect(result.exitCode).not.toBe(0);
|
|
170
|
+
assertNoHardcoded(result, 'skillsmith import -d /nonexistent', 'import: inaccessible path', __filename);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('Performance Baseline', () => {
|
|
174
|
+
// Skip: Requires GitHub API access and network for importing skills
|
|
175
|
+
it.skip('should complete import of 10 skills within reasonable time', async () => {
|
|
176
|
+
const { durationMs } = await measureAsync('import:10skills', 'skillsmith import -m 10', async () => {
|
|
177
|
+
return runCommand(['import', '-d', TEST_DB_PATH, '-m', '10'], 180000);
|
|
178
|
+
});
|
|
179
|
+
// Record baseline (no hard threshold for first run)
|
|
180
|
+
console.log(`Import 10 skills baseline: ${durationMs}ms`);
|
|
181
|
+
// Soft assertion: should complete within 3 minutes
|
|
182
|
+
expect(durationMs).toBeLessThan(180000);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('Hardcoded Value Detection', () => {
|
|
186
|
+
// Skip: Requires GitHub API access and network for importing skills
|
|
187
|
+
it.skip('should not contain user-specific paths in output', async () => {
|
|
188
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', '1', '-v'], 60000);
|
|
189
|
+
// Explicit check for common hardcoded patterns
|
|
190
|
+
const output = result.stdout + result.stderr;
|
|
191
|
+
expect(output).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
|
|
192
|
+
expect(output).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\//);
|
|
193
|
+
expect(output).not.toMatch(/C:\\Users\\[a-zA-Z0-9_-]+\\/);
|
|
194
|
+
});
|
|
195
|
+
// Skip: Requires GitHub API access and network for importing skills
|
|
196
|
+
it.skip('should not expose localhost URLs in output', async () => {
|
|
197
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', '1'], 60000);
|
|
198
|
+
const output = result.stdout + result.stderr;
|
|
199
|
+
// Allow github.com but not localhost
|
|
200
|
+
expect(output).not.toMatch(/localhost:\d+/);
|
|
201
|
+
expect(output).not.toMatch(/127\.0\.0\.1:\d+/);
|
|
202
|
+
});
|
|
203
|
+
// Skip: Requires GitHub API access and network for importing skills
|
|
204
|
+
it.skip('should not expose API keys in output', async () => {
|
|
205
|
+
const result = await runCommand(['import', '-d', TEST_DB_PATH, '-m', '1', '-v'], 60000);
|
|
206
|
+
const output = result.stdout + result.stderr;
|
|
207
|
+
expect(output).not.toMatch(/ghp_[a-zA-Z0-9]{36}/);
|
|
208
|
+
expect(output).not.toMatch(/sk-[a-zA-Z0-9]{32,}/);
|
|
209
|
+
expect(output).not.toMatch(/lin_api_[a-zA-Z0-9]+/);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
//# sourceMappingURL=import.e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.e2e.test.js","sourceRoot":"","sources":["../../../tests/e2e/import.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.e2e.test.d.ts","sourceRoot":"","sources":["../../../tests/e2e/manage.e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|