@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.
Files changed (289) hide show
  1. package/build/commands/commandLibrary.d.ts +1 -0
  2. package/build/commands/commandLibrary.js +19 -13
  3. package/build/commands/localDevTestChangesCommand.d.ts +15 -0
  4. package/build/commands/localDevTestChangesCommand.js +201 -0
  5. package/build/index.js +80 -6
  6. package/build/prompts/code-reuse.js +3 -0
  7. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
  8. package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
  9. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
  10. package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
  11. package/build/prompts/local-dev/local-dev-plan.js +429 -0
  12. package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
  13. package/build/prompts/local-dev/local-dev-prompts.js +190 -0
  14. package/build/prompts/pom-aware-code-reuse.js +12 -0
  15. package/build/prompts/prompt-utils.d.ts +8 -0
  16. package/build/prompts/prompt-utils.js +33 -0
  17. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
  18. package/build/prompts/sut-setup/shared.js +16 -12
  19. package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
  20. package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
  21. package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
  22. package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
  23. package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
  24. package/build/prompts/testbot/testbot-prompts.js +32 -52
  25. package/build/recommendation/planRanker.d.ts +15 -2
  26. package/build/recommendation/planRanker.js +76 -5
  27. package/build/resources/testbotResource.js +2 -1
  28. package/build/services/AnalyticsService.d.ts +1 -1
  29. package/build/services/TestExecutionService.d.ts +2 -1
  30. package/build/services/TestExecutionService.js +8 -3
  31. package/build/services/TestGenerationService.d.ts +2 -2
  32. package/build/services/TestGenerationService.js +39 -21
  33. package/build/services/containerEnv.js +3 -1
  34. package/build/tool-phases.js +6 -0
  35. package/build/tools/code-refactor/codeReuseTool.js +43 -4
  36. package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
  37. package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
  38. package/build/tools/code-refactor/reuse-outcome.js +158 -0
  39. package/build/tools/code-refactor/reuse-state.d.ts +45 -0
  40. package/build/tools/code-refactor/reuse-state.js +140 -0
  41. package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
  42. package/build/tools/enrichTestWithMocksTool.js +726 -0
  43. package/build/tools/executeSkyrampTestTool.d.ts +11 -0
  44. package/build/tools/executeSkyrampTestTool.js +62 -21
  45. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
  46. package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
  47. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
  48. package/build/tools/generate-tests/generateContractRestTool.js +2 -2
  49. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
  50. package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
  51. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
  52. package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
  53. package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
  54. package/build/tools/generate-tests/generateMockRestTool.js +391 -22
  55. package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
  56. package/build/tools/generate-tests/planGuard.js +2 -22
  57. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
  58. package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
  59. package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
  60. package/build/tools/localDevWorkerComposeTool.js +264 -0
  61. package/build/tools/one-click/oneClickTool.d.ts +13 -0
  62. package/build/tools/one-click/oneClickTool.js +195 -24
  63. package/build/tools/preflightMockCheckTool.d.ts +2 -0
  64. package/build/tools/preflightMockCheckTool.js +96 -0
  65. package/build/tools/queryProxyMocksTool.d.ts +70 -0
  66. package/build/tools/queryProxyMocksTool.js +522 -0
  67. package/build/tools/runExistingTestsTool.d.ts +31 -0
  68. package/build/tools/runExistingTestsTool.js +214 -13
  69. package/build/tools/submitReportTool.js +38 -3
  70. package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
  71. package/build/tools/test-management/analyzeChangesTool.js +63 -40
  72. package/build/tools/test-management/registerTestPlanTool.js +55 -7
  73. package/build/tools/trace/startTraceCollectionTool.js +3 -3
  74. package/build/types/FrontendIntegration.d.ts +3 -0
  75. package/build/types/FrontendIntegration.js +3 -0
  76. package/build/types/OneClickCommands.d.ts +1 -1
  77. package/build/types/Recommendation.d.ts +20 -0
  78. package/build/types/Recommendation.js +32 -6
  79. package/build/types/RepositoryAnalysis.d.ts +131 -14
  80. package/build/types/RepositoryAnalysis.js +16 -2
  81. package/build/types/ReuseOutcome.d.ts +63 -0
  82. package/build/types/ReuseOutcome.js +33 -0
  83. package/build/types/TestExecution.d.ts +1 -0
  84. package/build/types/TestTypes.d.ts +25 -7
  85. package/build/types/TestTypes.js +22 -6
  86. package/build/types/TestbotReport.d.ts +7 -0
  87. package/build/types/index.d.ts +2 -0
  88. package/build/types/index.js +1 -0
  89. package/build/utils/AnalysisStateManager.d.ts +26 -0
  90. package/build/utils/AnalysisStateManager.js +31 -1
  91. package/build/utils/analyze-openapi.js +18 -1
  92. package/build/utils/branchDiff.d.ts +17 -1
  93. package/build/utils/branchDiff.js +99 -14
  94. package/build/utils/featureFlags.d.ts +31 -0
  95. package/build/utils/featureFlags.js +37 -0
  96. package/build/utils/frontendIntegration.js +8 -1
  97. package/build/utils/grpcMockValidation.d.ts +1 -0
  98. package/build/utils/grpcMockValidation.js +49 -0
  99. package/build/utils/httpMethodValidation.d.ts +4 -0
  100. package/build/utils/httpMethodValidation.js +15 -0
  101. package/build/utils/logger.js +1 -1
  102. package/build/utils/mockCompatibility.d.ts +49 -0
  103. package/build/utils/mockCompatibility.js +82 -0
  104. package/build/utils/pom-scope/pom-files.js +7 -0
  105. package/build/utils/pom-verify/bindings.js +11 -1
  106. package/build/utils/pom-verify/re-exports.d.ts +10 -0
  107. package/build/utils/pom-verify/re-exports.js +61 -0
  108. package/build/utils/pom-verify/resolve.d.ts +4 -1
  109. package/build/utils/pom-verify/resolve.js +7 -4
  110. package/build/utils/pom-verify/verify.d.ts +5 -0
  111. package/build/utils/pom-verify/verify.js +25 -3
  112. package/build/utils/progress.js +10 -5
  113. package/build/utils/proxy-terminal.js +3 -3
  114. package/build/utils/routeParsers.d.ts +3 -9
  115. package/build/utils/routeParsers.js +79 -4
  116. package/build/utils/utils.js +2 -2
  117. package/build/utils/versions.d.ts +4 -3
  118. package/build/utils/versions.js +3 -1
  119. package/build/utils/workspaceAuth.d.ts +46 -0
  120. package/build/utils/workspaceAuth.js +156 -1
  121. package/build/workspace/testSuites.d.ts +2 -1
  122. package/build/workspace/testSuites.js +1 -1
  123. package/build/workspace/workspace.d.ts +108 -32
  124. package/build/workspace/workspace.js +32 -4
  125. package/package.json +5 -2
  126. package/build/adapters/jestAdapter.test.d.ts +0 -1
  127. package/build/adapters/jestAdapter.test.js +0 -93
  128. package/build/adapters/mochaAdapter.test.d.ts +0 -1
  129. package/build/adapters/mochaAdapter.test.js +0 -63
  130. package/build/adapters/playwrightAdapter.test.d.ts +0 -1
  131. package/build/adapters/playwrightAdapter.test.js +0 -169
  132. package/build/adapters/pytestAdapter.test.d.ts +0 -1
  133. package/build/adapters/pytestAdapter.test.js +0 -90
  134. package/build/prompts/code-reuse.test.d.ts +0 -1
  135. package/build/prompts/code-reuse.test.js +0 -62
  136. package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
  137. package/build/prompts/pom-aware-code-reuse.test.js +0 -11
  138. package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
  139. package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
  140. package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
  141. package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
  142. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
  143. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
  144. package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
  145. package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
  146. package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
  147. package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
  148. package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
  149. package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
  150. package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
  151. package/build/prompts/testbot/testbot-prompts.test.js +0 -451
  152. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
  153. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
  154. package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
  155. package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
  156. package/build/recommendation/discriminators.test.d.ts +0 -1
  157. package/build/recommendation/discriminators.test.js +0 -324
  158. package/build/recommendation/diversity.test.d.ts +0 -1
  159. package/build/recommendation/diversity.test.js +0 -77
  160. package/build/recommendation/planRanker.test.d.ts +0 -1
  161. package/build/recommendation/planRanker.test.js +0 -110
  162. package/build/resources/testbotResource.test.d.ts +0 -1
  163. package/build/resources/testbotResource.test.js +0 -44
  164. package/build/services/AnalyticsService.test.d.ts +0 -1
  165. package/build/services/AnalyticsService.test.js +0 -86
  166. package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
  167. package/build/services/ScenarioGenerationService.integration.test.js +0 -162
  168. package/build/services/ScenarioGenerationService.test.d.ts +0 -1
  169. package/build/services/ScenarioGenerationService.test.js +0 -414
  170. package/build/services/TestDiscoveryService.test.d.ts +0 -1
  171. package/build/services/TestDiscoveryService.test.js +0 -983
  172. package/build/services/TestExecutionService.test.d.ts +0 -1
  173. package/build/services/TestExecutionService.test.js +0 -1032
  174. package/build/services/TestGenerationService.test.d.ts +0 -1
  175. package/build/services/TestGenerationService.test.js +0 -578
  176. package/build/tool-phase-coverage.test.d.ts +0 -1
  177. package/build/tool-phase-coverage.test.js +0 -49
  178. package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
  179. package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
  180. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
  181. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
  182. package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
  183. package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
  184. package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
  185. package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
  186. package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
  187. package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
  188. package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
  189. package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
  190. package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
  191. package/build/tools/generate-tests/planGuard.test.js +0 -185
  192. package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
  193. package/build/tools/generate-tests/scenarioLint.test.js +0 -100
  194. package/build/tools/runExistingTestsTool.test.d.ts +0 -1
  195. package/build/tools/runExistingTestsTool.test.js +0 -379
  196. package/build/tools/submitReportTool.test.d.ts +0 -1
  197. package/build/tools/submitReportTool.test.js +0 -1428
  198. package/build/tools/test-management/actionsTool.test.d.ts +0 -1
  199. package/build/tools/test-management/actionsTool.test.js +0 -436
  200. package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
  201. package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
  202. package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
  203. package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
  204. package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
  205. package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
  206. package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
  207. package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
  208. package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
  209. package/build/tools/trace/resolveSessionPaths.test.js +0 -104
  210. package/build/tools/trace/sessionState.test.d.ts +0 -1
  211. package/build/tools/trace/sessionState.test.js +0 -17
  212. package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
  213. package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
  214. package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
  215. package/build/tools/workspace/serviceUpsert.test.js +0 -50
  216. package/build/utils/AnalysisStateManager.test.d.ts +0 -1
  217. package/build/utils/AnalysisStateManager.test.js +0 -134
  218. package/build/utils/dartRouteExtractor.test.d.ts +0 -1
  219. package/build/utils/dartRouteExtractor.test.js +0 -307
  220. package/build/utils/docker.test.d.ts +0 -1
  221. package/build/utils/docker.test.js +0 -114
  222. package/build/utils/featureFlags.test.d.ts +0 -1
  223. package/build/utils/featureFlags.test.js +0 -81
  224. package/build/utils/fileWalk.test.d.ts +0 -1
  225. package/build/utils/fileWalk.test.js +0 -252
  226. package/build/utils/frontendIntegration.test.d.ts +0 -1
  227. package/build/utils/frontendIntegration.test.js +0 -229
  228. package/build/utils/frontendSelectors.test.d.ts +0 -1
  229. package/build/utils/frontendSelectors.test.js +0 -118
  230. package/build/utils/gitStaging.test.d.ts +0 -1
  231. package/build/utils/gitStaging.test.js +0 -111
  232. package/build/utils/httpDefaults.test.d.ts +0 -1
  233. package/build/utils/httpDefaults.test.js +0 -21
  234. package/build/utils/importerHop.test.d.ts +0 -1
  235. package/build/utils/importerHop.test.js +0 -469
  236. package/build/utils/pathAffinityClassification.test.d.ts +0 -1
  237. package/build/utils/pathAffinityClassification.test.js +0 -208
  238. package/build/utils/planMatchKeys.test.d.ts +0 -1
  239. package/build/utils/planMatchKeys.test.js +0 -123
  240. package/build/utils/pom-scope/index.test.d.ts +0 -1
  241. package/build/utils/pom-scope/index.test.js +0 -278
  242. package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
  243. package/build/utils/pom-scope/pom-files.test.js +0 -29
  244. package/build/utils/pom-scope/scoring.test.d.ts +0 -1
  245. package/build/utils/pom-scope/scoring.test.js +0 -39
  246. package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
  247. package/build/utils/pom-scope/selector-extractor.test.js +0 -67
  248. package/build/utils/pom-verify/bindings.test.d.ts +0 -1
  249. package/build/utils/pom-verify/bindings.test.js +0 -164
  250. package/build/utils/pom-verify/calls.test.d.ts +0 -1
  251. package/build/utils/pom-verify/calls.test.js +0 -61
  252. package/build/utils/pom-verify/resolve.test.d.ts +0 -1
  253. package/build/utils/pom-verify/resolve.test.js +0 -114
  254. package/build/utils/pom-verify/verify.test.d.ts +0 -1
  255. package/build/utils/pom-verify/verify.test.js +0 -374
  256. package/build/utils/pr-comment-parser.test.d.ts +0 -1
  257. package/build/utils/pr-comment-parser.test.js +0 -428
  258. package/build/utils/progress.test.d.ts +0 -1
  259. package/build/utils/progress.test.js +0 -37
  260. package/build/utils/projectMetadata.test.d.ts +0 -1
  261. package/build/utils/projectMetadata.test.js +0 -172
  262. package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
  263. package/build/utils/pythonMountPrefixes.test.js +0 -113
  264. package/build/utils/repoScanner.test.d.ts +0 -1
  265. package/build/utils/repoScanner.test.js +0 -190
  266. package/build/utils/reportVerification.test.d.ts +0 -1
  267. package/build/utils/reportVerification.test.js +0 -185
  268. package/build/utils/routeParsers.test.d.ts +0 -1
  269. package/build/utils/routeParsers.test.js +0 -1011
  270. package/build/utils/scenarioDrafting.test.d.ts +0 -1
  271. package/build/utils/scenarioDrafting.test.js +0 -876
  272. package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
  273. package/build/utils/sourceRouteExtractor.test.js +0 -738
  274. package/build/utils/telemetry.test.d.ts +0 -1
  275. package/build/utils/telemetry.test.js +0 -70
  276. package/build/utils/trace-parser.test.d.ts +0 -6
  277. package/build/utils/trace-parser.test.js +0 -140
  278. package/build/utils/uiPageEnumerator.test.d.ts +0 -1
  279. package/build/utils/uiPageEnumerator.test.js +0 -824
  280. package/build/utils/utils.test.d.ts +0 -1
  281. package/build/utils/utils.test.js +0 -103
  282. package/build/utils/walkerCharacterization.test.d.ts +0 -1
  283. package/build/utils/walkerCharacterization.test.js +0 -233
  284. package/build/utils/workspaceAuth.test.d.ts +0 -1
  285. package/build/utils/workspaceAuth.test.js +0 -260
  286. package/build/workspace/testSuites.test.d.ts +0 -1
  287. package/build/workspace/testSuites.test.js +0 -23
  288. package/build/workspace/workspace.test.d.ts +0 -1
  289. package/build/workspace/workspace.test.js +0 -264
