@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,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-911: First Run Detection Unit Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the first-run detection and Tier 1 skill auto-installation module.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { tmpdir } from 'os';
|
|
10
|
+
import { TIER1_SKILLS, isFirstRun, markFirstRunComplete, getWelcomeMessage, SKILLSMITH_DIR, FIRST_RUN_MARKER, } from '../../src/onboarding/first-run.js';
|
|
11
|
+
describe('First Run Detection (SMI-911)', () => {
|
|
12
|
+
// Use a temp directory for testing to avoid modifying real ~/.skillsmith
|
|
13
|
+
const TEST_DIR = join(tmpdir(), `skillsmith-test-${Date.now()}`);
|
|
14
|
+
const TEST_MARKER = join(TEST_DIR, '.first-run-complete');
|
|
15
|
+
// Override the module constants for testing
|
|
16
|
+
let originalSkillsmithDir;
|
|
17
|
+
let originalMarkerFile;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
// Clean up any previous test directory
|
|
20
|
+
if (existsSync(TEST_DIR)) {
|
|
21
|
+
rmSync(TEST_DIR, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
// Clean up test directory
|
|
26
|
+
if (existsSync(TEST_DIR)) {
|
|
27
|
+
rmSync(TEST_DIR, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
describe('TIER1_SKILLS constant', () => {
|
|
31
|
+
it('should define exactly 3 Tier 1 skills', () => {
|
|
32
|
+
expect(TIER1_SKILLS).toHaveLength(3);
|
|
33
|
+
});
|
|
34
|
+
it('should include varlock with score 95', () => {
|
|
35
|
+
const varlock = TIER1_SKILLS.find((s) => s.name === 'varlock');
|
|
36
|
+
expect(varlock).toBeDefined();
|
|
37
|
+
expect(varlock?.id).toBe('anthropic/varlock');
|
|
38
|
+
expect(varlock?.score).toBe(95);
|
|
39
|
+
});
|
|
40
|
+
it('should include commit with score 92', () => {
|
|
41
|
+
const commit = TIER1_SKILLS.find((s) => s.name === 'commit');
|
|
42
|
+
expect(commit).toBeDefined();
|
|
43
|
+
expect(commit?.id).toBe('anthropic/commit');
|
|
44
|
+
expect(commit?.score).toBe(92);
|
|
45
|
+
});
|
|
46
|
+
it('should include governance with score 88', () => {
|
|
47
|
+
const governance = TIER1_SKILLS.find((s) => s.name === 'governance');
|
|
48
|
+
expect(governance).toBeDefined();
|
|
49
|
+
expect(governance?.id).toBe('anthropic/governance');
|
|
50
|
+
expect(governance?.score).toBe(88);
|
|
51
|
+
});
|
|
52
|
+
it('should have skills ordered by score (descending)', () => {
|
|
53
|
+
const scores = TIER1_SKILLS.map((s) => s.score);
|
|
54
|
+
const sortedScores = [...scores].sort((a, b) => b - a);
|
|
55
|
+
expect(scores).toEqual(sortedScores);
|
|
56
|
+
});
|
|
57
|
+
it('should have all skills with valid IDs in author/name format', () => {
|
|
58
|
+
for (const skill of TIER1_SKILLS) {
|
|
59
|
+
expect(skill.id).toMatch(/^[a-z0-9-]+\/[a-z0-9-]+$/);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('isFirstRun()', () => {
|
|
64
|
+
it('should return true when marker file does not exist', () => {
|
|
65
|
+
// FIRST_RUN_MARKER points to ~/.skillsmith/.first-run-complete
|
|
66
|
+
// We need to test the actual behavior, not mock it
|
|
67
|
+
// For this test, we verify the function reads the actual marker path
|
|
68
|
+
const result = isFirstRun();
|
|
69
|
+
// Result depends on whether the marker exists in the real location
|
|
70
|
+
expect(typeof result).toBe('boolean');
|
|
71
|
+
});
|
|
72
|
+
it('should return false when marker file exists', () => {
|
|
73
|
+
// Create the real marker file temporarily
|
|
74
|
+
const markerDir = SKILLSMITH_DIR;
|
|
75
|
+
const wasMarkerExisting = existsSync(FIRST_RUN_MARKER);
|
|
76
|
+
if (!existsSync(markerDir)) {
|
|
77
|
+
mkdirSync(markerDir, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
// Create marker if it doesn't exist
|
|
80
|
+
if (!wasMarkerExisting) {
|
|
81
|
+
writeFileSync(FIRST_RUN_MARKER, 'test');
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const result = isFirstRun();
|
|
85
|
+
expect(result).toBe(false);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
// Clean up only if we created it
|
|
89
|
+
if (!wasMarkerExisting && existsSync(FIRST_RUN_MARKER)) {
|
|
90
|
+
rmSync(FIRST_RUN_MARKER);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
it('should use existsSync to check marker file', () => {
|
|
95
|
+
// This verifies the implementation uses the file system
|
|
96
|
+
// The function should be pure (same input = same output)
|
|
97
|
+
const result1 = isFirstRun();
|
|
98
|
+
const result2 = isFirstRun();
|
|
99
|
+
expect(result1).toBe(result2);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('markFirstRunComplete()', () => {
|
|
103
|
+
it('should create the .skillsmith directory if it does not exist', () => {
|
|
104
|
+
// Ensure clean state by checking if directory needs to be created
|
|
105
|
+
const dirExistedBefore = existsSync(SKILLSMITH_DIR);
|
|
106
|
+
try {
|
|
107
|
+
markFirstRunComplete();
|
|
108
|
+
expect(existsSync(SKILLSMITH_DIR)).toBe(true);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
// Don't remove the directory if it existed before
|
|
112
|
+
if (!dirExistedBefore) {
|
|
113
|
+
// Only remove the marker, not the directory
|
|
114
|
+
if (existsSync(FIRST_RUN_MARKER)) {
|
|
115
|
+
rmSync(FIRST_RUN_MARKER);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
it('should create the marker file', () => {
|
|
121
|
+
const markerExistedBefore = existsSync(FIRST_RUN_MARKER);
|
|
122
|
+
try {
|
|
123
|
+
markFirstRunComplete();
|
|
124
|
+
expect(existsSync(FIRST_RUN_MARKER)).toBe(true);
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
// Clean up if we created it
|
|
128
|
+
if (!markerExistedBefore && existsSync(FIRST_RUN_MARKER)) {
|
|
129
|
+
rmSync(FIRST_RUN_MARKER);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
it('should write ISO timestamp to marker file', () => {
|
|
134
|
+
const markerExistedBefore = existsSync(FIRST_RUN_MARKER);
|
|
135
|
+
let originalContent;
|
|
136
|
+
if (markerExistedBefore) {
|
|
137
|
+
originalContent = readFileSync(FIRST_RUN_MARKER, 'utf-8');
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const beforeCall = new Date();
|
|
141
|
+
markFirstRunComplete();
|
|
142
|
+
const afterCall = new Date();
|
|
143
|
+
const content = readFileSync(FIRST_RUN_MARKER, 'utf-8');
|
|
144
|
+
const timestamp = new Date(content);
|
|
145
|
+
// Verify it's a valid ISO date
|
|
146
|
+
expect(timestamp.toISOString()).toBe(content);
|
|
147
|
+
// Verify timestamp is within expected range
|
|
148
|
+
expect(timestamp.getTime()).toBeGreaterThanOrEqual(beforeCall.getTime());
|
|
149
|
+
expect(timestamp.getTime()).toBeLessThanOrEqual(afterCall.getTime());
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
// Restore original content or remove marker
|
|
153
|
+
if (markerExistedBefore && originalContent !== undefined) {
|
|
154
|
+
writeFileSync(FIRST_RUN_MARKER, originalContent);
|
|
155
|
+
}
|
|
156
|
+
else if (!markerExistedBefore && existsSync(FIRST_RUN_MARKER)) {
|
|
157
|
+
rmSync(FIRST_RUN_MARKER);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
it('should be idempotent (can be called multiple times)', () => {
|
|
162
|
+
const markerExistedBefore = existsSync(FIRST_RUN_MARKER);
|
|
163
|
+
let originalContent;
|
|
164
|
+
if (markerExistedBefore) {
|
|
165
|
+
originalContent = readFileSync(FIRST_RUN_MARKER, 'utf-8');
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
markFirstRunComplete();
|
|
169
|
+
markFirstRunComplete();
|
|
170
|
+
markFirstRunComplete();
|
|
171
|
+
expect(existsSync(FIRST_RUN_MARKER)).toBe(true);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
if (markerExistedBefore && originalContent !== undefined) {
|
|
175
|
+
writeFileSync(FIRST_RUN_MARKER, originalContent);
|
|
176
|
+
}
|
|
177
|
+
else if (!markerExistedBefore && existsSync(FIRST_RUN_MARKER)) {
|
|
178
|
+
rmSync(FIRST_RUN_MARKER);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
it('should make isFirstRun return false after being called', () => {
|
|
183
|
+
const markerExistedBefore = existsSync(FIRST_RUN_MARKER);
|
|
184
|
+
let originalContent;
|
|
185
|
+
if (markerExistedBefore) {
|
|
186
|
+
originalContent = readFileSync(FIRST_RUN_MARKER, 'utf-8');
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
markFirstRunComplete();
|
|
190
|
+
expect(isFirstRun()).toBe(false);
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
if (markerExistedBefore && originalContent !== undefined) {
|
|
194
|
+
writeFileSync(FIRST_RUN_MARKER, originalContent);
|
|
195
|
+
}
|
|
196
|
+
else if (!markerExistedBefore && existsSync(FIRST_RUN_MARKER)) {
|
|
197
|
+
rmSync(FIRST_RUN_MARKER);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe('getWelcomeMessage()', () => {
|
|
203
|
+
it('should return formatted welcome message with skill list', () => {
|
|
204
|
+
const skills = ['varlock', 'commit', 'governance'];
|
|
205
|
+
const message = getWelcomeMessage(skills);
|
|
206
|
+
expect(message).toContain('Welcome to Skillsmith!');
|
|
207
|
+
expect(message).toContain('Essential skills installed:');
|
|
208
|
+
expect(message).toContain('- varlock');
|
|
209
|
+
expect(message).toContain('- commit');
|
|
210
|
+
expect(message).toContain('- governance');
|
|
211
|
+
});
|
|
212
|
+
it('should include usage hint for commit skill', () => {
|
|
213
|
+
const skills = ['varlock', 'commit', 'governance'];
|
|
214
|
+
const message = getWelcomeMessage(skills);
|
|
215
|
+
expect(message).toContain('Write a commit message');
|
|
216
|
+
});
|
|
217
|
+
it('should handle empty skill list', () => {
|
|
218
|
+
const message = getWelcomeMessage([]);
|
|
219
|
+
expect(message).toContain('Welcome to Skillsmith!');
|
|
220
|
+
expect(message).toContain('Essential skills installed:');
|
|
221
|
+
// Should still have the structure, just no skills listed
|
|
222
|
+
});
|
|
223
|
+
it('should handle single skill', () => {
|
|
224
|
+
const message = getWelcomeMessage(['varlock']);
|
|
225
|
+
expect(message).toContain('Welcome to Skillsmith!');
|
|
226
|
+
expect(message).toContain('- varlock');
|
|
227
|
+
expect(message).not.toContain('- commit');
|
|
228
|
+
});
|
|
229
|
+
it('should format each skill with dash prefix', () => {
|
|
230
|
+
const skills = ['skill1', 'skill2', 'skill3'];
|
|
231
|
+
const message = getWelcomeMessage(skills);
|
|
232
|
+
for (const skill of skills) {
|
|
233
|
+
expect(message).toContain(`- ${skill}`);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
it('should return trimmed message without leading/trailing whitespace', () => {
|
|
237
|
+
const message = getWelcomeMessage(['test']);
|
|
238
|
+
expect(message).not.toMatch(/^\s/);
|
|
239
|
+
expect(message).not.toMatch(/\s$/);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
describe('Module exports', () => {
|
|
243
|
+
it('should export SKILLSMITH_DIR constant', () => {
|
|
244
|
+
expect(SKILLSMITH_DIR).toBeDefined();
|
|
245
|
+
expect(typeof SKILLSMITH_DIR).toBe('string');
|
|
246
|
+
expect(SKILLSMITH_DIR).toContain('.skillsmith');
|
|
247
|
+
});
|
|
248
|
+
it('should export FIRST_RUN_MARKER constant', () => {
|
|
249
|
+
expect(FIRST_RUN_MARKER).toBeDefined();
|
|
250
|
+
expect(typeof FIRST_RUN_MARKER).toBe('string');
|
|
251
|
+
expect(FIRST_RUN_MARKER).toContain('.first-run-complete');
|
|
252
|
+
});
|
|
253
|
+
it('should have FIRST_RUN_MARKER inside SKILLSMITH_DIR', () => {
|
|
254
|
+
expect(FIRST_RUN_MARKER.startsWith(SKILLSMITH_DIR)).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
//# sourceMappingURL=first-run.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-run.test.js","sourceRoot":"","sources":["../../../tests/onboarding/first-run.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Validation Tests
|
|
3
|
+
*
|
|
4
|
+
* Validates that search and retrieval operations meet performance requirements.
|
|
5
|
+
* Tests are designed to catch performance regressions.
|
|
6
|
+
*
|
|
7
|
+
* @see SMI-797: Performance validation
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=search-performance.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-performance.test.d.ts","sourceRoot":"","sources":["../../../tests/performance/search-performance.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Validation Tests
|
|
3
|
+
*
|
|
4
|
+
* Validates that search and retrieval operations meet performance requirements.
|
|
5
|
+
* Tests are designed to catch performance regressions.
|
|
6
|
+
*
|
|
7
|
+
* @see SMI-797: Performance validation
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
10
|
+
import { existsSync, rmSync, mkdirSync } from 'fs';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
import { tmpdir } from 'os';
|
|
13
|
+
import { createDatabase, initializeSchema, SkillRepository, } from '@skillsmith/core';
|
|
14
|
+
import { createToolContext } from '../../src/context.js';
|
|
15
|
+
import { executeSearch } from '../../src/tools/search.js';
|
|
16
|
+
import { executeGetSkill } from '../../src/tools/get-skill.js';
|
|
17
|
+
// Generate bulk test data
|
|
18
|
+
function generateSkills(count) {
|
|
19
|
+
const trustTiers = [
|
|
20
|
+
'verified',
|
|
21
|
+
'community',
|
|
22
|
+
'experimental',
|
|
23
|
+
];
|
|
24
|
+
const categories = ['development', 'testing', 'devops', 'database', 'security'];
|
|
25
|
+
return Array.from({ length: count }, (_, i) => ({
|
|
26
|
+
id: `test-org/skill-${i}`,
|
|
27
|
+
name: `skill-${i}`,
|
|
28
|
+
description: `Test skill number ${i} for performance testing. This skill helps with ${categories[i % categories.length]} tasks.`,
|
|
29
|
+
author: `author-${i % 10}`,
|
|
30
|
+
repoUrl: `https://github.com/test-org/skill-${i}`,
|
|
31
|
+
qualityScore: 0.5 + (i % 50) / 100,
|
|
32
|
+
trustTier: trustTiers[i % trustTiers.length],
|
|
33
|
+
tags: [categories[i % categories.length], `tag-${i % 20}`, `group-${i % 5}`],
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
describe('SMI-797: Performance Validation', () => {
|
|
37
|
+
let db;
|
|
38
|
+
let context;
|
|
39
|
+
let testDbPath;
|
|
40
|
+
const SKILL_COUNT = 500;
|
|
41
|
+
beforeAll(() => {
|
|
42
|
+
// Create isolated test database
|
|
43
|
+
const testDir = join(tmpdir(), 'skillsmith-perf-test');
|
|
44
|
+
if (!existsSync(testDir)) {
|
|
45
|
+
mkdirSync(testDir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
testDbPath = join(testDir, `perf-test-${Date.now()}.db`);
|
|
48
|
+
// Initialize database with bulk data
|
|
49
|
+
db = createDatabase(testDbPath);
|
|
50
|
+
initializeSchema(db);
|
|
51
|
+
const skillRepository = new SkillRepository(db);
|
|
52
|
+
const skills = generateSkills(SKILL_COUNT);
|
|
53
|
+
// Batch insert for performance
|
|
54
|
+
for (const skill of skills) {
|
|
55
|
+
skillRepository.create(skill);
|
|
56
|
+
}
|
|
57
|
+
// Create context
|
|
58
|
+
context = createToolContext({ dbPath: testDbPath });
|
|
59
|
+
});
|
|
60
|
+
afterAll(() => {
|
|
61
|
+
db?.close();
|
|
62
|
+
if (testDbPath && existsSync(testDbPath)) {
|
|
63
|
+
rmSync(testDbPath, { force: true });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
describe('Search Performance', () => {
|
|
67
|
+
it('should complete single search under 50ms with 500 skills', async () => {
|
|
68
|
+
const start = performance.now();
|
|
69
|
+
const result = await executeSearch({ query: 'test' }, context);
|
|
70
|
+
const elapsed = performance.now() - start;
|
|
71
|
+
expect(elapsed).toBeLessThan(50);
|
|
72
|
+
expect(result.results.length).toBeGreaterThan(0);
|
|
73
|
+
});
|
|
74
|
+
it('should complete filtered search under 50ms', async () => {
|
|
75
|
+
const start = performance.now();
|
|
76
|
+
await executeSearch({
|
|
77
|
+
query: 'development',
|
|
78
|
+
min_score: 60,
|
|
79
|
+
}, context);
|
|
80
|
+
const elapsed = performance.now() - start;
|
|
81
|
+
expect(elapsed).toBeLessThan(50);
|
|
82
|
+
});
|
|
83
|
+
it('should handle 10 concurrent searches under 200ms total', async () => {
|
|
84
|
+
const queries = [
|
|
85
|
+
'test',
|
|
86
|
+
'development',
|
|
87
|
+
'testing',
|
|
88
|
+
'devops',
|
|
89
|
+
'database',
|
|
90
|
+
'skill',
|
|
91
|
+
'security',
|
|
92
|
+
'author',
|
|
93
|
+
'group',
|
|
94
|
+
'tag',
|
|
95
|
+
];
|
|
96
|
+
const start = performance.now();
|
|
97
|
+
const results = await Promise.all(queries.map((query) => executeSearch({ query }, context)));
|
|
98
|
+
const elapsed = performance.now() - start;
|
|
99
|
+
expect(elapsed).toBeLessThan(200);
|
|
100
|
+
expect(results.every((r) => r.results !== undefined)).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
it('should maintain sub-100ms response for repeated searches', async () => {
|
|
103
|
+
const timings = [];
|
|
104
|
+
for (let i = 0; i < 20; i++) {
|
|
105
|
+
const start = performance.now();
|
|
106
|
+
await executeSearch({ query: `skill-${i * 10}` }, context);
|
|
107
|
+
timings.push(performance.now() - start);
|
|
108
|
+
}
|
|
109
|
+
const avgTime = timings.reduce((a, b) => a + b, 0) / timings.length;
|
|
110
|
+
const maxTime = Math.max(...timings);
|
|
111
|
+
expect(avgTime).toBeLessThan(30);
|
|
112
|
+
expect(maxTime).toBeLessThan(100);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
describe('Get Skill Performance', () => {
|
|
116
|
+
it('should complete single get-skill under 20ms', async () => {
|
|
117
|
+
const start = performance.now();
|
|
118
|
+
const result = await executeGetSkill({ id: 'test-org/skill-0' }, context);
|
|
119
|
+
const elapsed = performance.now() - start;
|
|
120
|
+
expect(elapsed).toBeLessThan(20);
|
|
121
|
+
expect(result.skill.id).toBe('test-org/skill-0');
|
|
122
|
+
});
|
|
123
|
+
it('should handle 50 sequential get-skill calls under 500ms', async () => {
|
|
124
|
+
const start = performance.now();
|
|
125
|
+
for (let i = 0; i < 50; i++) {
|
|
126
|
+
await executeGetSkill({ id: `test-org/skill-${i}` }, context);
|
|
127
|
+
}
|
|
128
|
+
const elapsed = performance.now() - start;
|
|
129
|
+
expect(elapsed).toBeLessThan(500);
|
|
130
|
+
});
|
|
131
|
+
it('should handle 20 concurrent get-skill calls under 100ms', async () => {
|
|
132
|
+
const ids = Array.from({ length: 20 }, (_, i) => `test-org/skill-${i}`);
|
|
133
|
+
const start = performance.now();
|
|
134
|
+
const results = await Promise.all(ids.map((id) => executeGetSkill({ id }, context)));
|
|
135
|
+
const elapsed = performance.now() - start;
|
|
136
|
+
expect(elapsed).toBeLessThan(100);
|
|
137
|
+
expect(results.every((r) => r.skill !== undefined)).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('Combined Flow Performance', () => {
|
|
141
|
+
it('should complete search → get flow under 50ms', async () => {
|
|
142
|
+
const start = performance.now();
|
|
143
|
+
// Search
|
|
144
|
+
const searchResult = await executeSearch({ query: 'test' }, context);
|
|
145
|
+
expect(searchResult.results.length).toBeGreaterThan(0);
|
|
146
|
+
// Get first result
|
|
147
|
+
const firstId = searchResult.results[0].id;
|
|
148
|
+
await executeGetSkill({ id: firstId }, context);
|
|
149
|
+
const elapsed = performance.now() - start;
|
|
150
|
+
expect(elapsed).toBeLessThan(50);
|
|
151
|
+
});
|
|
152
|
+
it('should complete search → get all results flow under 200ms', async () => {
|
|
153
|
+
const start = performance.now();
|
|
154
|
+
// Search with limit
|
|
155
|
+
const searchResult = await executeSearch({ query: 'test' }, context);
|
|
156
|
+
// Get all results (up to 10)
|
|
157
|
+
const ids = searchResult.results.slice(0, 10).map((r) => r.id);
|
|
158
|
+
await Promise.all(ids.map((id) => executeGetSkill({ id }, context)));
|
|
159
|
+
const elapsed = performance.now() - start;
|
|
160
|
+
expect(elapsed).toBeLessThan(200);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('Memory and Resource Usage', () => {
|
|
164
|
+
it('should not leak memory across repeated operations', async () => {
|
|
165
|
+
const initialMemory = process.memoryUsage().heapUsed;
|
|
166
|
+
// Perform 100 search operations
|
|
167
|
+
for (let i = 0; i < 100; i++) {
|
|
168
|
+
await executeSearch({ query: `skill-${i}` }, context);
|
|
169
|
+
}
|
|
170
|
+
// Force garbage collection if available
|
|
171
|
+
if (global.gc) {
|
|
172
|
+
global.gc();
|
|
173
|
+
}
|
|
174
|
+
const finalMemory = process.memoryUsage().heapUsed;
|
|
175
|
+
const memoryIncrease = (finalMemory - initialMemory) / 1024 / 1024; // MB
|
|
176
|
+
// Allow up to 50MB increase (generous for test stability)
|
|
177
|
+
expect(memoryIncrease).toBeLessThan(50);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
describe('Performance Benchmarks Summary', () => {
|
|
181
|
+
it('should report performance metrics', async () => {
|
|
182
|
+
const metrics = {
|
|
183
|
+
singleSearch: 0,
|
|
184
|
+
singleGet: 0,
|
|
185
|
+
concurrentSearches: 0,
|
|
186
|
+
searchGetFlow: 0,
|
|
187
|
+
};
|
|
188
|
+
// Single search
|
|
189
|
+
let start = performance.now();
|
|
190
|
+
await executeSearch({ query: 'test' }, context);
|
|
191
|
+
metrics.singleSearch = performance.now() - start;
|
|
192
|
+
// Single get
|
|
193
|
+
start = performance.now();
|
|
194
|
+
await executeGetSkill({ id: 'test-org/skill-0' }, context);
|
|
195
|
+
metrics.singleGet = performance.now() - start;
|
|
196
|
+
// Concurrent searches (10)
|
|
197
|
+
start = performance.now();
|
|
198
|
+
await Promise.all(Array.from({ length: 10 }, (_, i) => executeSearch({ query: `skill-${i}` }, context)));
|
|
199
|
+
metrics.concurrentSearches = performance.now() - start;
|
|
200
|
+
// Search + Get flow
|
|
201
|
+
start = performance.now();
|
|
202
|
+
const result = await executeSearch({ query: 'test' }, context);
|
|
203
|
+
await executeGetSkill({ id: result.results[0].id }, context);
|
|
204
|
+
metrics.searchGetFlow = performance.now() - start;
|
|
205
|
+
console.log('Performance Metrics (ms):');
|
|
206
|
+
console.log(` Single Search: ${metrics.singleSearch.toFixed(2)}`);
|
|
207
|
+
console.log(` Single Get: ${metrics.singleGet.toFixed(2)}`);
|
|
208
|
+
console.log(` 10 Concurrent Searches: ${metrics.concurrentSearches.toFixed(2)}`);
|
|
209
|
+
console.log(` Search + Get Flow: ${metrics.searchGetFlow.toFixed(2)}`);
|
|
210
|
+
// Assertions
|
|
211
|
+
expect(metrics.singleSearch).toBeLessThan(50);
|
|
212
|
+
expect(metrics.singleGet).toBeLessThan(20);
|
|
213
|
+
expect(metrics.concurrentSearches).toBeLessThan(200);
|
|
214
|
+
expect(metrics.searchGetFlow).toBeLessThan(50);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=search-performance.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-performance.test.js","sourceRoot":"","sources":["../../../tests/performance/search-performance.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend.test.d.ts","sourceRoot":"","sources":["../../tests/recommend.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|