@skyramp/mcp 0.2.6 → 0.2.8-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/commandLibrary.d.ts +12 -0
- package/build/commands/recommendTestsAndExecuteCommand.d.ts +2 -0
- package/build/commands/testThisEndpointCommand.d.ts +2 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +6 -4
- package/build/playwright/PlaywrightTraceService.d.ts +32 -0
- package/build/playwright/index.d.ts +3 -0
- package/build/playwright/registerPlaywrightTools.d.ts +8 -0
- package/build/playwright/registerPlaywrightTools.js +12 -11
- package/build/playwright/traceRecordingPrompt.d.ts +13 -0
- package/build/playwright/traceRecordingPrompt.js +3 -11
- package/build/prompts/code-reuse.d.ts +1 -0
- package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +15 -0
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +24 -5
- package/build/prompts/fix-error-prompt.d.ts +1 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.d.ts +1 -0
- package/build/prompts/modularization/integration-test-modularization.d.ts +1 -0
- package/build/prompts/modularization/ui-test-modularization.d.ts +1 -0
- package/build/prompts/personas.d.ts +21 -0
- package/build/prompts/pom-aware-code-reuse.d.ts +1 -0
- package/build/prompts/startTraceCollectionPrompts.d.ts +2 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.d.ts +2 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +114 -0
- package/build/prompts/sut-setup/modes/dockerComposePrompt.d.ts +2 -0
- package/build/prompts/sut-setup/modes/dockerComposePrompt.js +292 -0
- package/build/prompts/sut-setup/shared.d.ts +39 -0
- package/build/prompts/sut-setup/shared.js +132 -0
- package/build/prompts/test-maintenance/actionsInstructions.d.ts +35 -0
- package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +4 -0
- package/build/prompts/test-maintenance/driftAnalysisSections.d.ts +13 -0
- package/build/prompts/test-maintenance/driftAnalysisSections.js +9 -3
- package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +84 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +1 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +1 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +1 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +17 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.js +83 -18
- package/build/prompts/test-recommendation/fullRepoCatalog.d.ts +7 -0
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +1 -0
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +1 -0
- package/build/prompts/test-recommendation/promptPlan.d.ts +203 -0
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +1 -0
- package/build/prompts/test-recommendation/recommendationSections.d.ts +35 -0
- package/build/prompts/test-recommendation/recommendationShared.d.ts +31 -0
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +7 -0
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +55 -0
- package/build/prompts/test-recommendation/scopeAssessment.js +2 -2
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +1 -0
- package/build/prompts/test-recommendation/scopeAssessment.test.js +1 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +6 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +4 -4
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +1 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +97 -99
- package/build/prompts/testbot/testbot-prompts.d.ts +26 -0
- package/build/prompts/testbot/testbot-prompts.js +301 -46
- package/build/prompts/testbot/testbot-prompts.test.d.ts +1 -0
- package/build/prompts/testbot/testbot-prompts.test.js +109 -117
- package/build/resources/analysisResources.d.ts +17 -0
- package/build/resources/progressResource.d.ts +2 -0
- package/build/resources/sutSetupResource.d.ts +2 -0
- package/build/resources/sutSetupResource.js +45 -0
- package/build/resources/testbotResource.d.ts +2 -0
- package/build/resources/testbotResource.js +2 -2
- package/build/services/AnalyticsService.d.ts +13 -0
- package/build/services/AnalyticsService.test.d.ts +1 -0
- package/build/services/AnalyticsService.test.js +86 -0
- package/build/services/ModularizationService.d.ts +11 -0
- package/build/services/ScenarioGenerationService.d.ts +37 -0
- package/build/services/ScenarioGenerationService.integration.test.d.ts +1 -0
- package/build/services/ScenarioGenerationService.integration.test.js +4 -0
- package/build/services/ScenarioGenerationService.test.d.ts +1 -0
- package/build/services/TestDiscoveryService.d.ts +128 -0
- package/build/services/TestDiscoveryService.js +22 -12
- package/build/services/TestDiscoveryService.test.d.ts +1 -0
- package/build/services/TestDiscoveryService.test.js +4 -3
- package/build/services/TestExecutionService.d.ts +55 -0
- package/build/services/TestExecutionService.js +158 -26
- package/build/services/TestExecutionService.test.d.ts +1 -0
- package/build/services/TestExecutionService.test.js +339 -25
- package/build/services/TestGenerationService.d.ts +56 -0
- package/build/services/TestGenerationService.test.d.ts +1 -0
- package/build/services/TestGenerationService.test.js +10 -8
- package/build/services/containerEnv.d.ts +14 -0
- package/build/tool-phase-coverage.test.d.ts +1 -0
- package/build/tool-phase-coverage.test.js +2 -0
- package/build/tool-phases.d.ts +38 -0
- package/build/tools/auth/loginTool.d.ts +2 -0
- package/build/tools/auth/logoutTool.d.ts +2 -0
- package/build/tools/code-refactor/codeReuseTool.d.ts +2 -0
- package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +2 -0
- package/build/tools/code-refactor/modularizationTool.d.ts +2 -0
- package/build/tools/executeSkyrampTestTool.d.ts +2 -0
- package/build/tools/executeSkyrampTestTool.js +26 -7
- package/build/tools/fixErrorTool.d.ts +2 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +45 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +1 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +1 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +11 -9
- package/build/tools/generate-tests/generateContractRestTool.d.ts +31 -0
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +13 -0
- package/build/tools/generate-tests/generateFuzzRestTool.d.ts +10 -0
- package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +16 -0
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +18 -0
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +1 -0
- package/build/tools/generate-tests/generateMockRestTool.d.ts +64 -0
- package/build/tools/generate-tests/generateSmokeRestTool.d.ts +8 -0
- package/build/tools/generate-tests/generateUIRestTool.d.ts +14 -0
- package/build/tools/generate-tests/generateUIRestTool.js +1 -1
- package/build/tools/generate-tests/loadTestSchema.d.ts +39 -0
- package/build/tools/one-click/oneClickTool.d.ts +11 -0
- package/build/tools/submitReportTool.d.ts +394 -0
- package/build/tools/submitReportTool.js +250 -41
- package/build/tools/submitReportTool.test.d.ts +1 -0
- package/build/tools/submitReportTool.test.js +511 -55
- package/build/tools/test-management/actionsTool.d.ts +10 -0
- package/build/tools/test-management/actionsTool.js +21 -7
- package/build/tools/test-management/analyzeChangesTool.d.ts +27 -0
- package/build/tools/test-management/analyzeChangesTool.js +150 -48
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +1 -0
- package/build/tools/test-management/analyzeChangesTool.test.js +95 -78
- package/build/tools/test-management/analyzeTestHealthTool.d.ts +2 -0
- package/build/tools/test-management/analyzeTestHealthTool.js +16 -9
- package/build/tools/test-management/index.d.ts +3 -0
- package/build/tools/test-management/index.js +0 -1
- package/build/tools/trace/resolveSaveStoragePath.d.ts +7 -0
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +1 -0
- package/build/tools/trace/resolveSessionPaths.d.ts +40 -0
- package/build/tools/trace/resolveSessionPaths.test.d.ts +1 -0
- package/build/tools/trace/sessionState.d.ts +2 -0
- package/build/tools/trace/sessionState.test.d.ts +1 -0
- package/build/tools/trace/startTraceCollectionTool.d.ts +2 -0
- package/build/tools/trace/stopTraceCollectionTool.d.ts +2 -0
- package/build/tools/workspace/initScanWorkspaceTool.d.ts +4 -0
- package/build/tools/workspace/initializeWorkspaceTool.d.ts +2 -0
- package/build/tools/workspace/initializeWorkspaceTool.js +39 -22
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +1 -0
- package/build/tools/workspace/initializeWorkspaceTool.test.js +134 -0
- package/build/tools/workspace/serviceUpsert.d.ts +12 -0
- package/build/tools/workspace/serviceUpsert.js +23 -0
- package/build/tools/workspace/serviceUpsert.test.d.ts +1 -0
- package/build/tools/workspace/serviceUpsert.test.js +50 -0
- package/build/types/OneClickCommands.d.ts +68 -0
- package/build/types/RepositoryAnalysis.d.ts +3004 -0
- package/build/types/TestAnalysis.d.ts +97 -0
- package/build/types/TestExecution.d.ts +63 -0
- package/build/types/TestExecution.js +11 -1
- package/build/types/TestRecommendation.d.ts +12 -0
- package/build/types/TestTypes.d.ts +234 -0
- package/build/types/TestbotReport.d.ts +68 -0
- package/build/types/TestbotReport.js +1 -0
- package/build/types/index.d.ts +4 -0
- package/build/types/index.js +3 -0
- package/build/utils/AnalysisStateManager.d.ts +242 -0
- package/build/utils/AnalysisStateManager.js +144 -3
- package/build/utils/AnalysisStateManager.test.d.ts +1 -0
- package/build/utils/AnalysisStateManager.test.js +98 -0
- package/build/utils/analyze-openapi.d.ts +1 -0
- package/build/utils/branchDiff.d.ts +18 -0
- package/build/utils/dartRouteExtractor.d.ts +45 -0
- package/build/utils/dartRouteExtractor.test.d.ts +1 -0
- package/build/utils/docker.d.ts +19 -0
- package/build/utils/docker.test.d.ts +1 -0
- package/build/utils/docker.test.js +10 -9
- package/build/utils/featureFlags.d.ts +37 -0
- package/build/utils/featureFlags.test.d.ts +1 -0
- package/build/utils/gitStaging.d.ts +24 -0
- package/build/utils/gitStaging.test.d.ts +1 -0
- package/build/utils/gitStaging.test.js +13 -7
- package/build/utils/httpDefaults.d.ts +10 -0
- package/build/utils/httpDefaults.test.d.ts +1 -0
- package/build/utils/initAgent.d.ts +36 -0
- package/build/utils/language-helper.d.ts +6 -0
- package/build/utils/logger.d.ts +11 -0
- package/build/utils/normalizeParams.d.ts +14 -0
- package/build/utils/normalizeSkyrampImports.d.ts +13 -0
- package/build/utils/pr-comment-parser.d.ts +31 -0
- package/build/utils/pr-comment-parser.test.d.ts +1 -0
- package/build/utils/pr-comment-parser.test.js +6 -5
- package/build/utils/projectMetadata.d.ts +15 -0
- package/build/utils/projectMetadata.test.d.ts +1 -0
- package/build/utils/proxy-terminal.d.ts +2 -0
- package/build/utils/repoScanner.d.ts +27 -0
- package/build/utils/repoScanner.test.d.ts +1 -0
- package/build/utils/routeParsers.d.ts +53 -0
- package/build/utils/routeParsers.js +31 -38
- package/build/utils/routeParsers.test.d.ts +1 -0
- package/build/utils/scenarioDrafting.d.ts +71 -0
- package/build/utils/scenarioDrafting.js +23 -1
- package/build/utils/scenarioDrafting.test.d.ts +1 -0
- package/build/utils/skyrampMdContent.d.ts +5 -0
- package/build/utils/sourceRouteExtractor.d.ts +48 -0
- package/build/utils/sourceRouteExtractor.test.d.ts +1 -0
- package/build/utils/telemetry.d.ts +32 -0
- package/build/utils/telemetry.test.d.ts +1 -0
- package/build/utils/trace-parser.d.ts +32 -0
- package/build/utils/trace-parser.test.d.ts +6 -0
- package/build/utils/uiPageEnumerator.d.ts +146 -0
- package/build/utils/uiPageEnumerator.js +58 -14
- package/build/utils/uiPageEnumerator.test.d.ts +1 -0
- package/build/utils/uiPageEnumerator.test.js +223 -43
- package/build/utils/utils.d.ts +45 -0
- package/build/utils/utils.js +10 -0
- package/build/utils/utils.test.d.ts +1 -0
- package/build/utils/versions.d.ts +3 -0
- package/build/utils/versions.js +1 -1
- package/build/utils/workspaceAuth.d.ts +127 -0
- package/build/utils/workspaceAuth.test.d.ts +1 -0
- package/build/utils/workspaceAuth.test.js +25 -25
- package/build/workspace/index.d.ts +1 -0
- package/build/workspace/workspace.d.ts +390 -0
- package/build/workspace/workspace.js +7 -7
- package/build/workspace/workspace.test.d.ts +1 -0
- package/build/workspace/workspace.test.js +6 -6
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -13
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +88 -15
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -3
- package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +23 -126
- package/node_modules/playwright/node_modules/playwright-core/lib/generated/injectedScriptSource.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +79 -19
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/aliasRemapper.js +84 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +15 -4
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-CPZKmjFR.js → codeMirrorModule-D0BjbCb7.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +193 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-B0JOjboO.js → codeMirrorModule-Cqp3cwEJ.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{defaultSettingsView-1anWeyDf.js → defaultSettingsView-CYf9adZh.js} +79 -79
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.Cc5029a3.js → index.B_7ywgmr.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{uiMode.Wo5yvvVh.js → uiMode.u4_8VnCV.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/generated/injectedScriptSource.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +129 -43
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/aliasRemapper.ts +119 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +33 -10
- package/node_modules/playwright/package.json +1 -1
- package/package.json +16 -4
- package/build/tools/test-management/uiAnalyzeChangesTool.js +0 -155
- package/build/tools/test-management/uiAnalyzeChangesTool.test.js +0 -147
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.bin/node-which +0 -52
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/is-docker +0 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/mime +0 -46
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/yaml +0 -11
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-CsgPR2wy.js +0 -193
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.CP3Y8Zsb.js +0 -2
|
@@ -1,28 +1,52 @@
|
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
1
3
|
import { buildContainerEnv, rewriteLocalhostForDocker } from "./containerEnv.js";
|
|
2
4
|
// Mock dockerode before importing TestExecutionService
|
|
3
5
|
const mockRun = jest.fn();
|
|
4
6
|
const mockListImages = jest.fn();
|
|
5
|
-
jest.
|
|
6
|
-
|
|
7
|
+
jest.unstable_mockModule("dockerode", () => ({
|
|
8
|
+
default: jest.fn().mockImplementation(() => ({
|
|
7
9
|
run: mockRun,
|
|
8
10
|
listImages: mockListImages,
|
|
9
|
-
}))
|
|
11
|
+
})),
|
|
12
|
+
}));
|
|
13
|
+
// Get actual fs for spreading, then mock specific methods
|
|
14
|
+
const actualFs = await import("fs");
|
|
15
|
+
const mockAccessSync = jest.fn();
|
|
16
|
+
const mockExistsSync = jest.fn().mockReturnValue(true);
|
|
17
|
+
const mockReaddirSync = jest.fn().mockImplementation((_path, options) => {
|
|
18
|
+
if (options?.withFileTypes) {
|
|
19
|
+
return [{ name: "test_file.py", isFile: () => true, isDirectory: () => false }];
|
|
20
|
+
}
|
|
21
|
+
return ["test_file.py"];
|
|
10
22
|
});
|
|
11
|
-
|
|
12
|
-
jest.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
const mockReadFileSync = jest.fn().mockReturnValue("");
|
|
24
|
+
const mockWriteFileSync = jest.fn();
|
|
25
|
+
const mockMkdirSync = jest.fn();
|
|
26
|
+
const mockRmSync = jest.fn();
|
|
27
|
+
jest.unstable_mockModule("fs", () => ({
|
|
28
|
+
...actualFs,
|
|
29
|
+
default: {
|
|
30
|
+
...actualFs.default,
|
|
31
|
+
accessSync: mockAccessSync,
|
|
32
|
+
existsSync: mockExistsSync,
|
|
33
|
+
readdirSync: mockReaddirSync,
|
|
34
|
+
readFileSync: mockReadFileSync,
|
|
35
|
+
writeFileSync: mockWriteFileSync,
|
|
36
|
+
mkdirSync: mockMkdirSync,
|
|
37
|
+
rmSync: mockRmSync,
|
|
38
|
+
constants: actualFs.default.constants,
|
|
39
|
+
},
|
|
40
|
+
accessSync: mockAccessSync,
|
|
41
|
+
existsSync: mockExistsSync,
|
|
42
|
+
readdirSync: mockReaddirSync,
|
|
43
|
+
readFileSync: mockReadFileSync,
|
|
44
|
+
writeFileSync: mockWriteFileSync,
|
|
45
|
+
mkdirSync: mockMkdirSync,
|
|
46
|
+
rmSync: mockRmSync,
|
|
23
47
|
}));
|
|
24
48
|
// Mock logger
|
|
25
|
-
jest.
|
|
49
|
+
jest.unstable_mockModule("../utils/logger.js", () => ({
|
|
26
50
|
logger: {
|
|
27
51
|
debug: jest.fn(),
|
|
28
52
|
info: jest.fn(),
|
|
@@ -145,12 +169,9 @@ describe("buildContainerEnv", () => {
|
|
|
145
169
|
describe("detectSessionFiles", () => {
|
|
146
170
|
// Import after mocks are set up so the fs mock applies
|
|
147
171
|
let detectSessionFiles;
|
|
148
|
-
let mockReadFileSync;
|
|
149
172
|
beforeAll(async () => {
|
|
150
173
|
const mod = await import("./TestExecutionService.js");
|
|
151
174
|
detectSessionFiles = mod.detectSessionFiles;
|
|
152
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
153
|
-
mockReadFileSync = require("fs").readFileSync;
|
|
154
175
|
});
|
|
155
176
|
it("detects string-literal storageState (TS/JS)", () => {
|
|
156
177
|
mockReadFileSync.mockReturnValueOnce(`test.use({ storageState: '/abs/path/session.json' });`);
|
|
@@ -185,6 +206,81 @@ test('x', () => {});
|
|
|
185
206
|
expect(detectSessionFiles("/ws/spec.ts")).toEqual([]);
|
|
186
207
|
});
|
|
187
208
|
});
|
|
209
|
+
describe("isBrowserTest", () => {
|
|
210
|
+
let isBrowserTest;
|
|
211
|
+
beforeAll(async () => {
|
|
212
|
+
const mod = await import("./TestExecutionService.js");
|
|
213
|
+
isBrowserTest = mod.isBrowserTest;
|
|
214
|
+
});
|
|
215
|
+
it("returns true for UI test type", () => {
|
|
216
|
+
expect(isBrowserTest("ui")).toBe(true);
|
|
217
|
+
});
|
|
218
|
+
it("returns true for E2E test type", () => {
|
|
219
|
+
expect(isBrowserTest("e2e")).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
it("returns false for contract test type", () => {
|
|
222
|
+
expect(isBrowserTest("contract")).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
it("returns false for integration test type", () => {
|
|
225
|
+
expect(isBrowserTest("integration")).toBe(false);
|
|
226
|
+
});
|
|
227
|
+
it("returns false for fuzz test type", () => {
|
|
228
|
+
expect(isBrowserTest("fuzz")).toBe(false);
|
|
229
|
+
});
|
|
230
|
+
it("returns false for smoke test type", () => {
|
|
231
|
+
expect(isBrowserTest("smoke")).toBe(false);
|
|
232
|
+
});
|
|
233
|
+
it("returns false for load test type", () => {
|
|
234
|
+
expect(isBrowserTest("load")).toBe(false);
|
|
235
|
+
});
|
|
236
|
+
it("returns false for mock test type", () => {
|
|
237
|
+
expect(isBrowserTest("mock")).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
describe("getVideoSubdir", () => {
|
|
241
|
+
let getVideoSubdir;
|
|
242
|
+
beforeAll(async () => {
|
|
243
|
+
const mod = await import("./TestExecutionService.js");
|
|
244
|
+
getVideoSubdir = mod.getVideoSubdir;
|
|
245
|
+
});
|
|
246
|
+
it("generates deterministic subdirectory name with basename and hash", () => {
|
|
247
|
+
const testFile = "/workspace/tests/login.spec.ts";
|
|
248
|
+
const result = getVideoSubdir(testFile);
|
|
249
|
+
// Should be "basename-8hexchars" format
|
|
250
|
+
// Note: path.extname only strips the final extension (.ts), so .spec remains in basename
|
|
251
|
+
expect(result).toMatch(/^login\.spec-[0-9a-f]{8}$/);
|
|
252
|
+
});
|
|
253
|
+
it("strips file extension from basename", () => {
|
|
254
|
+
const result = getVideoSubdir("/workspace/checkout.spec.ts");
|
|
255
|
+
// path.extname('.spec.ts') returns '.ts', so 'checkout.spec' is the basename
|
|
256
|
+
expect(result).toMatch(/^checkout\.spec-[0-9a-f]{8}$/);
|
|
257
|
+
expect(result).toContain(".spec");
|
|
258
|
+
});
|
|
259
|
+
it("produces different hashes for different paths", () => {
|
|
260
|
+
const path1 = "/workspace/tests/login.spec.ts";
|
|
261
|
+
const path2 = "/workspace/tests/checkout.spec.ts";
|
|
262
|
+
const result1 = getVideoSubdir(path1);
|
|
263
|
+
const result2 = getVideoSubdir(path2);
|
|
264
|
+
expect(result1).not.toBe(result2);
|
|
265
|
+
// Different hashes
|
|
266
|
+
expect(result1.split("-")[1]).not.toBe(result2.split("-")[1]);
|
|
267
|
+
});
|
|
268
|
+
it("produces same hash for the same path (deterministic)", () => {
|
|
269
|
+
const testFile = "/workspace/tests/products.spec.ts";
|
|
270
|
+
const result1 = getVideoSubdir(testFile);
|
|
271
|
+
const result2 = getVideoSubdir(testFile);
|
|
272
|
+
expect(result1).toBe(result2);
|
|
273
|
+
});
|
|
274
|
+
it("handles paths with no extension", () => {
|
|
275
|
+
const result = getVideoSubdir("/workspace/test_file");
|
|
276
|
+
expect(result).toMatch(/^test_file-[0-9a-f]{8}$/);
|
|
277
|
+
});
|
|
278
|
+
it("handles paths with multiple dots", () => {
|
|
279
|
+
const result = getVideoSubdir("/workspace/test.spec.e2e.ts");
|
|
280
|
+
// Should strip only the last extension (.ts)
|
|
281
|
+
expect(result).toMatch(/^test\.spec\.e2e-[0-9a-f]{8}$/);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
188
284
|
describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
189
285
|
// Import after mocks are set up
|
|
190
286
|
let TestExecutionService;
|
|
@@ -258,9 +354,7 @@ describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
|
258
354
|
// resolve correctly inside the executor regardless of which path-shape the
|
|
259
355
|
// codegen happens to emit.
|
|
260
356
|
it("mirrors each workspace file mount at both /home/user/<f> and the host-absolute path", async () => {
|
|
261
|
-
|
|
262
|
-
const fs = require("fs");
|
|
263
|
-
fs.readdirSync.mockImplementation((_path, options) => {
|
|
357
|
+
mockReaddirSync.mockImplementation((_path, options) => {
|
|
264
358
|
if (options?.withFileTypes) {
|
|
265
359
|
return [
|
|
266
360
|
{ name: "xdr_dashboard.spec.ts", isFile: () => true, isDirectory: () => false },
|
|
@@ -288,9 +382,7 @@ describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
|
288
382
|
expect(targets).toContain("/Users/pedro/projects/cisco-xdr-tests/skyramp_session_storage.json");
|
|
289
383
|
});
|
|
290
384
|
it("does not double-mount when workspacePath equals /home/user", async () => {
|
|
291
|
-
|
|
292
|
-
const fs = require("fs");
|
|
293
|
-
fs.readdirSync.mockImplementation((_path, options) => {
|
|
385
|
+
mockReaddirSync.mockImplementation((_path, options) => {
|
|
294
386
|
if (options?.withFileTypes) {
|
|
295
387
|
return [{ name: "test_file.py", isFile: () => true, isDirectory: () => false }];
|
|
296
388
|
}
|
|
@@ -316,3 +408,225 @@ describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
|
316
408
|
}
|
|
317
409
|
});
|
|
318
410
|
});
|
|
411
|
+
describe("TestExecutionService.executeTest - Video capture for browser tests", () => {
|
|
412
|
+
let TestExecutionService;
|
|
413
|
+
let getVideoSubdir;
|
|
414
|
+
let EXECUTOR_DOCKER_IMAGE;
|
|
415
|
+
beforeAll(async () => {
|
|
416
|
+
const mod = await import("./TestExecutionService.js");
|
|
417
|
+
TestExecutionService = mod.TestExecutionService;
|
|
418
|
+
getVideoSubdir = mod.getVideoSubdir;
|
|
419
|
+
EXECUTOR_DOCKER_IMAGE = mod.EXECUTOR_DOCKER_IMAGE;
|
|
420
|
+
});
|
|
421
|
+
beforeEach(() => {
|
|
422
|
+
jest.clearAllMocks();
|
|
423
|
+
mockListImages.mockResolvedValue([{ RepoTags: [EXECUTOR_DOCKER_IMAGE] }]);
|
|
424
|
+
mockExistsSync.mockReturnValue(true);
|
|
425
|
+
mockReaddirSync.mockImplementation((_path, options) => {
|
|
426
|
+
if (options?.withFileTypes) {
|
|
427
|
+
return [
|
|
428
|
+
{ name: "test.spec.ts", isFile: () => true, isDirectory: () => false },
|
|
429
|
+
{ name: "test.py", isFile: () => true, isDirectory: () => false },
|
|
430
|
+
];
|
|
431
|
+
}
|
|
432
|
+
return ["test.spec.ts", "test.py"];
|
|
433
|
+
});
|
|
434
|
+
// Reset writeFileSync mock to default behavior
|
|
435
|
+
mockWriteFileSync.mockImplementation(() => { });
|
|
436
|
+
});
|
|
437
|
+
it("mounts generated Playwright config at /home/user/playwright.config.ts for TypeScript UI test", async () => {
|
|
438
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
439
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
440
|
+
const service = new TestExecutionService();
|
|
441
|
+
await service.executeTest({
|
|
442
|
+
testFile: "/workspace/login.spec.ts",
|
|
443
|
+
workspacePath: "/workspace",
|
|
444
|
+
language: "typescript",
|
|
445
|
+
testType: "ui",
|
|
446
|
+
});
|
|
447
|
+
const dockerOptions = mockRun.mock.calls[0][3];
|
|
448
|
+
const playwrightConfigMount = dockerOptions.HostConfig.Mounts.find((m) => m.Target === "/home/user/playwright.config.ts");
|
|
449
|
+
expect(playwrightConfigMount).toBeDefined();
|
|
450
|
+
expect(playwrightConfigMount.Type).toBe("bind");
|
|
451
|
+
// Source should be a temp file containing the generated config
|
|
452
|
+
expect(playwrightConfigMount.Source).toContain("skyramp-playwright-");
|
|
453
|
+
expect(playwrightConfigMount.Source).toContain(".config.ts");
|
|
454
|
+
});
|
|
455
|
+
it("generated Playwright config for TypeScript contains video:on and outputDir", async () => {
|
|
456
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
457
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
458
|
+
let capturedConfigContent = "";
|
|
459
|
+
mockWriteFileSync.mockImplementation((filePath, content) => {
|
|
460
|
+
if (filePath.includes("skyramp-playwright-") && filePath.endsWith(".config.ts")) {
|
|
461
|
+
capturedConfigContent = content;
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
const service = new TestExecutionService();
|
|
465
|
+
await service.executeTest({
|
|
466
|
+
testFile: "/workspace/checkout.spec.ts",
|
|
467
|
+
workspacePath: "/workspace",
|
|
468
|
+
language: "typescript",
|
|
469
|
+
testType: "e2e",
|
|
470
|
+
});
|
|
471
|
+
expect(capturedConfigContent).toContain('video: "on"');
|
|
472
|
+
expect(capturedConfigContent).toContain("outputDir:");
|
|
473
|
+
expect(capturedConfigContent).toContain(".skyramp/videos/");
|
|
474
|
+
});
|
|
475
|
+
it("mounts generated pytest.ini at /home/user/pytest.ini for Python UI test", async () => {
|
|
476
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
477
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
478
|
+
const service = new TestExecutionService();
|
|
479
|
+
await service.executeTest({
|
|
480
|
+
testFile: "/workspace/test_login.py",
|
|
481
|
+
workspacePath: "/workspace",
|
|
482
|
+
language: "python",
|
|
483
|
+
testType: "ui",
|
|
484
|
+
});
|
|
485
|
+
const dockerOptions = mockRun.mock.calls[0][3];
|
|
486
|
+
const pytestConfigMount = dockerOptions.HostConfig.Mounts.find((m) => m.Target === "/home/user/pytest.ini");
|
|
487
|
+
expect(pytestConfigMount).toBeDefined();
|
|
488
|
+
expect(pytestConfigMount.Type).toBe("bind");
|
|
489
|
+
expect(pytestConfigMount.Source).toContain("skyramp-pytest-");
|
|
490
|
+
expect(pytestConfigMount.Source).toContain(".ini");
|
|
491
|
+
});
|
|
492
|
+
it("generated pytest.ini for Python contains --video on and --output", async () => {
|
|
493
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
494
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
495
|
+
let capturedPytestContent = "";
|
|
496
|
+
mockWriteFileSync.mockImplementation((filePath, content) => {
|
|
497
|
+
if (filePath.includes("skyramp-pytest-") && filePath.endsWith(".ini")) {
|
|
498
|
+
capturedPytestContent = content;
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
const service = new TestExecutionService();
|
|
502
|
+
await service.executeTest({
|
|
503
|
+
testFile: "/workspace/test_checkout.py",
|
|
504
|
+
workspacePath: "/workspace",
|
|
505
|
+
language: "python",
|
|
506
|
+
testType: "e2e",
|
|
507
|
+
});
|
|
508
|
+
expect(capturedPytestContent).toContain("--video on");
|
|
509
|
+
expect(capturedPytestContent).toContain("--output");
|
|
510
|
+
expect(capturedPytestContent).toContain(".skyramp/videos/");
|
|
511
|
+
});
|
|
512
|
+
it("mounts video output directory as writable for UI test", async () => {
|
|
513
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
514
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
515
|
+
const service = new TestExecutionService();
|
|
516
|
+
await service.executeTest({
|
|
517
|
+
testFile: "/workspace/tests/login.spec.ts",
|
|
518
|
+
workspacePath: "/workspace",
|
|
519
|
+
language: "typescript",
|
|
520
|
+
testType: "ui",
|
|
521
|
+
});
|
|
522
|
+
const dockerOptions = mockRun.mock.calls[0][3];
|
|
523
|
+
const videoSubdir = getVideoSubdir("/workspace/tests/login.spec.ts");
|
|
524
|
+
const videoMount = dockerOptions.HostConfig.Mounts.find((m) => m.Target === `/home/user/.skyramp/videos/${videoSubdir}`);
|
|
525
|
+
expect(videoMount).toBeDefined();
|
|
526
|
+
expect(videoMount.Type).toBe("bind");
|
|
527
|
+
expect(videoMount.ReadOnly).toBe(false);
|
|
528
|
+
expect(videoMount.Source).toContain(".skyramp/videos/");
|
|
529
|
+
expect(videoMount.Source).toContain(videoSubdir);
|
|
530
|
+
});
|
|
531
|
+
it("does not mount video directory for non-browser tests", async () => {
|
|
532
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
533
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
534
|
+
const service = new TestExecutionService();
|
|
535
|
+
await service.executeTest({
|
|
536
|
+
testFile: "/workspace/contract_test.py",
|
|
537
|
+
workspacePath: "/workspace",
|
|
538
|
+
language: "python",
|
|
539
|
+
testType: "contract",
|
|
540
|
+
});
|
|
541
|
+
const dockerOptions = mockRun.mock.calls[0][3];
|
|
542
|
+
const videoMounts = dockerOptions.HostConfig.Mounts.filter((m) => m.Target.includes(".skyramp/videos"));
|
|
543
|
+
expect(videoMounts).toHaveLength(0);
|
|
544
|
+
});
|
|
545
|
+
it("uses minimal static Playwright config for non-browser TypeScript tests", async () => {
|
|
546
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
547
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
548
|
+
let usedGeneratedConfig = false;
|
|
549
|
+
mockWriteFileSync.mockImplementation((filePath, content) => {
|
|
550
|
+
if (filePath.includes("skyramp-playwright-") && content.includes('video: "on"')) {
|
|
551
|
+
usedGeneratedConfig = true;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
const service = new TestExecutionService();
|
|
555
|
+
await service.executeTest({
|
|
556
|
+
testFile: "/workspace/contract_test.spec.ts",
|
|
557
|
+
workspacePath: "/workspace",
|
|
558
|
+
language: "typescript",
|
|
559
|
+
testType: "contract",
|
|
560
|
+
});
|
|
561
|
+
// Should NOT generate a video-enabled config for contract test
|
|
562
|
+
expect(usedGeneratedConfig).toBe(false);
|
|
563
|
+
});
|
|
564
|
+
it("populates videoPath when video.webm exists after execution", async () => {
|
|
565
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
566
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
567
|
+
const videoSubdir = getVideoSubdir("/workspace/test.spec.ts");
|
|
568
|
+
mockReaddirSync.mockImplementation((dir, options) => {
|
|
569
|
+
// Mock video directory scan
|
|
570
|
+
if (dir.includes(".skyramp/videos") && dir.includes(videoSubdir)) {
|
|
571
|
+
if (options?.withFileTypes) {
|
|
572
|
+
return [{ name: "video.webm", isFile: () => true, isDirectory: () => false }];
|
|
573
|
+
}
|
|
574
|
+
return ["video.webm"];
|
|
575
|
+
}
|
|
576
|
+
// Default workspace files
|
|
577
|
+
if (options?.withFileTypes) {
|
|
578
|
+
return [{ name: "test.spec.ts", isFile: () => true, isDirectory: () => false }];
|
|
579
|
+
}
|
|
580
|
+
return ["test.spec.ts"];
|
|
581
|
+
});
|
|
582
|
+
const service = new TestExecutionService();
|
|
583
|
+
const result = await service.executeTest({
|
|
584
|
+
testFile: "/workspace/test.spec.ts",
|
|
585
|
+
workspacePath: "/workspace",
|
|
586
|
+
language: "typescript",
|
|
587
|
+
testType: "ui",
|
|
588
|
+
});
|
|
589
|
+
expect(result.videoPath).toBeDefined();
|
|
590
|
+
expect(result.videoPath).toContain(".skyramp/videos/");
|
|
591
|
+
expect(result.videoPath).toContain("video.webm");
|
|
592
|
+
});
|
|
593
|
+
it("leaves videoPath undefined when no video.webm found", async () => {
|
|
594
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
595
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
596
|
+
const videoSubdir = getVideoSubdir("/workspace/test.spec.ts");
|
|
597
|
+
mockReaddirSync.mockImplementation((dir, options) => {
|
|
598
|
+
// Mock empty video directory
|
|
599
|
+
if (dir.includes(".skyramp/videos") && dir.includes(videoSubdir)) {
|
|
600
|
+
if (options?.withFileTypes) {
|
|
601
|
+
return [];
|
|
602
|
+
}
|
|
603
|
+
return [];
|
|
604
|
+
}
|
|
605
|
+
// Default workspace files
|
|
606
|
+
if (options?.withFileTypes) {
|
|
607
|
+
return [{ name: "test.spec.ts", isFile: () => true, isDirectory: () => false }];
|
|
608
|
+
}
|
|
609
|
+
return ["test.spec.ts"];
|
|
610
|
+
});
|
|
611
|
+
const service = new TestExecutionService();
|
|
612
|
+
const result = await service.executeTest({
|
|
613
|
+
testFile: "/workspace/test.spec.ts",
|
|
614
|
+
workspacePath: "/workspace",
|
|
615
|
+
language: "typescript",
|
|
616
|
+
testType: "ui",
|
|
617
|
+
});
|
|
618
|
+
expect(result.videoPath).toBeUndefined();
|
|
619
|
+
});
|
|
620
|
+
it("leaves videoPath undefined for non-browser tests", async () => {
|
|
621
|
+
const mockContainer = { remove: jest.fn().mockResolvedValue(undefined) };
|
|
622
|
+
mockRun.mockResolvedValue([{ StatusCode: 0 }, mockContainer]);
|
|
623
|
+
const service = new TestExecutionService();
|
|
624
|
+
const result = await service.executeTest({
|
|
625
|
+
testFile: "/workspace/integration_test.py",
|
|
626
|
+
workspacePath: "/workspace",
|
|
627
|
+
language: "python",
|
|
628
|
+
testType: "integration",
|
|
629
|
+
});
|
|
630
|
+
expect(result.videoPath).toBeUndefined();
|
|
631
|
+
});
|
|
632
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { TestType } from "../types/TestTypes.js";
|
|
4
|
+
export interface BaseTestParams {
|
|
5
|
+
endpointURL?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
apiSchema?: string;
|
|
8
|
+
language?: string;
|
|
9
|
+
framework?: string;
|
|
10
|
+
output?: string;
|
|
11
|
+
outputDir: string;
|
|
12
|
+
force: boolean;
|
|
13
|
+
deployDashboard?: boolean;
|
|
14
|
+
runtime?: string;
|
|
15
|
+
dockerNetwork?: string;
|
|
16
|
+
dockerWorkerPort?: number;
|
|
17
|
+
k8sNamespace?: string;
|
|
18
|
+
k8sConfig?: string;
|
|
19
|
+
k8sContext?: string;
|
|
20
|
+
authHeader?: string;
|
|
21
|
+
authScheme?: string;
|
|
22
|
+
pathParams?: string;
|
|
23
|
+
queryParams?: string;
|
|
24
|
+
formParams?: string;
|
|
25
|
+
requestData?: string;
|
|
26
|
+
responseStatusCode?: string;
|
|
27
|
+
trace?: string;
|
|
28
|
+
include?: string[];
|
|
29
|
+
exclude?: string[];
|
|
30
|
+
insecure?: boolean;
|
|
31
|
+
prompt?: string;
|
|
32
|
+
codeReuse?: boolean;
|
|
33
|
+
modularizeCode?: boolean;
|
|
34
|
+
chainingKey?: string;
|
|
35
|
+
scenarioFile?: string;
|
|
36
|
+
mockPort?: number;
|
|
37
|
+
optionalFields?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare abstract class TestGenerationService {
|
|
40
|
+
protected client: SkyrampClient;
|
|
41
|
+
constructor();
|
|
42
|
+
generateTest(params: BaseTestParams & Record<string, any>): Promise<CallToolResult>;
|
|
43
|
+
protected validateInputs(params: BaseTestParams): CallToolResult;
|
|
44
|
+
protected abstract buildGenerationOptions(params: BaseTestParams & Record<string, any>): any;
|
|
45
|
+
protected abstract getTestType(): TestType;
|
|
46
|
+
protected handleApiAnalysis(params: BaseTestParams): Promise<CallToolResult | null>;
|
|
47
|
+
private static readonly STANDARD_HEADERS;
|
|
48
|
+
private static simpleWildcardMatch;
|
|
49
|
+
private static traceMatchesFilters;
|
|
50
|
+
protected extractAuthFromTrace(traceFilePath: string, include?: string[], exclude?: string[]): {
|
|
51
|
+
authHeader: string;
|
|
52
|
+
authScheme: string;
|
|
53
|
+
} | null;
|
|
54
|
+
protected executeGeneration(generateOptions: any): Promise<string>;
|
|
55
|
+
protected buildBaseGenerationOptions(params: BaseTestParams): any;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
jest.mock("@skyramp/skyramp", () => ({
|
|
4
|
-
SkyrampClient: jest.fn().mockImplementation(() => ({})),
|
|
5
|
-
}));
|
|
6
|
-
import { TestGenerationService } from "./TestGenerationService.js";
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
7
3
|
import { TestType } from "../types/TestTypes.js";
|
|
8
4
|
import { AUTH_PLACEHOLDER_TOKEN } from "../types/TestTypes.js";
|
|
9
5
|
import fs from "fs";
|
|
10
6
|
import os from "os";
|
|
11
7
|
import path from "path";
|
|
8
|
+
// Mock @skyramp/skyramp before importing TestGenerationService to avoid
|
|
9
|
+
// pulling in playwright (dynamic imports fail on Node 18 in CI). Under native
|
|
10
|
+
// ESM, jest.mock is not hoisted — use unstable_mockModule + dynamic import.
|
|
11
|
+
jest.unstable_mockModule("@skyramp/skyramp", () => ({
|
|
12
|
+
SkyrampClient: jest.fn().mockImplementation(() => ({})),
|
|
13
|
+
}));
|
|
14
|
+
const { TestGenerationService, BaseTestParams } = await import("./TestGenerationService.js");
|
|
15
|
+
const { SkyrampClient } = await import("@skyramp/skyramp");
|
|
12
16
|
class StubService extends TestGenerationService {
|
|
13
17
|
buildGenerationOptions() {
|
|
14
18
|
return {};
|
|
@@ -87,7 +91,6 @@ describe("TestGenerationService — authType/authScheme not passed to library",
|
|
|
87
91
|
let mockGenerateRestTest;
|
|
88
92
|
beforeEach(() => {
|
|
89
93
|
mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
|
|
90
|
-
const { SkyrampClient } = require("@skyramp/skyramp");
|
|
91
94
|
SkyrampClient.mockImplementation(() => ({
|
|
92
95
|
generateRestTest: mockGenerateRestTest,
|
|
93
96
|
}));
|
|
@@ -333,7 +336,6 @@ describe("TestGenerationService — trace-based auth in executeGeneration", () =
|
|
|
333
336
|
let tmpDir;
|
|
334
337
|
beforeEach(() => {
|
|
335
338
|
mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
|
|
336
|
-
const { SkyrampClient } = require("@skyramp/skyramp");
|
|
337
339
|
SkyrampClient.mockImplementation(() => ({
|
|
338
340
|
generateRestTest: mockGenerateRestTest,
|
|
339
341
|
}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TestExecutionOptions } from "../types/TestExecution.js";
|
|
2
|
+
/**
|
|
3
|
+
* Rewrite localhost / 127.0.0.1 URLs to host.docker.internal so the Docker
|
|
4
|
+
* executor container can reach services running on the host machine.
|
|
5
|
+
*
|
|
6
|
+
* Only applied when NOT using host networking (bridge mode), because in bridge
|
|
7
|
+
* mode the container's localhost is its own loopback, not the host's.
|
|
8
|
+
* host.docker.internal is mapped via ExtraHosts in TestExecutionService.
|
|
9
|
+
*/
|
|
10
|
+
export declare function rewriteLocalhostForDocker(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Build the environment variable array for the Docker executor container.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildContainerEnv(options: Pick<TestExecutionOptions, "token" | "language" | "useHostNetwork">, saveStoragePath?: string, hostEnv?: Record<string, string | undefined>): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { TOOL_PHASE_MAP, TOOLS_WITHOUT_PHASE } from "./tool-phases.js";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
4
6
|
function findAllToolNames() {
|
|
5
7
|
const toolNames = [];
|
|
6
8
|
function walk(dir) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical mapping of Skyramp MCP tool names to testbot progress phases.
|
|
3
|
+
*
|
|
4
|
+
* The testbot progress UI reads this map at runtime to know which tool calls
|
|
5
|
+
* correspond to which progress steps. When adding or renaming tools, update
|
|
6
|
+
* this map so the progress UI stays accurate.
|
|
7
|
+
*
|
|
8
|
+
* Tools not in this map must be listed in TOOLS_WITHOUT_PHASE.
|
|
9
|
+
*
|
|
10
|
+
* Phases: analyzing, generating, executing, maintaining, reporting
|
|
11
|
+
*
|
|
12
|
+
* ## Static vs context-dependent mappings
|
|
13
|
+
*
|
|
14
|
+
* - **Static** (`string`): the tool always maps to this phase.
|
|
15
|
+
* - **Context-dependent** (`{ before, after }`): the phase depends on whether
|
|
16
|
+
* the "generating" boundary has been crossed. The consumer tracks a boolean
|
|
17
|
+
* flag (`generationSeen`), initially `false`. When any tool in
|
|
18
|
+
* `GENERATING_TOOLS` is encountered, set `generationSeen = true`.
|
|
19
|
+
* - While `generationSeen` is `false`, resolve to the `before` phase.
|
|
20
|
+
* - Once `generationSeen` is `true`, resolve to the `after` phase.
|
|
21
|
+
*
|
|
22
|
+
* Example: `skyramp_execute_test` maps to `{ before: "maintaining", after: "executing" }`.
|
|
23
|
+
* Before any generation tool is seen, execution calls are part of
|
|
24
|
+
* maintenance (baseline runs). After generation, they are final test execution.
|
|
25
|
+
*
|
|
26
|
+
* Reset `generationSeen` to `false` at the start of each session/run.
|
|
27
|
+
*/
|
|
28
|
+
export type PhaseMapping = string | {
|
|
29
|
+
before: string;
|
|
30
|
+
after: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const TOOL_PHASE_MAP: Record<string, PhaseMapping>;
|
|
33
|
+
/** Tools whose phase depends on context — listed here for consumer discovery. */
|
|
34
|
+
export declare const CONTEXT_DEPENDENT_TOOLS: Set<string>;
|
|
35
|
+
/** All tools that belong to the "generating" phase — used as the boundary. */
|
|
36
|
+
export declare const GENERATING_TOOLS: Set<string>;
|
|
37
|
+
/** Tools that intentionally have no progress phase (infrastructure/utility). */
|
|
38
|
+
export declare const TOOLS_WITHOUT_PHASE: Set<string>;
|