@@ -1,379 +0,0 @@
1
- import path from "path";
2
- import os from "os";
3
- import { promises as fs } from "fs";
4
- import { StateManager, } from "../utils/AnalysisStateManager.js";
5
- import { resolveRunConfig, aggregateRuns, runExternalTests, runExternalSuite, frameworkHasReader, extractLastJsonObject } from "./runExistingTestsTool.js";
6
- function playwrightConfig(runtimeOverrides) {
7
- return {
8
- services: [
9
- {
10
- serviceName: "web",
11
- framework: "playwright",
12
- runtimeDetails: {
13
- runtime: "local",
14
- testSuites: [
15
- {
16
- testRunCommand: "bash e2e/scripts/run-playwright-host.sh npx playwright test",
17
- testEnv: { TEST_WORKERS_COUNT: "1" },
18
- },
19
- ],
20
- ...runtimeOverrides,
21
- },
22
- },
23
- ],
24
- };
25
- }
26
- describe("frameworkHasReader", () => {
27
- it.each(["playwright", "pytest", "jest", "vitest"])("returns true for %s", (fw) => {
28
- expect(frameworkHasReader(fw)).toBe(true);
29
- });
30
- it.each(["go", undefined])("returns false for %s", (fw) => {
31
- expect(frameworkHasReader(fw)).toBe(false);
32
- });
33
- });
34
- describe("resolveRunConfig", () => {
35
- it("returns the Playwright service's run command and env", () => {
36
- const r = resolveRunConfig(playwrightConfig(), { service: "web" });
37
- expect(r.runs).toHaveLength(1);
38
- expect(r.runs[0].testRunCommand).toContain("playwright");
39
- expect(r.runs[0].testEnv).toMatchObject({ TEST_WORKERS_COUNT: "1" });
40
- });
41
- it("selects the sole Playwright service when serviceName is omitted", () => {
42
- const r = resolveRunConfig(playwrightConfig());
43
- expect(r.runs).toHaveLength(1);
44
- expect(r.runs[0].testRunCommand).toContain("playwright");
45
- });
46
- it("skips (no error), rather than throwing, an explicitly-named framework with no reader", () => {
47
- const cfg = playwrightConfig();
48
- cfg.services[0].framework = "go";
49
- const r = resolveRunConfig(cfg, { service: "web" });
50
- expect(r.runs).toHaveLength(0);
51
- expect(r.skips).toEqual([
52
- { service: "web", reason: expect.stringMatching(/reader/i) },
53
- ]);
54
- });
55
- it("skips (no error) when no service has a reader-supported framework", () => {
56
- const cfg = playwrightConfig();
57
- cfg.services[0].framework = "go";
58
- const r = resolveRunConfig(cfg);
59
- expect(r.runs).toHaveLength(0);
60
- expect(r.skips.map((s) => s.service)).toContain("web");
61
- expect(r.skips[0].reason).toMatch(/pytest/i);
62
- });
63
- it("carries the resolved framework on each run config", () => {
64
- const r = resolveRunConfig(playwrightConfig(), { service: "web" });
65
- expect(r.runs).toHaveLength(1);
66
- expect(r.runs[0].framework).toBe("playwright");
67
- });
68
- it("skips (no error, no reason to report) when testSuites is missing", () => {
69
- const cfg = playwrightConfig();
70
- delete cfg.services[0].runtimeDetails
71
- .testSuites;
72
- const r = resolveRunConfig(cfg, { service: "web" });
73
- // resolveSuites() drops a service with no testSuites entirely (SKYR-4002
74
- // Task 2), so there is no suite left to report a skip reason on — runs and
75
- // skips are both empty, and (critically) resolveRunConfig does not throw.
76
- expect(r.runs).toHaveLength(0);
77
- expect(r.skips).toHaveLength(0);
78
- });
79
- });
80
- describe("runExternalTests", () => {
81
- let stateFile;
82
- const fakeParsed = {
83
- results: [
84
- {
85
- testId: "a.test.ts › x",
86
- file: "a.test.ts",
87
- status: "fail",
88
- message: "boom",
89
- durationMs: 5,
90
- },
91
- ],
92
- summary: { ran: 1, failed: 1, errored: 0, skipped: 0, truncated: false },
93
- environmentHealthy: true,
94
- };
95
- beforeEach(async () => {
96
- const dir = await fs.mkdtemp(path.join(os.tmpdir(), "external-exec-"));
97
- stateFile = path.join(dir, "analyze-changes-state.json");
98
- const sm = StateManager.fromStatePath(stateFile);
99
- await sm.writeRepoData({
100
- existingTests: [],
101
- analysisScope: {},
102
- newEndpoints: [],
103
- }, {});
104
- });
105
- function deps(parsed = fakeParsed) {
106
- return {
107
- readConfig: async () => playwrightConfig(),
108
- runner: async () => parsed,
109
- now: () => "2026-07-16T00:00:00.000Z",
110
- };
111
- }
112
- it("returns the parsed results, summary and health", async () => {
113
- const out = await runExternalTests({
114
- workspacePath: "/repo",
115
- service: "web",
116
- stateFile,
117
- testSelectors: ["a.test.ts"],
118
- }, deps());
119
- expect(out.summary.failed).toBe(1);
120
- expect(out.environmentHealthy).toBe(true);
121
- expect(out.results[0].status).toBe("fail");
122
- });
123
- it("returns a skipped run (never calls the runner) when no suite is runnable", async () => {
124
- const out = await runExternalTests({
125
- workspacePath: "/repo",
126
- service: "web",
127
- stateFile,
128
- }, {
129
- readConfig: async () => {
130
- const cfg = playwrightConfig();
131
- delete cfg.services[0].runtimeDetails
132
- .testSuites;
133
- return cfg;
134
- },
135
- runner: async () => {
136
- throw new Error("runner must not be called on a skipped run");
137
- },
138
- now: () => "2026-07-16T00:00:00.000Z",
139
- });
140
- expect(out.skipped).toBe(true);
141
- expect(out.summary.ran).toBe(0);
142
- expect(out.environmentHealthy).toBe(true);
143
- expect(out.results).toHaveLength(0);
144
- });
145
- it("loops over multiple reader-backed suites, dispatching each by framework, and aggregates", async () => {
146
- const config = {
147
- services: [
148
- { serviceName: "api", framework: "jest", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "jest" }] } },
149
- { serviceName: "ui", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "pw" }] } },
150
- ],
151
- };
152
- const seenFrameworks = [];
153
- const out = await runExternalTests({ workspacePath: "/repo", stateFile }, {
154
- readConfig: async () => config,
155
- runner: async (c) => {
156
- seenFrameworks.push(c.framework);
157
- return {
158
- results: [{ testId: `${c.serviceName}:t`, file: "f", status: "pass", durationMs: 1 }],
159
- summary: { ran: 1, failed: 0, errored: 0, skipped: 0, truncated: false },
160
- environmentHealthy: true,
161
- };
162
- },
163
- now: () => "t",
164
- });
165
- expect(seenFrameworks.sort()).toEqual(["jest", "playwright"]);
166
- expect(out.summary.ran).toBe(2);
167
- expect(out.results).toHaveLength(2);
168
- expect(out.environmentHealthy).toBe(true);
169
- });
170
- it("persists an externalTestResults record to the state file", async () => {
171
- await runExternalTests({
172
- workspacePath: "/repo",
173
- service: "web",
174
- stateFile,
175
- testSelectors: ["a.test.ts"],
176
- mode: "confirm",
177
- }, deps());
178
- const sm = StateManager.fromStatePath(stateFile);
179
- const state = await sm.readRepoData();
180
- expect(state.externalTestResults).toHaveLength(1);
181
- expect(state.externalTestResults[0]).toMatchObject({
182
- mode: "confirm",
183
- ranAt: "2026-07-16T00:00:00.000Z",
184
- });
185
- expect(state.externalTestResults[0].summary.failed).toBe(1);
186
- });
187
- it("trims selectors and marks truncated when maxTests is exceeded", async () => {
188
- let received = [];
189
- const out = await runExternalTests({
190
- workspacePath: "/repo",
191
- service: "web",
192
- stateFile,
193
- testSelectors: ["a", "b", "c"],
194
- maxTests: 2,
195
- }, {
196
- readConfig: async () => playwrightConfig(),
197
- runner: async (_cfg, opts) => {
198
- received = opts.selectors;
199
- return {
200
- ...fakeParsed,
201
- summary: { ...fakeParsed.summary, truncated: opts.truncated },
202
- };
203
- },
204
- now: () => "t",
205
- });
206
- expect(received).toHaveLength(2);
207
- expect(out.summary.truncated).toBe(true);
208
- });
209
- });
210
- const cfg = (services) => ({ services });
211
- describe("resolveRunConfig (multi-suite)", () => {
212
- it("returns one run for a single Playwright service (no service arg)", () => {
213
- const r = resolveRunConfig(cfg([{ serviceName: "ui", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "pw" }] } }]));
214
- expect(r.runs.map((x) => x.serviceName)).toEqual(["ui"]);
215
- expect(r.skips).toEqual([]);
216
- });
217
- it("runs every runnable Playwright suite across services", () => {
218
- const r = resolveRunConfig(cfg([
219
- { serviceName: "server", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "a" }] } },
220
- { serviceName: "webapp", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "b" }] } },
221
- ]));
222
- expect(r.runs.map((x) => x.serviceName).sort()).toEqual(["server", "webapp"]);
223
- });
224
- it("runs a jest suite (reader exists) — routed to a run, not a skip", () => {
225
- const r = resolveRunConfig(cfg([
226
- { serviceName: "api", framework: "jest", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "jest" }] } },
227
- ]));
228
- expect(r.runs.map((x) => x.serviceName)).toEqual(["api"]);
229
- expect(r.runs[0].framework).toBe("jest");
230
- expect(r.skips).toEqual([]);
231
- });
232
- it("runs a pytest suite (reader exists) — routed to a run, not a skip", () => {
233
- const r = resolveRunConfig(cfg([
234
- { serviceName: "svc", framework: "pytest", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "pytest" }] } },
235
- ]));
236
- expect(r.runs.map((x) => x.serviceName)).toEqual(["svc"]);
237
- expect(r.runs[0].framework).toBe("pytest");
238
- expect(r.skips).toEqual([]);
239
- });
240
- it("runs mixed reader-backed suites (jest + playwright) and skips only a no-reader framework", () => {
241
- const r = resolveRunConfig(cfg([
242
- { serviceName: "api", framework: "jest", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "jest" }] } },
243
- { serviceName: "gosvc", framework: "go", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "go test" }] } },
244
- { serviceName: "ui", framework: "playwright", runtimeDetails: { runtime: "local", testSuites: [{ testRunCommand: "pw" }] } },
245
- ]));
246
- expect(r.runs.map((x) => x.serviceName).sort()).toEqual(["api", "ui"]);
247
- expect(r.skips.map((s) => s.service)).toEqual(["gosvc"]);
248
- expect(r.skips[0].reason).toMatch(/reader/i);
249
- });
250
- it("throws only for an explicitly-named unknown service", () => {
251
- expect(() => resolveRunConfig(cfg([]), { service: "nope" })).toThrow(/No service named/);
252
- });
253
- });
254
- describe("aggregateRuns", () => {
255
- it("sums summaries, concatenates results, and ANDs environmentHealthy", () => {
256
- const agg = aggregateRuns([
257
- { results: [{ testId: "a", file: "a", status: "pass", durationMs: 1 }], summary: { ran: 1, failed: 0, errored: 0, skipped: 0, truncated: false }, environmentHealthy: true },
258
- { results: [{ testId: "b", file: "b", status: "fail", durationMs: 1 }], summary: { ran: 1, failed: 1, errored: 0, skipped: 0, truncated: false }, environmentHealthy: false, healthDetail: "boom" },
259
- ]);
260
- expect(agg.summary).toEqual({ ran: 2, failed: 1, errored: 0, skipped: 0, truncated: false });
261
- expect(agg.results).toHaveLength(2);
262
- expect(agg.environmentHealthy).toBe(false);
263
- expect(agg.healthDetail).toContain("boom");
264
- });
265
- it("preserves the single suite's diagnostics unchanged", () => {
266
- const diagnostics = {
267
- runLevelErrors: ["some run-level error"],
268
- infraSpecFailed: false,
269
- maxFailuresBail: false,
270
- };
271
- const run = {
272
- results: [{ testId: "a", file: "a", status: "pass", durationMs: 1 }],
273
- summary: { ran: 1, failed: 0, errored: 0, skipped: 0, truncated: false },
274
- environmentHealthy: true,
275
- diagnostics,
276
- };
277
- const agg = aggregateRuns([run]);
278
- expect(agg.diagnostics).toEqual(diagnostics);
279
- });
280
- it("picks the first unhealthy suite's diagnostics across multiple suites", () => {
281
- const healthyDiagnostics = {
282
- runLevelErrors: [],
283
- infraSpecFailed: false,
284
- maxFailuresBail: false,
285
- };
286
- const unhealthyDiagnostics = {
287
- runLevelErrors: ["global setup failed"],
288
- infraSpecFailed: true,
289
- maxFailuresBail: false,
290
- };
291
- const agg = aggregateRuns([
292
- {
293
- results: [{ testId: "a", file: "a", status: "pass", durationMs: 1 }],
294
- summary: { ran: 1, failed: 0, errored: 0, skipped: 0, truncated: false },
295
- environmentHealthy: true,
296
- diagnostics: healthyDiagnostics,
297
- },
298
- {
299
- results: [{ testId: "b", file: "b", status: "error", durationMs: 1 }],
300
- summary: { ran: 0, failed: 0, errored: 1, skipped: 0, truncated: false },
301
- environmentHealthy: false,
302
- healthDetail: "boom",
303
- diagnostics: unhealthyDiagnostics,
304
- },
305
- ]);
306
- expect(agg.diagnostics).toEqual(unhealthyDiagnostics);
307
- });
308
- });
309
- describe("extractLastJsonObject", () => {
310
- it("returns a lone JSON object unchanged", () => {
311
- const parsed = JSON.parse(extractLastJsonObject('{"a":1}'));
312
- expect(parsed).toEqual({ a: 1 });
313
- });
314
- it("extracts the LAST top-level object when an earlier object + noise precede it", () => {
315
- const out = extractLastJsonObject('{"stale":1}\nnoise line\n{"stats":{"tests":2}}');
316
- const parsed = JSON.parse(out);
317
- expect(parsed.stats?.tests).toBe(2);
318
- expect(parsed.stale).toBeUndefined();
319
- });
320
- it("is not fooled by braces inside strings", () => {
321
- const parsed = JSON.parse(extractLastJsonObject('{"msg":"a } b { c","ok":true}'));
322
- expect(parsed).toEqual({ msg: "a } b { c", ok: true });
323
- });
324
- it("throws when there is no JSON object", () => {
325
- expect(() => extractLastJsonObject("no json here")).toThrow();
326
- });
327
- });
328
- describe("runExternalSuite — surfaces stderr on an unhealthy but parseable report", () => {
329
- // A stdout-reporting spec so the test needs no temp file: the report is the
330
- // JSON the command prints; `parse` decides health. The command also writes a
331
- // diagnostic to stderr, standing in for a Playwright global-setup stack trace.
332
- const specWith = (parse) => ({
333
- framework: "playwright",
334
- outputVia: "stdout",
335
- buildArgs: () => [],
336
- parse,
337
- });
338
- const runCfg = (cmd) => ({
339
- serviceName: "web",
340
- framework: "playwright",
341
- testRunCommand: cmd,
342
- });
343
- const runOpts = {
344
- workspacePath: os.tmpdir(),
345
- selectors: [],
346
- mode: "confirm",
347
- truncated: false,
348
- };
349
- it("appends the stderr tail to the parser's healthDetail when env is unhealthy", async () => {
350
- const out = await runExternalSuite(specWith(() => ({
351
- results: [],
352
- summary: { ran: 0, failed: 0, errored: 0, skipped: 6, truncated: false },
353
- environmentHealthy: false,
354
- healthDetail: 'Environment setup failed: "global environment setup" (tests/global.setup.ts) reported fail.',
355
- })), runCfg("printf '%s\\n' 'Error: no such container: ghost-dev-mysql' 1>&2; printf '%s' '{\"ok\":true}'"), runOpts);
356
- expect(out.environmentHealthy).toBe(false);
357
- expect(out.healthDetail).toContain("Environment setup failed");
358
- expect(out.healthDetail).toContain("stderr:");
359
- expect(out.healthDetail).toContain("no such container: ghost-dev-mysql");
360
- });
361
- it("synthesizes a healthDetail from the stderr tail when the parser left it empty", async () => {
362
- const out = await runExternalSuite(specWith(() => ({
363
- results: [],
364
- summary: { ran: 0, failed: 0, errored: 0, skipped: 0, truncated: false },
365
- environmentHealthy: false,
366
- })), runCfg("printf '%s' 'boom on the runner' 1>&2; printf '%s' '{\"ok\":true}'"), runOpts);
367
- expect(out.healthDetail).toMatch(/playwright environment unhealthy/);
368
- expect(out.healthDetail).toContain("boom on the runner");
369
- });
370
- it("leaves a healthy run's healthDetail untouched (no stderr noise leaks in)", async () => {
371
- const out = await runExternalSuite(specWith(() => ({
372
- results: [{ testId: "a", file: "a", status: "pass", durationMs: 1 }],
373
- summary: { ran: 1, failed: 0, errored: 0, skipped: 0, truncated: false },
374
- environmentHealthy: true,
375
- })), runCfg("printf '%s' 'harmless deprecation warning' 1>&2; printf '%s' '{\"ok\":true}'"), runOpts);
376
- expect(out.environmentHealthy).toBe(true);
377
- expect(out.healthDetail).toBeUndefined();
378
- });
379
- });
@@ -1 +0,0 @@
1
- export {};