@skillsmith/mcp-server 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/__tests__/get-skill.test.d.ts +6 -0
- package/dist/src/__tests__/get-skill.test.d.ts.map +1 -0
- package/dist/src/__tests__/get-skill.test.js +88 -0
- package/dist/src/__tests__/get-skill.test.js.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js +304 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js.map +1 -0
- package/dist/src/__tests__/middleware/license.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/license.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/license.test.js +500 -0
- package/dist/src/__tests__/middleware/license.test.js.map +1 -0
- package/dist/src/__tests__/search.test.d.ts +6 -0
- package/dist/src/__tests__/search.test.d.ts.map +1 -0
- package/dist/src/__tests__/search.test.js +86 -0
- package/dist/src/__tests__/search.test.js.map +1 -0
- package/dist/src/__tests__/test-utils.d.ts +19 -0
- package/dist/src/__tests__/test-utils.d.ts.map +1 -0
- package/dist/src/__tests__/test-utils.js +87 -0
- package/dist/src/__tests__/test-utils.js.map +1 -0
- package/dist/src/context/index.d.ts +19 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +25 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/project-detector.d.ts +145 -0
- package/dist/src/context/project-detector.d.ts.map +1 -0
- package/dist/src/context/project-detector.js +321 -0
- package/dist/src/context/project-detector.js.map +1 -0
- package/dist/src/context.d.ts +100 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +157 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/core-shim.d.ts +7 -0
- package/dist/src/core-shim.d.ts.map +1 -0
- package/dist/src/core-shim.js +9 -0
- package/dist/src/core-shim.js.map +1 -0
- package/dist/src/health/healthCheck.d.ts +88 -0
- package/dist/src/health/healthCheck.d.ts.map +1 -0
- package/dist/src/health/healthCheck.js +117 -0
- package/dist/src/health/healthCheck.js.map +1 -0
- package/dist/src/health/index.d.ts +21 -0
- package/dist/src/health/index.d.ts.map +1 -0
- package/dist/src/health/index.js +21 -0
- package/dist/src/health/index.js.map +1 -0
- package/dist/src/health/readinessCheck.d.ts +139 -0
- package/dist/src/health/readinessCheck.d.ts.map +1 -0
- package/dist/src/health/readinessCheck.js +266 -0
- package/dist/src/health/readinessCheck.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +178 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/index.test.d.ts +2 -0
- package/dist/src/index.test.d.ts.map +1 -0
- package/dist/src/index.test.js +43 -0
- package/dist/src/index.test.js.map +1 -0
- package/dist/src/logger.d.ts +26 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +179 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.js +389 -0
- package/dist/src/middleware/__tests__/csp.test.js.map +1 -0
- package/dist/src/middleware/csp.d.ts +87 -0
- package/dist/src/middleware/csp.d.ts.map +1 -0
- package/dist/src/middleware/csp.js +273 -0
- package/dist/src/middleware/csp.js.map +1 -0
- package/dist/src/middleware/degradation.d.ts +99 -0
- package/dist/src/middleware/degradation.d.ts.map +1 -0
- package/dist/src/middleware/degradation.js +315 -0
- package/dist/src/middleware/degradation.js.map +1 -0
- package/dist/src/middleware/errorFormatter.d.ts +119 -0
- package/dist/src/middleware/errorFormatter.d.ts.map +1 -0
- package/dist/src/middleware/errorFormatter.js +294 -0
- package/dist/src/middleware/errorFormatter.js.map +1 -0
- package/dist/src/middleware/index.d.ts +10 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +14 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/middleware/license.d.ts +161 -0
- package/dist/src/middleware/license.d.ts.map +1 -0
- package/dist/src/middleware/license.js +281 -0
- package/dist/src/middleware/license.js.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts +36 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.js +90 -0
- package/dist/src/middleware/toolFeatureMapping.js.map +1 -0
- package/dist/src/onboarding/first-run.d.ts +64 -0
- package/dist/src/onboarding/first-run.d.ts.map +1 -0
- package/dist/src/onboarding/first-run.js +77 -0
- package/dist/src/onboarding/first-run.js.map +1 -0
- package/dist/src/onboarding/index.d.ts +7 -0
- package/dist/src/onboarding/index.d.ts.map +1 -0
- package/dist/src/onboarding/index.js +7 -0
- package/dist/src/onboarding/index.js.map +1 -0
- package/dist/src/suggestions/index.d.ts +21 -0
- package/dist/src/suggestions/index.d.ts.map +1 -0
- package/dist/src/suggestions/index.js +20 -0
- package/dist/src/suggestions/index.js.map +1 -0
- package/dist/src/suggestions/suggestion-engine.d.ts +185 -0
- package/dist/src/suggestions/suggestion-engine.d.ts.map +1 -0
- package/dist/src/suggestions/suggestion-engine.js +352 -0
- package/dist/src/suggestions/suggestion-engine.js.map +1 -0
- package/dist/src/suggestions/types.d.ts +88 -0
- package/dist/src/suggestions/types.d.ts.map +1 -0
- package/dist/src/suggestions/types.js +21 -0
- package/dist/src/suggestions/types.js.map +1 -0
- package/dist/src/tools/analyze.d.ts +151 -0
- package/dist/src/tools/analyze.d.ts.map +1 -0
- package/dist/src/tools/analyze.js +205 -0
- package/dist/src/tools/analyze.js.map +1 -0
- package/dist/src/tools/compare.d.ts +149 -0
- package/dist/src/tools/compare.d.ts.map +1 -0
- package/dist/src/tools/compare.js +464 -0
- package/dist/src/tools/compare.js.map +1 -0
- package/dist/src/tools/get-skill.d.ts +116 -0
- package/dist/src/tools/get-skill.d.ts.map +1 -0
- package/dist/src/tools/get-skill.js +224 -0
- package/dist/src/tools/get-skill.js.map +1 -0
- package/dist/src/tools/index.d.ts +20 -0
- package/dist/src/tools/index.d.ts.map +1 -0
- package/dist/src/tools/index.js +20 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/tools/install.d.ts +122 -0
- package/dist/src/tools/install.d.ts.map +1 -0
- package/dist/src/tools/install.js +314 -0
- package/dist/src/tools/install.js.map +1 -0
- package/dist/src/tools/recommend.d.ts +171 -0
- package/dist/src/tools/recommend.d.ts.map +1 -0
- package/dist/src/tools/recommend.js +325 -0
- package/dist/src/tools/recommend.js.map +1 -0
- package/dist/src/tools/search.d.ts +121 -0
- package/dist/src/tools/search.d.ts.map +1 -0
- package/dist/src/tools/search.js +249 -0
- package/dist/src/tools/search.js.map +1 -0
- package/dist/src/tools/suggest.d.ts +181 -0
- package/dist/src/tools/suggest.d.ts.map +1 -0
- package/dist/src/tools/suggest.js +342 -0
- package/dist/src/tools/suggest.js.map +1 -0
- package/dist/src/tools/uninstall.d.ts +123 -0
- package/dist/src/tools/uninstall.d.ts.map +1 -0
- package/dist/src/tools/uninstall.js +250 -0
- package/dist/src/tools/uninstall.js.map +1 -0
- package/dist/src/tools/validate.d.ts +122 -0
- package/dist/src/tools/validate.d.ts.map +1 -0
- package/dist/src/tools/validate.js +497 -0
- package/dist/src/tools/validate.js.map +1 -0
- package/dist/src/utils/installed-skills.d.ts +101 -0
- package/dist/src/utils/installed-skills.d.ts.map +1 -0
- package/dist/src/utils/installed-skills.js +220 -0
- package/dist/src/utils/installed-skills.js.map +1 -0
- package/dist/src/utils/validation.d.ts +76 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +153 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/dist/src/webhooks/index.d.ts +8 -0
- package/dist/src/webhooks/index.d.ts.map +1 -0
- package/dist/src/webhooks/index.js +9 -0
- package/dist/src/webhooks/index.js.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts +149 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.js +339 -0
- package/dist/src/webhooks/webhook-endpoint.js.map +1 -0
- package/dist/tests/compare.test.d.ts +6 -0
- package/dist/tests/compare.test.d.ts.map +1 -0
- package/dist/tests/compare.test.js +225 -0
- package/dist/tests/compare.test.js.map +1 -0
- package/dist/tests/context/project-detector.test.d.ts +6 -0
- package/dist/tests/context/project-detector.test.d.ts.map +1 -0
- package/dist/tests/context/project-detector.test.js +719 -0
- package/dist/tests/context/project-detector.test.js.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.js +286 -0
- package/dist/tests/e2e/compare.e2e.test.js.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.js +209 -0
- package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts +12 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.js +347 -0
- package/dist/tests/e2e/recommend.e2e.test.js.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js +280 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts +13 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.js +347 -0
- package/dist/tests/e2e/suggest.e2e.test.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 +255 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
- package/dist/tests/e2e/utils/index.d.ts +7 -0
- package/dist/tests/e2e/utils/index.d.ts.map +1 -0
- package/dist/tests/e2e/utils/index.js +7 -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 +232 -0
- package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
- package/dist/tests/health.test.d.ts +9 -0
- package/dist/tests/health.test.d.ts.map +1 -0
- package/dist/tests/health.test.js +308 -0
- package/dist/tests/health.test.js.map +1 -0
- package/dist/tests/integration/analyze.integration.test.d.ts +2 -0
- package/dist/tests/integration/analyze.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/analyze.integration.test.js +244 -0
- package/dist/tests/integration/analyze.integration.test.js.map +1 -0
- package/dist/tests/integration/compare.integration.test.d.ts +2 -0
- package/dist/tests/integration/compare.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/compare.integration.test.js +120 -0
- package/dist/tests/integration/compare.integration.test.js.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts +62 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.js +644 -0
- package/dist/tests/integration/fixtures/test-skills.js.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts +6 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.js +203 -0
- package/dist/tests/integration/get-skill.integration.test.js.map +1 -0
- package/dist/tests/integration/github-api.integration.test.d.ts +14 -0
- package/dist/tests/integration/github-api.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/github-api.integration.test.js +190 -0
- package/dist/tests/integration/github-api.integration.test.js.map +1 -0
- package/dist/tests/integration/install.integration.test.d.ts +6 -0
- package/dist/tests/integration/install.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install.integration.test.js +282 -0
- package/dist/tests/integration/install.integration.test.js.map +1 -0
- package/dist/tests/integration/recommend.integration.test.d.ts +2 -0
- package/dist/tests/integration/recommend.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/recommend.integration.test.js +215 -0
- package/dist/tests/integration/recommend.integration.test.js.map +1 -0
- package/dist/tests/integration/search.integration.test.d.ts +6 -0
- package/dist/tests/integration/search.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/search.integration.test.js +229 -0
- package/dist/tests/integration/search.integration.test.js.map +1 -0
- package/dist/tests/integration/setup.d.ts +71 -0
- package/dist/tests/integration/setup.d.ts.map +1 -0
- package/dist/tests/integration/setup.js +124 -0
- package/dist/tests/integration/setup.js.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts +6 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.js +296 -0
- package/dist/tests/integration/uninstall.integration.test.js.map +1 -0
- package/dist/tests/integration/validate.integration.test.d.ts +2 -0
- package/dist/tests/integration/validate.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/validate.integration.test.js +181 -0
- package/dist/tests/integration/validate.integration.test.js.map +1 -0
- package/dist/tests/onboarding/first-run.test.d.ts +7 -0
- package/dist/tests/onboarding/first-run.test.d.ts.map +1 -0
- package/dist/tests/onboarding/first-run.test.js +258 -0
- package/dist/tests/onboarding/first-run.test.js.map +1 -0
- package/dist/tests/performance/search-performance.test.d.ts +10 -0
- package/dist/tests/performance/search-performance.test.d.ts.map +1 -0
- package/dist/tests/performance/search-performance.test.js +218 -0
- package/dist/tests/performance/search-performance.test.js.map +1 -0
- package/dist/tests/recommend.test.d.ts +6 -0
- package/dist/tests/recommend.test.d.ts.map +1 -0
- package/dist/tests/recommend.test.js +208 -0
- package/dist/tests/recommend.test.js.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts +6 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.js +448 -0
- package/dist/tests/suggestions/suggestion-engine.test.js.map +1 -0
- package/dist/tests/test-utils.d.ts +74 -0
- package/dist/tests/test-utils.d.ts.map +1 -0
- package/dist/tests/test-utils.js +98 -0
- package/dist/tests/test-utils.js.map +1 -0
- package/dist/tests/tools.test.d.ts +5 -0
- package/dist/tests/tools.test.d.ts.map +1 -0
- package/dist/tests/tools.test.js +138 -0
- package/dist/tests/tools.test.js.map +1 -0
- package/dist/tests/unit/installed-skills.test.d.ts +6 -0
- package/dist/tests/unit/installed-skills.test.d.ts.map +1 -0
- package/dist/tests/unit/installed-skills.test.js +285 -0
- package/dist/tests/unit/installed-skills.test.js.map +1 -0
- package/dist/tests/unit/logger.test.d.ts +6 -0
- package/dist/tests/unit/logger.test.d.ts.map +1 -0
- package/dist/tests/unit/logger.test.js +281 -0
- package/dist/tests/unit/logger.test.js.map +1 -0
- package/dist/tests/validate.test.d.ts +5 -0
- package/dist/tests/validate.test.d.ts.map +1 -0
- package/dist/tests/validate.test.js +303 -0
- package/dist/tests/validate.test.js.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts +8 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js +145 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts +8 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js +122 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js.map +1 -0
- package/dist/vitest.config.d.ts +6 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +13 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-616: Uninstall Skill Tool Integration Tests
|
|
3
|
+
* Tests the uninstall_skill tool with real filesystem operations
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { createTestFilesystem, createMockManifest, createMockInstalledSkill, fileExists, readJsonFile, } from './setup.js';
|
|
9
|
+
describe('Uninstall Skill Tool Integration Tests', () => {
|
|
10
|
+
let fsContext;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
fsContext = await createTestFilesystem();
|
|
13
|
+
});
|
|
14
|
+
afterEach(async () => {
|
|
15
|
+
await fsContext.cleanup();
|
|
16
|
+
});
|
|
17
|
+
describe('Basic Uninstall Operations', () => {
|
|
18
|
+
it('should uninstall skill that exists in manifest', async () => {
|
|
19
|
+
const skillName = 'skill-to-remove';
|
|
20
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
21
|
+
await createMockManifest(fsContext.manifestDir, {
|
|
22
|
+
[skillName]: {
|
|
23
|
+
id: 'owner/skill-to-remove',
|
|
24
|
+
name: skillName,
|
|
25
|
+
version: '1.0.0',
|
|
26
|
+
source: 'github:owner/skill-to-remove',
|
|
27
|
+
installPath: skillPath,
|
|
28
|
+
installedAt: new Date().toISOString(),
|
|
29
|
+
lastUpdated: new Date().toISOString(),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
// Verify skill exists before uninstall
|
|
33
|
+
expect(await fileExists(skillPath)).toBe(true);
|
|
34
|
+
// Perform uninstall
|
|
35
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
36
|
+
// Update manifest
|
|
37
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
38
|
+
const manifest = await readJsonFile(manifestPath);
|
|
39
|
+
delete manifest.installedSkills[skillName];
|
|
40
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
41
|
+
// Verify uninstall
|
|
42
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
43
|
+
const updatedManifest = await readJsonFile(manifestPath);
|
|
44
|
+
expect(updatedManifest.installedSkills[skillName]).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
it('should handle skill not in manifest but on disk', async () => {
|
|
47
|
+
const skillName = 'orphan-skill';
|
|
48
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
49
|
+
// Create empty manifest (skill not tracked)
|
|
50
|
+
await createMockManifest(fsContext.manifestDir, {});
|
|
51
|
+
// Verify skill exists on disk
|
|
52
|
+
expect(await fileExists(skillPath)).toBe(true);
|
|
53
|
+
// Force remove from disk
|
|
54
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
55
|
+
// Verify removal
|
|
56
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it('should report skill not found', async () => {
|
|
59
|
+
await createMockManifest(fsContext.manifestDir, {});
|
|
60
|
+
const skillPath = path.join(fsContext.skillsDir, 'nonexistent-skill');
|
|
61
|
+
const exists = await fileExists(skillPath);
|
|
62
|
+
expect(exists).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('Modification Detection', () => {
|
|
66
|
+
it('should detect modified files', async () => {
|
|
67
|
+
const skillName = 'modified-skill';
|
|
68
|
+
const skillPath = path.join(fsContext.skillsDir, skillName);
|
|
69
|
+
await fs.mkdir(skillPath, { recursive: true });
|
|
70
|
+
// Create SKILL.md
|
|
71
|
+
await fs.writeFile(path.join(skillPath, 'SKILL.md'), '# Original Content\n\nOriginal skill content.');
|
|
72
|
+
const installedAt = new Date(Date.now() - 10000).toISOString(); // 10 seconds ago
|
|
73
|
+
// Wait a tiny bit then modify
|
|
74
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
75
|
+
await fs.writeFile(path.join(skillPath, 'SKILL.md'), '# Modified Content\n\nThis content was changed after installation.');
|
|
76
|
+
// Check modification time
|
|
77
|
+
const stats = await fs.stat(path.join(skillPath, 'SKILL.md'));
|
|
78
|
+
const installDate = new Date(installedAt);
|
|
79
|
+
const isModified = stats.mtime > installDate;
|
|
80
|
+
expect(isModified).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
it('should not flag unmodified files as modified', async () => {
|
|
83
|
+
const skillName = 'unmodified-skill';
|
|
84
|
+
const skillPath = path.join(fsContext.skillsDir, skillName);
|
|
85
|
+
await fs.mkdir(skillPath, { recursive: true });
|
|
86
|
+
// Create SKILL.md
|
|
87
|
+
await fs.writeFile(path.join(skillPath, 'SKILL.md'), '# Unchanged Content\n\nThis content remains unchanged.');
|
|
88
|
+
// Wait then record install time
|
|
89
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
90
|
+
const installedAt = new Date().toISOString();
|
|
91
|
+
// Check modification time
|
|
92
|
+
const stats = await fs.stat(path.join(skillPath, 'SKILL.md'));
|
|
93
|
+
const installDate = new Date(installedAt);
|
|
94
|
+
const isModified = stats.mtime > installDate;
|
|
95
|
+
expect(isModified).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('Force Uninstall', () => {
|
|
99
|
+
it('should force uninstall modified skill', async () => {
|
|
100
|
+
const skillName = 'force-uninstall-skill';
|
|
101
|
+
const skillPath = path.join(fsContext.skillsDir, skillName);
|
|
102
|
+
await fs.mkdir(skillPath, { recursive: true });
|
|
103
|
+
await fs.writeFile(path.join(skillPath, 'SKILL.md'), '# Force Uninstall Test\n\nThis skill will be force uninstalled.');
|
|
104
|
+
// Modify after creation
|
|
105
|
+
await fs.writeFile(path.join(skillPath, 'custom-file.txt'), 'User added this file');
|
|
106
|
+
// Force remove
|
|
107
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
108
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
it('should force uninstall skill not in manifest', async () => {
|
|
111
|
+
const skillName = 'untracked-skill';
|
|
112
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
113
|
+
await createMockManifest(fsContext.manifestDir, {}); // Empty manifest
|
|
114
|
+
// Force remove
|
|
115
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
116
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('Manifest Cleanup', () => {
|
|
120
|
+
it('should remove skill entry from manifest', async () => {
|
|
121
|
+
const skillName = 'manifest-cleanup-skill';
|
|
122
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
123
|
+
await createMockManifest(fsContext.manifestDir, {
|
|
124
|
+
[skillName]: {
|
|
125
|
+
id: 'owner/manifest-cleanup-skill',
|
|
126
|
+
name: skillName,
|
|
127
|
+
version: '1.0.0',
|
|
128
|
+
source: 'github:owner/manifest-cleanup-skill',
|
|
129
|
+
installPath: skillPath,
|
|
130
|
+
installedAt: new Date().toISOString(),
|
|
131
|
+
lastUpdated: new Date().toISOString(),
|
|
132
|
+
},
|
|
133
|
+
'other-skill': {
|
|
134
|
+
id: 'owner/other-skill',
|
|
135
|
+
name: 'other-skill',
|
|
136
|
+
version: '1.0.0',
|
|
137
|
+
source: 'github:owner/other-skill',
|
|
138
|
+
installPath: path.join(fsContext.skillsDir, 'other-skill'),
|
|
139
|
+
installedAt: new Date().toISOString(),
|
|
140
|
+
lastUpdated: new Date().toISOString(),
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
// Remove skill and update manifest
|
|
144
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
145
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
146
|
+
const manifest = await readJsonFile(manifestPath);
|
|
147
|
+
delete manifest.installedSkills[skillName];
|
|
148
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
149
|
+
// Verify cleanup
|
|
150
|
+
const updatedManifest = await readJsonFile(manifestPath);
|
|
151
|
+
expect(updatedManifest.installedSkills[skillName]).toBeUndefined();
|
|
152
|
+
expect(updatedManifest.installedSkills['other-skill']).toBeDefined();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe('Recursive Directory Removal', () => {
|
|
156
|
+
it('should remove skill with nested files', async () => {
|
|
157
|
+
const skillName = 'nested-skill';
|
|
158
|
+
const skillPath = path.join(fsContext.skillsDir, skillName);
|
|
159
|
+
// Create nested structure
|
|
160
|
+
await fs.mkdir(path.join(skillPath, 'examples'), { recursive: true });
|
|
161
|
+
await fs.mkdir(path.join(skillPath, 'tests'), { recursive: true });
|
|
162
|
+
await fs.writeFile(path.join(skillPath, 'SKILL.md'), '# Nested Skill');
|
|
163
|
+
await fs.writeFile(path.join(skillPath, 'README.md'), '# README');
|
|
164
|
+
await fs.writeFile(path.join(skillPath, 'examples', 'example1.md'), '# Example 1');
|
|
165
|
+
await fs.writeFile(path.join(skillPath, 'tests', 'test1.md'), '# Test 1');
|
|
166
|
+
// Verify nested structure exists
|
|
167
|
+
expect(await fileExists(path.join(skillPath, 'examples', 'example1.md'))).toBe(true);
|
|
168
|
+
expect(await fileExists(path.join(skillPath, 'tests', 'test1.md'))).toBe(true);
|
|
169
|
+
// Remove recursively
|
|
170
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
171
|
+
// Verify complete removal
|
|
172
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
it('should handle already deleted skill gracefully', async () => {
|
|
175
|
+
const skillPath = path.join(fsContext.skillsDir, 'already-deleted');
|
|
176
|
+
// Try to remove non-existent directory
|
|
177
|
+
await expect(fs.rm(skillPath, { recursive: true, force: true })).resolves.not.toThrow();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
describe('List Installed Skills', () => {
|
|
181
|
+
it('should list all installed skills from manifest', async () => {
|
|
182
|
+
await createMockManifest(fsContext.manifestDir, {
|
|
183
|
+
skill1: {
|
|
184
|
+
id: 'owner/skill1',
|
|
185
|
+
name: 'skill1',
|
|
186
|
+
version: '1.0.0',
|
|
187
|
+
source: 'github:owner/skill1',
|
|
188
|
+
installPath: path.join(fsContext.skillsDir, 'skill1'),
|
|
189
|
+
installedAt: new Date().toISOString(),
|
|
190
|
+
lastUpdated: new Date().toISOString(),
|
|
191
|
+
},
|
|
192
|
+
skill2: {
|
|
193
|
+
id: 'owner/skill2',
|
|
194
|
+
name: 'skill2',
|
|
195
|
+
version: '1.0.0',
|
|
196
|
+
source: 'github:owner/skill2',
|
|
197
|
+
installPath: path.join(fsContext.skillsDir, 'skill2'),
|
|
198
|
+
installedAt: new Date().toISOString(),
|
|
199
|
+
lastUpdated: new Date().toISOString(),
|
|
200
|
+
},
|
|
201
|
+
skill3: {
|
|
202
|
+
id: 'owner/skill3',
|
|
203
|
+
name: 'skill3',
|
|
204
|
+
version: '2.0.0',
|
|
205
|
+
source: 'github:owner/skill3',
|
|
206
|
+
installPath: path.join(fsContext.skillsDir, 'skill3'),
|
|
207
|
+
installedAt: new Date().toISOString(),
|
|
208
|
+
lastUpdated: new Date().toISOString(),
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
212
|
+
const manifest = await readJsonFile(manifestPath);
|
|
213
|
+
const skillNames = Object.keys(manifest.installedSkills);
|
|
214
|
+
expect(skillNames).toContain('skill1');
|
|
215
|
+
expect(skillNames).toContain('skill2');
|
|
216
|
+
expect(skillNames).toContain('skill3');
|
|
217
|
+
expect(skillNames.length).toBe(3);
|
|
218
|
+
});
|
|
219
|
+
it('should return empty list when no skills installed', async () => {
|
|
220
|
+
await createMockManifest(fsContext.manifestDir, {});
|
|
221
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
222
|
+
const manifest = await readJsonFile(manifestPath);
|
|
223
|
+
const skillNames = Object.keys(manifest.installedSkills);
|
|
224
|
+
expect(skillNames).toEqual([]);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
describe('Edge Cases', () => {
|
|
228
|
+
it('should handle skill name with special characters', async () => {
|
|
229
|
+
const skillName = 'skill-with-dashes';
|
|
230
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
231
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
232
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
233
|
+
});
|
|
234
|
+
it('should handle concurrent uninstall attempts', async () => {
|
|
235
|
+
const skillName = 'concurrent-skill';
|
|
236
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
237
|
+
// Simulate concurrent uninstalls
|
|
238
|
+
await Promise.all([
|
|
239
|
+
fs.rm(skillPath, { recursive: true, force: true }),
|
|
240
|
+
fs.rm(skillPath, { recursive: true, force: true }),
|
|
241
|
+
]);
|
|
242
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
243
|
+
});
|
|
244
|
+
it('should handle manifest file missing', async () => {
|
|
245
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
246
|
+
// Ensure manifest doesn't exist
|
|
247
|
+
try {
|
|
248
|
+
await fs.unlink(manifestPath);
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Ignore if doesn't exist
|
|
252
|
+
}
|
|
253
|
+
// Should be able to create new manifest
|
|
254
|
+
await createMockManifest(fsContext.manifestDir, {});
|
|
255
|
+
expect(await fileExists(manifestPath)).toBe(true);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
describe('Full Uninstall Flow Simulation', () => {
|
|
259
|
+
it('should complete full uninstall flow', async () => {
|
|
260
|
+
const skillName = 'full-uninstall-skill';
|
|
261
|
+
const skillPath = await createMockInstalledSkill(fsContext.skillsDir, skillName);
|
|
262
|
+
// Create additional files
|
|
263
|
+
await fs.writeFile(path.join(skillPath, 'README.md'), '# README');
|
|
264
|
+
await fs.writeFile(path.join(skillPath, 'config.json'), '{}');
|
|
265
|
+
await createMockManifest(fsContext.manifestDir, {
|
|
266
|
+
[skillName]: {
|
|
267
|
+
id: 'owner/full-uninstall-skill',
|
|
268
|
+
name: skillName,
|
|
269
|
+
version: '1.0.0',
|
|
270
|
+
source: 'github:owner/full-uninstall-skill',
|
|
271
|
+
installPath: skillPath,
|
|
272
|
+
installedAt: new Date().toISOString(),
|
|
273
|
+
lastUpdated: new Date().toISOString(),
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
// Verify pre-conditions
|
|
277
|
+
expect(await fileExists(skillPath)).toBe(true);
|
|
278
|
+
expect(await fileExists(path.join(skillPath, 'SKILL.md'))).toBe(true);
|
|
279
|
+
expect(await fileExists(path.join(skillPath, 'README.md'))).toBe(true);
|
|
280
|
+
expect(await fileExists(path.join(skillPath, 'config.json'))).toBe(true);
|
|
281
|
+
// Execute uninstall
|
|
282
|
+
// 1. Remove directory
|
|
283
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
284
|
+
// 2. Update manifest
|
|
285
|
+
const manifestPath = path.join(fsContext.manifestDir, 'manifest.json');
|
|
286
|
+
const manifest = await readJsonFile(manifestPath);
|
|
287
|
+
delete manifest.installedSkills[skillName];
|
|
288
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
289
|
+
// Verify post-conditions
|
|
290
|
+
expect(await fileExists(skillPath)).toBe(false);
|
|
291
|
+
const updatedManifest = await readJsonFile(manifestPath);
|
|
292
|
+
expect(updatedManifest.installedSkills[skillName]).toBeUndefined();
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
//# sourceMappingURL=uninstall.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall.integration.test.js","sourceRoot":"","sources":["../../../tests/integration/uninstall.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.integration.test.d.ts","sourceRoot":"","sources":["../../../tests/integration/validate.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-756: Integration tests for validate MCP tool
|
|
3
|
+
* Tests skill validation with real filesystem
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { createTestFilesystem, createMockInstalledSkill, } from './setup.js';
|
|
9
|
+
import { executeValidate, formatValidationResults } from '../../src/tools/validate.js';
|
|
10
|
+
describe('Validate Tool Integration', () => {
|
|
11
|
+
let ctx;
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
ctx = await createTestFilesystem();
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await ctx.cleanup();
|
|
17
|
+
});
|
|
18
|
+
describe('executeValidate', () => {
|
|
19
|
+
it('should validate a valid SKILL.md file', async () => {
|
|
20
|
+
const validSkillContent = `---
|
|
21
|
+
name: test-skill
|
|
22
|
+
description: A valid test skill for integration testing
|
|
23
|
+
author: test-author
|
|
24
|
+
version: 1.0.0
|
|
25
|
+
triggers:
|
|
26
|
+
- test trigger
|
|
27
|
+
- another trigger
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Test Skill
|
|
31
|
+
|
|
32
|
+
This is a valid skill with proper frontmatter and content.
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
Use this skill by saying "test trigger".
|
|
37
|
+
`;
|
|
38
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'test-skill', validSkillContent);
|
|
39
|
+
const result = await executeValidate({
|
|
40
|
+
skill_path: skillPath,
|
|
41
|
+
});
|
|
42
|
+
expect(result.valid).toBe(true);
|
|
43
|
+
expect(result.errors.filter((e) => e.severity === 'error')).toHaveLength(0);
|
|
44
|
+
expect(result.metadata).toBeDefined();
|
|
45
|
+
expect(result.metadata?.name).toBe('test-skill');
|
|
46
|
+
});
|
|
47
|
+
it('should detect missing required fields in strict mode', async () => {
|
|
48
|
+
const invalidContent = `---
|
|
49
|
+
name: test-skill
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
# Test Skill
|
|
53
|
+
|
|
54
|
+
Missing description field.
|
|
55
|
+
`;
|
|
56
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'invalid-skill', invalidContent);
|
|
57
|
+
// In strict mode, missing description is an error
|
|
58
|
+
const result = await executeValidate({
|
|
59
|
+
skill_path: skillPath,
|
|
60
|
+
strict: true,
|
|
61
|
+
});
|
|
62
|
+
expect(result.valid).toBe(false);
|
|
63
|
+
const errors = result.errors.filter((e) => e.severity === 'error');
|
|
64
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
65
|
+
expect(errors.some((e) => e.field === 'description')).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('should detect empty frontmatter', async () => {
|
|
68
|
+
const emptyFrontmatter = `---
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
# Just Content
|
|
72
|
+
|
|
73
|
+
No frontmatter fields at all.
|
|
74
|
+
`;
|
|
75
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'empty-fm', emptyFrontmatter);
|
|
76
|
+
const result = await executeValidate({
|
|
77
|
+
skill_path: skillPath,
|
|
78
|
+
});
|
|
79
|
+
expect(result.valid).toBe(false);
|
|
80
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
81
|
+
});
|
|
82
|
+
it('should validate skill directory with SKILL.md', async () => {
|
|
83
|
+
const skillContent = `---
|
|
84
|
+
name: dir-skill
|
|
85
|
+
description: A skill in a directory
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
# Directory Skill
|
|
89
|
+
`;
|
|
90
|
+
const skillDir = path.join(ctx.skillsDir, 'dir-skill');
|
|
91
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
92
|
+
await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent);
|
|
93
|
+
const result = await executeValidate({
|
|
94
|
+
skill_path: skillDir,
|
|
95
|
+
});
|
|
96
|
+
expect(result.path).toContain('SKILL.md');
|
|
97
|
+
});
|
|
98
|
+
it('should throw for non-existent path', async () => {
|
|
99
|
+
await expect(executeValidate({
|
|
100
|
+
skill_path: '/non/existent/path',
|
|
101
|
+
})).rejects.toThrow();
|
|
102
|
+
});
|
|
103
|
+
it('should enforce strict mode', async () => {
|
|
104
|
+
// Create skill with warnings
|
|
105
|
+
const warningContent = `---
|
|
106
|
+
name: warning-skill
|
|
107
|
+
description: Short
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
# Warning Skill
|
|
111
|
+
`;
|
|
112
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'warning-skill', warningContent);
|
|
113
|
+
const normalResult = await executeValidate({
|
|
114
|
+
skill_path: skillPath,
|
|
115
|
+
strict: false,
|
|
116
|
+
});
|
|
117
|
+
const strictResult = await executeValidate({
|
|
118
|
+
skill_path: skillPath,
|
|
119
|
+
strict: true,
|
|
120
|
+
});
|
|
121
|
+
// In strict mode, warnings become errors
|
|
122
|
+
if (normalResult.errors.some((e) => e.severity === 'warning')) {
|
|
123
|
+
expect(strictResult.valid).toBe(false);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it('should detect security issues', async () => {
|
|
127
|
+
const securityContent = `---
|
|
128
|
+
name: security-test
|
|
129
|
+
description: A skill with potential security issues
|
|
130
|
+
url: file:///etc/passwd
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
# Security Test
|
|
134
|
+
`;
|
|
135
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'security-skill', securityContent);
|
|
136
|
+
const result = await executeValidate({
|
|
137
|
+
skill_path: skillPath,
|
|
138
|
+
});
|
|
139
|
+
// Should detect file:// URL as security issue
|
|
140
|
+
const _securityErrors = result.errors.filter((e) => e.message.toLowerCase().includes('security') || e.message.toLowerCase().includes('url'));
|
|
141
|
+
// May or may not have security errors depending on implementation
|
|
142
|
+
expect(result.errors).toBeDefined();
|
|
143
|
+
});
|
|
144
|
+
it('should track timing information', async () => {
|
|
145
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'timing-skill');
|
|
146
|
+
const result = await executeValidate({
|
|
147
|
+
skill_path: skillPath,
|
|
148
|
+
});
|
|
149
|
+
expect(result.timing.totalMs).toBeGreaterThanOrEqual(0);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
describe('formatValidationResults', () => {
|
|
153
|
+
it('should format valid skill results', async () => {
|
|
154
|
+
const validContent = `---
|
|
155
|
+
name: format-test
|
|
156
|
+
description: Testing format output
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
# Format Test
|
|
160
|
+
`;
|
|
161
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'format-skill', validContent);
|
|
162
|
+
const result = await executeValidate({ skill_path: skillPath });
|
|
163
|
+
const formatted = formatValidationResults(result);
|
|
164
|
+
expect(formatted).toContain('Validation');
|
|
165
|
+
});
|
|
166
|
+
it('should format errors and warnings', async () => {
|
|
167
|
+
const invalidContent = `---
|
|
168
|
+
name: error-test
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
# Error Test
|
|
172
|
+
`;
|
|
173
|
+
const skillPath = await createMockInstalledSkill(ctx.skillsDir, 'error-skill', invalidContent);
|
|
174
|
+
const result = await executeValidate({ skill_path: skillPath });
|
|
175
|
+
const formatted = formatValidationResults(result);
|
|
176
|
+
expect(formatted).toBeDefined();
|
|
177
|
+
expect(typeof formatted).toBe('string');
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=validate.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.integration.test.js","sourceRoot":"","sources":["../../../tests/integration/validate.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-run.test.d.ts","sourceRoot":"","sources":["../../../tests/onboarding/first-run.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|