@skyramp/mcp 0.3.2-rc.pom-3 → 0.3.2
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 +1 -0
- package/build/commands/commandLibrary.js +19 -13
- package/build/commands/localDevTestChangesCommand.d.ts +15 -0
- package/build/commands/localDevTestChangesCommand.js +201 -0
- package/build/index.js +80 -6
- package/build/prompts/code-reuse.js +3 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
- package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
- package/build/prompts/local-dev/local-dev-plan.js +429 -0
- package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
- package/build/prompts/local-dev/local-dev-prompts.js +190 -0
- package/build/prompts/pom-aware-code-reuse.js +12 -0
- package/build/prompts/prompt-utils.d.ts +8 -0
- package/build/prompts/prompt-utils.js +33 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
- package/build/prompts/sut-setup/shared.js +16 -12
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
- package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
- package/build/prompts/testbot/testbot-prompts.js +32 -52
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +2 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +2 -1
- package/build/services/TestExecutionService.js +8 -3
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +3 -1
- package/build/tool-phases.js +6 -0
- package/build/tools/code-refactor/codeReuseTool.js +43 -4
- package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
- package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
- package/build/tools/code-refactor/reuse-outcome.js +158 -0
- package/build/tools/code-refactor/reuse-state.d.ts +45 -0
- package/build/tools/code-refactor/reuse-state.js +140 -0
- package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
- package/build/tools/enrichTestWithMocksTool.js +726 -0
- package/build/tools/executeSkyrampTestTool.d.ts +11 -0
- package/build/tools/executeSkyrampTestTool.js +62 -21
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
- package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
- package/build/tools/generate-tests/generateContractRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
- package/build/tools/generate-tests/generateMockRestTool.js +391 -22
- package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
- package/build/tools/generate-tests/planGuard.js +2 -22
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
- package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
- package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
- package/build/tools/localDevWorkerComposeTool.js +264 -0
- package/build/tools/one-click/oneClickTool.d.ts +13 -0
- package/build/tools/one-click/oneClickTool.js +195 -24
- package/build/tools/preflightMockCheckTool.d.ts +2 -0
- package/build/tools/preflightMockCheckTool.js +96 -0
- package/build/tools/queryProxyMocksTool.d.ts +70 -0
- package/build/tools/queryProxyMocksTool.js +522 -0
- package/build/tools/runExistingTestsTool.d.ts +31 -0
- package/build/tools/runExistingTestsTool.js +214 -13
- package/build/tools/submitReportTool.js +38 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/FrontendIntegration.d.ts +3 -0
- package/build/types/FrontendIntegration.js +3 -0
- package/build/types/OneClickCommands.d.ts +1 -1
- package/build/types/Recommendation.d.ts +20 -0
- package/build/types/Recommendation.js +32 -6
- package/build/types/RepositoryAnalysis.d.ts +131 -14
- package/build/types/RepositoryAnalysis.js +16 -2
- package/build/types/ReuseOutcome.d.ts +63 -0
- package/build/types/ReuseOutcome.js +33 -0
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +22 -6
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +26 -0
- package/build/utils/AnalysisStateManager.js +31 -1
- package/build/utils/analyze-openapi.js +18 -1
- package/build/utils/branchDiff.d.ts +17 -1
- package/build/utils/branchDiff.js +99 -14
- package/build/utils/featureFlags.d.ts +31 -0
- package/build/utils/featureFlags.js +37 -0
- package/build/utils/frontendIntegration.js +8 -1
- package/build/utils/grpcMockValidation.d.ts +1 -0
- package/build/utils/grpcMockValidation.js +49 -0
- package/build/utils/httpMethodValidation.d.ts +4 -0
- package/build/utils/httpMethodValidation.js +15 -0
- package/build/utils/logger.js +1 -1
- package/build/utils/mockCompatibility.d.ts +49 -0
- package/build/utils/mockCompatibility.js +82 -0
- package/build/utils/pom-scope/pom-files.js +7 -0
- package/build/utils/pom-verify/bindings.js +11 -1
- package/build/utils/pom-verify/re-exports.d.ts +10 -0
- package/build/utils/pom-verify/re-exports.js +61 -0
- package/build/utils/pom-verify/resolve.d.ts +4 -1
- package/build/utils/pom-verify/resolve.js +7 -4
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +25 -3
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/routeParsers.d.ts +3 -9
- package/build/utils/routeParsers.js +79 -4
- package/build/utils/utils.js +2 -2
- package/build/utils/versions.d.ts +4 -3
- package/build/utils/versions.js +3 -1
- package/build/utils/workspaceAuth.d.ts +46 -0
- package/build/utils/workspaceAuth.js +156 -1
- package/build/workspace/testSuites.d.ts +2 -1
- package/build/workspace/testSuites.js +1 -1
- package/build/workspace/workspace.d.ts +108 -32
- package/build/workspace/workspace.js +32 -4
- package/package.json +5 -2
- package/build/adapters/jestAdapter.test.d.ts +0 -1
- package/build/adapters/jestAdapter.test.js +0 -93
- package/build/adapters/mochaAdapter.test.d.ts +0 -1
- package/build/adapters/mochaAdapter.test.js +0 -63
- package/build/adapters/playwrightAdapter.test.d.ts +0 -1
- package/build/adapters/playwrightAdapter.test.js +0 -169
- package/build/adapters/pytestAdapter.test.d.ts +0 -1
- package/build/adapters/pytestAdapter.test.js +0 -90
- package/build/prompts/code-reuse.test.d.ts +0 -1
- package/build/prompts/code-reuse.test.js +0 -62
- package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
- package/build/prompts/pom-aware-code-reuse.test.js +0 -11
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
- package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
- package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
- package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
- package/build/prompts/testbot/testbot-prompts.test.js +0 -451
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
- package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
- package/build/recommendation/discriminators.test.d.ts +0 -1
- package/build/recommendation/discriminators.test.js +0 -324
- package/build/recommendation/diversity.test.d.ts +0 -1
- package/build/recommendation/diversity.test.js +0 -77
- package/build/recommendation/planRanker.test.d.ts +0 -1
- package/build/recommendation/planRanker.test.js +0 -110
- package/build/resources/testbotResource.test.d.ts +0 -1
- package/build/resources/testbotResource.test.js +0 -44
- package/build/services/AnalyticsService.test.d.ts +0 -1
- package/build/services/AnalyticsService.test.js +0 -86
- package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.integration.test.js +0 -162
- package/build/services/ScenarioGenerationService.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.test.js +0 -414
- package/build/services/TestDiscoveryService.test.d.ts +0 -1
- package/build/services/TestDiscoveryService.test.js +0 -983
- package/build/services/TestExecutionService.test.d.ts +0 -1
- package/build/services/TestExecutionService.test.js +0 -1032
- package/build/services/TestGenerationService.test.d.ts +0 -1
- package/build/services/TestGenerationService.test.js +0 -578
- package/build/tool-phase-coverage.test.d.ts +0 -1
- package/build/tool-phase-coverage.test.js +0 -49
- package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
- package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
- package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
- package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
- package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
- package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
- package/build/tools/generate-tests/planGuard.test.js +0 -185
- package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
- package/build/tools/generate-tests/scenarioLint.test.js +0 -100
- package/build/tools/runExistingTestsTool.test.d.ts +0 -1
- package/build/tools/runExistingTestsTool.test.js +0 -379
- package/build/tools/submitReportTool.test.d.ts +0 -1
- package/build/tools/submitReportTool.test.js +0 -1428
- package/build/tools/test-management/actionsTool.test.d.ts +0 -1
- package/build/tools/test-management/actionsTool.test.js +0 -436
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
- package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
- package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
- package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
- package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
- package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
- package/build/tools/trace/resolveSessionPaths.test.js +0 -104
- package/build/tools/trace/sessionState.test.d.ts +0 -1
- package/build/tools/trace/sessionState.test.js +0 -17
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
- package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
- package/build/tools/workspace/serviceUpsert.test.js +0 -50
- package/build/utils/AnalysisStateManager.test.d.ts +0 -1
- package/build/utils/AnalysisStateManager.test.js +0 -134
- package/build/utils/dartRouteExtractor.test.d.ts +0 -1
- package/build/utils/dartRouteExtractor.test.js +0 -307
- package/build/utils/docker.test.d.ts +0 -1
- package/build/utils/docker.test.js +0 -114
- package/build/utils/featureFlags.test.d.ts +0 -1
- package/build/utils/featureFlags.test.js +0 -81
- package/build/utils/fileWalk.test.d.ts +0 -1
- package/build/utils/fileWalk.test.js +0 -252
- package/build/utils/frontendIntegration.test.d.ts +0 -1
- package/build/utils/frontendIntegration.test.js +0 -229
- package/build/utils/frontendSelectors.test.d.ts +0 -1
- package/build/utils/frontendSelectors.test.js +0 -118
- package/build/utils/gitStaging.test.d.ts +0 -1
- package/build/utils/gitStaging.test.js +0 -111
- package/build/utils/httpDefaults.test.d.ts +0 -1
- package/build/utils/httpDefaults.test.js +0 -21
- package/build/utils/importerHop.test.d.ts +0 -1
- package/build/utils/importerHop.test.js +0 -469
- package/build/utils/pathAffinityClassification.test.d.ts +0 -1
- package/build/utils/pathAffinityClassification.test.js +0 -208
- package/build/utils/planMatchKeys.test.d.ts +0 -1
- package/build/utils/planMatchKeys.test.js +0 -123
- package/build/utils/pom-scope/index.test.d.ts +0 -1
- package/build/utils/pom-scope/index.test.js +0 -278
- package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
- package/build/utils/pom-scope/pom-files.test.js +0 -29
- package/build/utils/pom-scope/scoring.test.d.ts +0 -1
- package/build/utils/pom-scope/scoring.test.js +0 -39
- package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
- package/build/utils/pom-scope/selector-extractor.test.js +0 -67
- package/build/utils/pom-verify/bindings.test.d.ts +0 -1
- package/build/utils/pom-verify/bindings.test.js +0 -164
- package/build/utils/pom-verify/calls.test.d.ts +0 -1
- package/build/utils/pom-verify/calls.test.js +0 -61
- package/build/utils/pom-verify/resolve.test.d.ts +0 -1
- package/build/utils/pom-verify/resolve.test.js +0 -114
- package/build/utils/pom-verify/verify.test.d.ts +0 -1
- package/build/utils/pom-verify/verify.test.js +0 -374
- package/build/utils/pr-comment-parser.test.d.ts +0 -1
- package/build/utils/pr-comment-parser.test.js +0 -428
- package/build/utils/progress.test.d.ts +0 -1
- package/build/utils/progress.test.js +0 -37
- package/build/utils/projectMetadata.test.d.ts +0 -1
- package/build/utils/projectMetadata.test.js +0 -172
- package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
- package/build/utils/pythonMountPrefixes.test.js +0 -113
- package/build/utils/repoScanner.test.d.ts +0 -1
- package/build/utils/repoScanner.test.js +0 -190
- package/build/utils/reportVerification.test.d.ts +0 -1
- package/build/utils/reportVerification.test.js +0 -185
- package/build/utils/routeParsers.test.d.ts +0 -1
- package/build/utils/routeParsers.test.js +0 -1011
- package/build/utils/scenarioDrafting.test.d.ts +0 -1
- package/build/utils/scenarioDrafting.test.js +0 -876
- package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
- package/build/utils/sourceRouteExtractor.test.js +0 -738
- package/build/utils/telemetry.test.d.ts +0 -1
- package/build/utils/telemetry.test.js +0 -70
- package/build/utils/trace-parser.test.d.ts +0 -6
- package/build/utils/trace-parser.test.js +0 -140
- package/build/utils/uiPageEnumerator.test.d.ts +0 -1
- package/build/utils/uiPageEnumerator.test.js +0 -824
- package/build/utils/utils.test.d.ts +0 -1
- package/build/utils/utils.test.js +0 -103
- package/build/utils/walkerCharacterization.test.d.ts +0 -1
- package/build/utils/walkerCharacterization.test.js +0 -233
- package/build/utils/workspaceAuth.test.d.ts +0 -1
- package/build/utils/workspaceAuth.test.js +0 -260
- package/build/workspace/testSuites.test.d.ts +0 -1
- package/build/workspace/testSuites.test.js +0 -23
- package/build/workspace/workspace.test.d.ts +0 -1
- package/build/workspace/workspace.test.js +0 -264
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
-
import { jest, describe, it, expect, beforeEach } from "@jest/globals";
|
|
3
|
-
jest.unstable_mockModule("@modelcontextprotocol/sdk/server/mcp.js", () => ({
|
|
4
|
-
McpServer: jest.fn(),
|
|
5
|
-
}));
|
|
6
|
-
jest.unstable_mockModule("@modelcontextprotocol/sdk/types.js", () => ({
|
|
7
|
-
CallToolResult: {},
|
|
8
|
-
}));
|
|
9
|
-
jest.unstable_mockModule("../../utils/logger.js", () => ({
|
|
10
|
-
logger: {
|
|
11
|
-
info: jest.fn(),
|
|
12
|
-
debug: jest.fn(),
|
|
13
|
-
error: jest.fn(),
|
|
14
|
-
warning: jest.fn(),
|
|
15
|
-
},
|
|
16
|
-
}));
|
|
17
|
-
jest.unstable_mockModule("../../services/AnalyticsService.js", () => ({
|
|
18
|
-
AnalyticsService: { pushMCPToolEvent: jest.fn().mockResolvedValue(undefined) },
|
|
19
|
-
}));
|
|
20
|
-
const mockBuildDriftAnalysisPrompt = jest.fn().mockImplementation((_stateFile, apiTests, ui) => {
|
|
21
|
-
const parts = [];
|
|
22
|
-
if ((apiTests?.length ?? 0) > 0 || !ui)
|
|
23
|
-
parts.push("<drift_analysis_rules>API drift</drift_analysis_rules>");
|
|
24
|
-
if (ui)
|
|
25
|
-
parts.push("<ui_drift_analysis_rules>UI drift</ui_drift_analysis_rules>");
|
|
26
|
-
return parts.join("\n\n");
|
|
27
|
-
});
|
|
28
|
-
jest.unstable_mockModule("../../prompts/test-maintenance/drift-analysis-prompt.js", () => ({
|
|
29
|
-
buildDriftAnalysisPrompt: mockBuildDriftAnalysisPrompt,
|
|
30
|
-
}));
|
|
31
|
-
const mockFromStatePath = jest.fn();
|
|
32
|
-
const mockCleanupOldFiles = jest.fn().mockImplementation(() => Promise.resolve());
|
|
33
|
-
jest.unstable_mockModule("../../utils/AnalysisStateManager.js", () => ({
|
|
34
|
-
StateManager: {
|
|
35
|
-
fromStatePath: mockFromStatePath,
|
|
36
|
-
cleanupOldFiles: mockCleanupOldFiles,
|
|
37
|
-
},
|
|
38
|
-
TestSource: { Skyramp: "skyramp", External: "external" },
|
|
39
|
-
}));
|
|
40
|
-
jest.unstable_mockModule("../../utils/utils.js", () => ({
|
|
41
|
-
toolError: (msg) => ({ content: [{ type: "text", text: `Error: ${msg}` }] }),
|
|
42
|
-
}));
|
|
43
|
-
// Confirm-gate dep: the workspace read decides whether the repo has a runnable
|
|
44
|
-
// external-test suite (a Playwright service with a runtimeDetails.testSuites entry).
|
|
45
|
-
// Default to "no services" so tests that don't opt in keep today's behaviour
|
|
46
|
-
// (gate never fires).
|
|
47
|
-
const mockWsRead = jest.fn(() => Promise.resolve({ services: [] }));
|
|
48
|
-
jest.unstable_mockModule("../../workspace/workspace.js", () => ({
|
|
49
|
-
WorkspaceConfigManager: jest.fn().mockImplementation(() => ({ read: mockWsRead })),
|
|
50
|
-
}));
|
|
51
|
-
const { registerAnalyzeTestHealthTool } = await import("./analyzeTestHealthTool.js");
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Helpers
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
function makeFakeServer() {
|
|
56
|
-
let capturedHandler = null;
|
|
57
|
-
let capturedSchema = null;
|
|
58
|
-
const server = {
|
|
59
|
-
registerTool: jest.fn((_name, config, handler) => {
|
|
60
|
-
capturedSchema = config.inputSchema;
|
|
61
|
-
capturedHandler = handler;
|
|
62
|
-
}),
|
|
63
|
-
getHandler: () => capturedHandler,
|
|
64
|
-
getSchema: () => capturedSchema,
|
|
65
|
-
};
|
|
66
|
-
return server;
|
|
67
|
-
}
|
|
68
|
-
function makeStateManager(stateData) {
|
|
69
|
-
return {
|
|
70
|
-
getStatePath: jest.fn().mockReturnValue("/tmp/skyramp-analysis-test.json"),
|
|
71
|
-
readData: jest.fn().mockResolvedValue(stateData),
|
|
72
|
-
readFullState: jest.fn().mockResolvedValue({ metadata: { repositoryPath: "/repo" } }),
|
|
73
|
-
// Multi-repo API added in SKYR-3786 — analyzeTestHealthTool now uses these.
|
|
74
|
-
readRepoData: jest.fn().mockResolvedValue(stateData),
|
|
75
|
-
getRepoRepositoryPath: jest.fn().mockResolvedValue("/repo"),
|
|
76
|
-
listRelatedRepos: jest.fn().mockResolvedValue([]),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
|
-
// Tests
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
|
-
describe("analyzeTestHealthTool — blueprintCaptured schema", () => {
|
|
83
|
-
it("registers blueprintCaptured as an optional boolean parameter", () => {
|
|
84
|
-
const server = makeFakeServer();
|
|
85
|
-
registerAnalyzeTestHealthTool(server);
|
|
86
|
-
const schema = server.getSchema();
|
|
87
|
-
expect(schema).toHaveProperty("blueprintCaptured");
|
|
88
|
-
expect(schema.blueprintCaptured.safeParse(undefined).success).toBe(true);
|
|
89
|
-
expect(schema.blueprintCaptured.safeParse(true).success).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
describe("analyzeTestHealthTool — UI drift gate logic", () => {
|
|
93
|
-
let server;
|
|
94
|
-
beforeEach(() => {
|
|
95
|
-
jest.clearAllMocks();
|
|
96
|
-
server = makeFakeServer();
|
|
97
|
-
registerAnalyzeTestHealthTool(server);
|
|
98
|
-
});
|
|
99
|
-
it("includes UI drift when uiContext has changedFrontendFiles and a UI test", async () => {
|
|
100
|
-
const mockStateManager = makeStateManager({
|
|
101
|
-
existingTests: [
|
|
102
|
-
{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" },
|
|
103
|
-
],
|
|
104
|
-
uiContext: {
|
|
105
|
-
changedFrontendFiles: ["/repo/src/components/Cart.tsx"],
|
|
106
|
-
candidateUiPages: [],
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
110
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
111
|
-
expect(result).not.toHaveProperty("isError", true);
|
|
112
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeDefined();
|
|
113
|
-
const testsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][2].tests;
|
|
114
|
-
expect(testsArg).toContainEqual(expect.objectContaining({ testFile: "/repo/tests/cart.spec.ts" }));
|
|
115
|
-
});
|
|
116
|
-
it("passes blueprintCaptured=true to buildUiDriftAnalysisPrompt", async () => {
|
|
117
|
-
const mockStateManager = makeStateManager({
|
|
118
|
-
existingTests: [{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" }],
|
|
119
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
120
|
-
});
|
|
121
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
122
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
123
|
-
const blueprintArg = mockBuildDriftAnalysisPrompt.mock.calls[0][2].blueprintCaptured;
|
|
124
|
-
expect(blueprintArg).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
it("passes blueprintCaptured=false to buildUiDriftAnalysisPrompt", async () => {
|
|
127
|
-
const mockStateManager = makeStateManager({
|
|
128
|
-
existingTests: [{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" }],
|
|
129
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
130
|
-
});
|
|
131
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
132
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: false });
|
|
133
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeDefined();
|
|
134
|
-
const blueprintArg = mockBuildDriftAnalysisPrompt.mock.calls[0][2].blueprintCaptured;
|
|
135
|
-
expect(blueprintArg).toBe(false);
|
|
136
|
-
});
|
|
137
|
-
it("excludes UI drift when uiContext is absent", async () => {
|
|
138
|
-
const mockStateManager = makeStateManager({ existingTests: [] });
|
|
139
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
140
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
141
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeUndefined();
|
|
142
|
-
});
|
|
143
|
-
it("excludes UI drift when changedFrontendFiles is empty", async () => {
|
|
144
|
-
const mockStateManager = makeStateManager({
|
|
145
|
-
existingTests: [{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui" }],
|
|
146
|
-
uiContext: { changedFrontendFiles: [], candidateUiPages: [] },
|
|
147
|
-
});
|
|
148
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
149
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
150
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeUndefined();
|
|
151
|
-
});
|
|
152
|
-
it("includes UI drift (empty test list) when frontend changed but no UI tests found — grep pre-scan will discover them", async () => {
|
|
153
|
-
const mockStateManager = makeStateManager({
|
|
154
|
-
existingTests: [
|
|
155
|
-
{ testFile: "/repo/tests/products_contract_test.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
156
|
-
{ testFile: "/repo/tests/orders_smoke_test.py", source: "skyramp", testType: "smoke", framework: "pytest" },
|
|
157
|
-
],
|
|
158
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
159
|
-
});
|
|
160
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
161
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
162
|
-
// UI drift fires even with 0 UI tests — grep pre-scan discovers component tests dynamically
|
|
163
|
-
const uiParam = mockBuildDriftAnalysisPrompt.mock.calls[0][2];
|
|
164
|
-
expect(uiParam).toBeDefined();
|
|
165
|
-
expect(uiParam.tests).toHaveLength(0);
|
|
166
|
-
expect(uiParam.changedFrontendFiles).toEqual(["/repo/src/Cart.tsx"]);
|
|
167
|
-
});
|
|
168
|
-
it("includes UI drift for RTL tests (framework=rtl, testType=unknown)", async () => {
|
|
169
|
-
const mockStateManager = makeStateManager({
|
|
170
|
-
existingTests: [
|
|
171
|
-
{ testFile: "/repo/src/components/Cart.test.tsx", source: "external", testType: "unknown", framework: "rtl" },
|
|
172
|
-
{ testFile: "/repo/tests/orders_smoke_test.py", source: "skyramp", testType: "smoke", framework: "pytest" },
|
|
173
|
-
],
|
|
174
|
-
repositoryAnalysis: { relevantExternalTestPaths: ["src/components/Cart.test.tsx"] },
|
|
175
|
-
uiContext: { changedFrontendFiles: ["/repo/src/components/Cart.tsx"], candidateUiPages: [] },
|
|
176
|
-
});
|
|
177
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
178
|
-
mockFromStatePath.mock.results[0]?.value?.readFullState?.mockResolvedValue({
|
|
179
|
-
metadata: { repositoryPath: "/repo" },
|
|
180
|
-
});
|
|
181
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: false });
|
|
182
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeDefined();
|
|
183
|
-
const testsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][2].tests;
|
|
184
|
-
expect(testsArg).toHaveLength(1);
|
|
185
|
-
expect(testsArg[0]).toMatchObject({ testFile: "/repo/src/components/Cart.test.tsx" });
|
|
186
|
-
});
|
|
187
|
-
it("excludes RTL test from API drift prompt when UI drift is running", async () => {
|
|
188
|
-
const mockStateManager = makeStateManager({
|
|
189
|
-
existingTests: [
|
|
190
|
-
{ testFile: "/repo/src/components/Cart.test.tsx", source: "external", testType: "unknown", framework: "rtl" },
|
|
191
|
-
{ testFile: "/repo/tests/orders_smoke_test.py", source: "skyramp", testType: "smoke", framework: "pytest" },
|
|
192
|
-
],
|
|
193
|
-
repositoryAnalysis: { relevantExternalTestPaths: ["src/components/Cart.test.tsx"] },
|
|
194
|
-
uiContext: { changedFrontendFiles: ["/repo/src/components/Cart.tsx"], candidateUiPages: [] },
|
|
195
|
-
});
|
|
196
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
197
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: false });
|
|
198
|
-
const apiTestsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][1];
|
|
199
|
-
expect(apiTestsArg).toHaveLength(1);
|
|
200
|
-
expect(apiTestsArg[0]).toMatchObject({ testFile: "/repo/tests/orders_smoke_test.py" });
|
|
201
|
-
});
|
|
202
|
-
it("passes only UI tests to buildUiDriftAnalysisPrompt when mixed test types exist", async () => {
|
|
203
|
-
const mockStateManager = makeStateManager({
|
|
204
|
-
existingTests: [
|
|
205
|
-
{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" },
|
|
206
|
-
{ testFile: "/repo/tests/products_contract.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
207
|
-
{ testFile: "/repo/tests/smoke.py", source: "skyramp", testType: "smoke", framework: "pytest" },
|
|
208
|
-
],
|
|
209
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
210
|
-
});
|
|
211
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
212
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
213
|
-
expect(mockBuildDriftAnalysisPrompt.mock.calls[0][2]).toBeDefined();
|
|
214
|
-
const testsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][2].tests;
|
|
215
|
-
expect(testsArg).toHaveLength(1);
|
|
216
|
-
expect(testsArg[0]).toMatchObject({ testFile: "/repo/tests/cart.spec.ts" });
|
|
217
|
-
});
|
|
218
|
-
it("excludes UI tests from API drift prompt when UI drift is also running", async () => {
|
|
219
|
-
const mockStateManager = makeStateManager({
|
|
220
|
-
existingTests: [
|
|
221
|
-
{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" },
|
|
222
|
-
{ testFile: "/repo/tests/products_contract.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
223
|
-
],
|
|
224
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
225
|
-
});
|
|
226
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
227
|
-
await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
228
|
-
const apiTestsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][1];
|
|
229
|
-
expect(apiTestsArg).toHaveLength(1);
|
|
230
|
-
expect(apiTestsArg[0]).toMatchObject({ testFile: "/repo/tests/products_contract.py" });
|
|
231
|
-
});
|
|
232
|
-
it("includes UI tests in API drift prompt when no frontend changes", async () => {
|
|
233
|
-
const mockStateManager = makeStateManager({
|
|
234
|
-
existingTests: [
|
|
235
|
-
{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" },
|
|
236
|
-
{ testFile: "/repo/tests/products_contract.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
237
|
-
],
|
|
238
|
-
});
|
|
239
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
240
|
-
await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
241
|
-
// No frontend changes → no UI drift section → UI tests fall through to API drift
|
|
242
|
-
// so they are not silently dropped on API-only PRs.
|
|
243
|
-
const apiTestsArg = mockBuildDriftAnalysisPrompt.mock.calls[0][1];
|
|
244
|
-
expect(apiTestsArg).toHaveLength(2);
|
|
245
|
-
expect(apiTestsArg).toContainEqual(expect.objectContaining({ testFile: "/repo/tests/cart.spec.ts" }));
|
|
246
|
-
expect(apiTestsArg).toContainEqual(expect.objectContaining({ testFile: "/repo/tests/products_contract.py" }));
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
describe("analyzeTestHealthTool — prompt concatenation", () => {
|
|
250
|
-
let server;
|
|
251
|
-
beforeEach(() => {
|
|
252
|
-
jest.clearAllMocks();
|
|
253
|
-
server = makeFakeServer();
|
|
254
|
-
registerAnalyzeTestHealthTool(server);
|
|
255
|
-
});
|
|
256
|
-
it("concatenates API and UI drift prompts when both are included", async () => {
|
|
257
|
-
const mockStateManager = makeStateManager({
|
|
258
|
-
existingTests: [
|
|
259
|
-
{ testFile: "/repo/tests/cart.spec.ts", source: "skyramp", testType: "ui", framework: "playwright-ui" },
|
|
260
|
-
{ testFile: "/repo/tests/contract.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
261
|
-
],
|
|
262
|
-
uiContext: { changedFrontendFiles: ["/repo/src/Cart.tsx"], candidateUiPages: [] },
|
|
263
|
-
});
|
|
264
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
265
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json", blueprintCaptured: true });
|
|
266
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
267
|
-
expect(result.structuredContent?.prompt).toContain("UI drift");
|
|
268
|
-
});
|
|
269
|
-
it("returns only API drift prompt when uiContext is absent", async () => {
|
|
270
|
-
const mockStateManager = makeStateManager({ existingTests: [] });
|
|
271
|
-
mockFromStatePath.mockReturnValue(mockStateManager);
|
|
272
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
273
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
274
|
-
expect(result.structuredContent?.prompt).not.toContain("UI drift");
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
describe("analyzeTestHealthTool — external-test confirm gate", () => {
|
|
278
|
-
let server;
|
|
279
|
-
beforeEach(() => {
|
|
280
|
-
jest.clearAllMocks();
|
|
281
|
-
server = makeFakeServer();
|
|
282
|
-
registerAnalyzeTestHealthTool(server);
|
|
283
|
-
});
|
|
284
|
-
const externalTestState = (extra = {}) => ({
|
|
285
|
-
existingTests: [
|
|
286
|
-
{ testFile: "/repo/e2e/tests/publish-flow.test.ts", source: "external", testType: "e2e", framework: "playwright" },
|
|
287
|
-
{ testFile: "/repo/tests/orders_contract.py", source: "skyramp", testType: "contract", framework: "pytest" },
|
|
288
|
-
],
|
|
289
|
-
...extra,
|
|
290
|
-
});
|
|
291
|
-
const pwService = (name) => ({
|
|
292
|
-
serviceName: name,
|
|
293
|
-
framework: "playwright",
|
|
294
|
-
runtimeDetails: { testSuites: [{ testRunCommand: "bash ./e2e/run.sh" }] },
|
|
295
|
-
});
|
|
296
|
-
it("gates until a confirm run is recorded when external tests + runnable test-env exist", async () => {
|
|
297
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState()));
|
|
298
|
-
mockWsRead.mockResolvedValue({ services: [pwService("ghost")] });
|
|
299
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
300
|
-
// Refuses to produce the drift prompt; instructs the confirm run instead.
|
|
301
|
-
expect(mockBuildDriftAnalysisPrompt).not.toHaveBeenCalled();
|
|
302
|
-
expect(result.structuredContent).toBeUndefined();
|
|
303
|
-
expect(result.content[0].text).toContain("skyramp_run_existing_tests");
|
|
304
|
-
expect(result.content[0].text).toContain('mode: "confirm"');
|
|
305
|
-
expect(result.content[0].text).toContain("/repo/e2e/tests/publish-flow.test.ts");
|
|
306
|
-
});
|
|
307
|
-
it("gates when MULTIPLE Playwright services are configured (regression: resolveRunConfig throw no longer fails-open)", async () => {
|
|
308
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState()));
|
|
309
|
-
// Two Playwright services with test* — e.g. Ghost's ghost + ghost-content.
|
|
310
|
-
// The old resolveRunConfig-based check threw here and silently skipped the gate.
|
|
311
|
-
mockWsRead.mockResolvedValue({ services: [pwService("ghost"), pwService("ghost-content")] });
|
|
312
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
313
|
-
expect(mockBuildDriftAnalysisPrompt).not.toHaveBeenCalled();
|
|
314
|
-
expect(result.content[0].text).toContain("skyramp_run_existing_tests");
|
|
315
|
-
// Instruction disambiguates the service for the multi-service case.
|
|
316
|
-
expect(result.content[0].text).toContain('service: "ghost"');
|
|
317
|
-
});
|
|
318
|
-
it("does not gate once a confirm run has been recorded (loop-safe)", async () => {
|
|
319
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState({ externalTestResults: [{ mode: "confirm", ranAt: "t", results: [] }] })));
|
|
320
|
-
mockWsRead.mockResolvedValue({ services: [pwService("ghost")] });
|
|
321
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
322
|
-
expect(mockBuildDriftAnalysisPrompt).toHaveBeenCalled();
|
|
323
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
324
|
-
});
|
|
325
|
-
it("still gates when only a verify run is recorded (verify must not clear the confirm gate)", async () => {
|
|
326
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState({ externalTestResults: [{ mode: "verify", ranAt: "t", results: [] }] })));
|
|
327
|
-
mockWsRead.mockResolvedValue({ services: [pwService("ghost")] });
|
|
328
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
329
|
-
expect(mockBuildDriftAnalysisPrompt).not.toHaveBeenCalled();
|
|
330
|
-
expect(result.content[0].text).toContain('mode: "confirm"');
|
|
331
|
-
});
|
|
332
|
-
it("does not gate when the repo has no runnable test-env config (Playwright service without testRunCommand)", async () => {
|
|
333
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState()));
|
|
334
|
-
mockWsRead.mockResolvedValue({ services: [{ serviceName: "ghost", framework: "playwright" }] });
|
|
335
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
336
|
-
expect(mockBuildDriftAnalysisPrompt).toHaveBeenCalled();
|
|
337
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
338
|
-
});
|
|
339
|
-
it("does not gate when there are no external tests relevant to the diff", async () => {
|
|
340
|
-
mockFromStatePath.mockReturnValue(makeStateManager({
|
|
341
|
-
existingTests: [{ testFile: "/repo/tests/orders_contract.py", source: "skyramp", testType: "contract", framework: "pytest" }],
|
|
342
|
-
}));
|
|
343
|
-
mockWsRead.mockResolvedValue({ services: [pwService("ghost")] });
|
|
344
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
345
|
-
expect(mockBuildDriftAnalysisPrompt).toHaveBeenCalled();
|
|
346
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
347
|
-
});
|
|
348
|
-
it("fails open (produces drift prompt) when the workspace config cannot be read", async () => {
|
|
349
|
-
mockFromStatePath.mockReturnValue(makeStateManager(externalTestState()));
|
|
350
|
-
mockWsRead.mockRejectedValue(new Error("workspace.yml missing"));
|
|
351
|
-
const result = await server.getHandler()({ stateFile: "/tmp/state.json" });
|
|
352
|
-
expect(mockBuildDriftAnalysisPrompt).toHaveBeenCalled();
|
|
353
|
-
expect(result.structuredContent?.prompt).toContain("API drift");
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
describe("runnableTestEnvServices — multi-suite recognition (SKYR-4002)", () => {
|
|
357
|
-
// NOTE: this file already mocks the whole `workspace.js` module (see
|
|
358
|
-
// jest.unstable_mockModule above) with a factory that returns a plain object
|
|
359
|
-
// literal `{ read: mockWsRead }` rather than a `new`-constructed instance, so
|
|
360
|
-
// `WorkspaceConfigManager.prototype.read` is never consulted by the code under
|
|
361
|
-
// test. jest.spyOn(WorkspaceConfigManager.prototype, "read") was attempted and
|
|
362
|
-
// confirmed to be a no-op here (spied prototype method never invoked; the real
|
|
363
|
-
// module-level mockWsRead default of `{ services: [] }` won instead). Using the
|
|
364
|
-
// file's own established mock control point (mockWsRead) for parity with the 6
|
|
365
|
-
// sibling gate tests below — same assertion, different injection point.
|
|
366
|
-
it("recognizes a Playwright suite declared under testSuites, AND a reader-backed jest suite (SKYR-3990/3991: gate widened beyond Playwright-only)", async () => {
|
|
367
|
-
const { runnableTestEnvServices } = await import("./analyzeTestHealthTool.js");
|
|
368
|
-
mockWsRead.mockResolvedValue({
|
|
369
|
-
services: [
|
|
370
|
-
{ serviceName: "ui", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ framework: "playwright", testRunCommand: "pw" }] } },
|
|
371
|
-
{ serviceName: "api", framework: "jest", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "jest" }] } },
|
|
372
|
-
],
|
|
373
|
-
});
|
|
374
|
-
await expect(runnableTestEnvServices("/x")).resolves.toEqual(["ui", "api"]);
|
|
375
|
-
});
|
|
376
|
-
it("excludes a framework with no reader (e.g. go) even with a testRunCommand", async () => {
|
|
377
|
-
const { runnableTestEnvServices } = await import("./analyzeTestHealthTool.js");
|
|
378
|
-
mockWsRead.mockResolvedValue({
|
|
379
|
-
services: [
|
|
380
|
-
{ serviceName: "svc", framework: "go", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "go test ./..." }] } },
|
|
381
|
-
],
|
|
382
|
-
});
|
|
383
|
-
await expect(runnableTestEnvServices("/x")).resolves.toEqual([]);
|
|
384
|
-
});
|
|
385
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|