@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,371 +0,0 @@
1
- import { jest } from "@jest/globals";
2
- jest.mock("@skyramp/skyramp", () => ({
3
- WorkspaceConfigManager: { create: jest.fn() },
4
- }));
5
- import * as fs from "fs";
6
- import * as path from "path";
7
- import * as os from "os";
8
- import { hasFlutterSdkDep, isFrontendFile, isTestFile, buildScopeAssessmentSection } from "./scopeAssessment.js";
9
- // ---------------------------------------------------------------------------
10
- // isFrontendFile
11
- // ---------------------------------------------------------------------------
12
- describe("isFrontendFile", () => {
13
- it("returns true for a TSX component in components/", () => {
14
- expect(isFrontendFile("src/components/Button.tsx")).toBe(true);
15
- });
16
- it("returns true for a JSX file in pages/", () => {
17
- expect(isFrontendFile("src/pages/Home.jsx")).toBe(true);
18
- });
19
- it("returns true for a Vue file in views/", () => {
20
- expect(isFrontendFile("src/views/Dashboard.vue")).toBe(true);
21
- });
22
- it("returns false for a TS route handler (API directory)", () => {
23
- expect(isFrontendFile("src/routes/items.ts")).toBe(false);
24
- });
25
- it("returns false for a TS file in a backend service directory", () => {
26
- expect(isFrontendFile("src/services/AuthService.ts")).toBe(false);
27
- });
28
- it("returns true for a TS file in components/ (tsx? matches .ts)", () => {
29
- // FRONTEND_FILE_PATTERN uses tsx? which matches both .ts and .tsx
30
- expect(isFrontendFile("src/components/utils.ts")).toBe(true);
31
- });
32
- it("returns false for a backend TS file in api/ even with tsx extension", () => {
33
- expect(isFrontendFile("src/api/handlers/UserHandler.tsx")).toBe(false);
34
- });
35
- // Regression cases from three-tier logic
36
- it("returns true for SvelteKit page in routes/ (svelte is always frontend)", () => {
37
- expect(isFrontendFile("src/routes/+page.svelte")).toBe(true);
38
- });
39
- it("returns false for Next.js API route (.tsx in pages/api/)", () => {
40
- expect(isFrontendFile("pages/api/users.tsx")).toBe(false);
41
- });
42
- it("returns true for a standalone TSX component (no API dir)", () => {
43
- expect(isFrontendFile("Button.tsx")).toBe(true);
44
- });
45
- it("returns true for an App.vue file", () => {
46
- expect(isFrontendFile("App.vue")).toBe(true);
47
- });
48
- // .tsx/.jsx in non-standard dirs (lib/, shared/, helpers/) — tier 2 fires because
49
- // JSX syntax is inherently frontend; no backend framework uses .tsx outside API dirs.
50
- it("returns true for a TSX helper in lib/ (JSX implies frontend, no API dir)", () => {
51
- expect(isFrontendFile("lib/FormHelpers.tsx")).toBe(true);
52
- });
53
- it("returns true for a JSX component in shared/", () => {
54
- expect(isFrontendFile("shared/helpers.jsx")).toBe(true);
55
- });
56
- // .ts in a non-frontend dir stays false — plain TypeScript needs directory context.
57
- it("returns false for a plain TS utility in lib/ (no frontend dir, tier 3 applies)", () => {
58
- expect(isFrontendFile("lib/utils.ts")).toBe(false);
59
- });
60
- it("returns false for a plain TS API client in utils/ (no frontend dir)", () => {
61
- expect(isFrontendFile("utils/apiClient.ts")).toBe(false);
62
- });
63
- // Flutter / Dart support — gated on hasFlutterSdkDep.
64
- // Without the flag, .dart is unrecognised (legacy behaviour). With it,
65
- // .dart is always-frontend (tier 2, before API_DIR_PATTERN).
66
- describe(".dart files (Flutter)", () => {
67
- it("returns false for .dart without hasFlutterSdkDep (default)", () => {
68
- expect(isFrontendFile("lib/main.dart")).toBe(false);
69
- });
70
- it("returns false for .dart with hasFlutterSdkDep: false", () => {
71
- expect(isFrontendFile("lib/main.dart", { hasFlutterSdkDep: false })).toBe(false);
72
- });
73
- it("returns true for .dart with hasFlutterSdkDep: true", () => {
74
- expect(isFrontendFile("lib/main.dart", { hasFlutterSdkDep: true })).toBe(true);
75
- });
76
- it("returns true for nested .dart files in a Flutter project", () => {
77
- expect(isFrontendFile("lib/widgets/game_board.dart", { hasFlutterSdkDep: true })).toBe(true);
78
- });
79
- it("returns true for .dart even in a directory that would otherwise look API-like (Flutter has no server-side Dart in scope)", () => {
80
- // .dart sits in tier 2 (above API_DIR_PATTERN) so it's frontend even
81
- // under api/ — there's no server-side Dart web framework that would
82
- // make this ambiguous in the Flutter case.
83
- expect(isFrontendFile("lib/api/client.dart", { hasFlutterSdkDep: true })).toBe(true);
84
- });
85
- it("returns true for game.dart at repo root in a Flutter project", () => {
86
- expect(isFrontendFile("game.dart", { hasFlutterSdkDep: true })).toBe(true);
87
- });
88
- });
89
- });
90
- // ---------------------------------------------------------------------------
91
- // hasFlutterSdkDep
92
- // ---------------------------------------------------------------------------
93
- describe("hasFlutterSdkDep", () => {
94
- let tmpDir;
95
- beforeEach(() => {
96
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "flutter-pubspec-"));
97
- });
98
- afterEach(() => {
99
- fs.rmSync(tmpDir, { recursive: true, force: true });
100
- });
101
- it("returns false when pubspec.yaml is absent", () => {
102
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
103
- });
104
- it("returns true when pubspec.yaml has the canonical Flutter SDK dep", () => {
105
- fs.writeFileSync(path.join(tmpDir, "pubspec.yaml"), `name: birdle
106
- description: A Flutter app.
107
- dependencies:
108
- flutter:
109
- sdk: flutter
110
- cupertino_icons: ^1.0.6
111
- `);
112
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
113
- });
114
- it("returns false for a pure Dart project (no flutter SDK dep)", () => {
115
- // Pure Dart server (e.g. shelf, dart_frog) has pubspec.yaml but no flutter SDK
116
- fs.writeFileSync(path.join(tmpDir, "pubspec.yaml"), `name: my_dart_server
117
- description: A Dart server using shelf.
118
- environment:
119
- sdk: ">=3.0.0 <4.0.0"
120
- dependencies:
121
- shelf: ^1.4.0
122
- shelf_router: ^1.1.4
123
- `);
124
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
125
- });
126
- it("returns false for a Dart CLI tool (no flutter SDK dep)", () => {
127
- fs.writeFileSync(path.join(tmpDir, "pubspec.yaml"), `name: my_cli
128
- description: A Dart CLI.
129
- environment:
130
- sdk: ^3.5.0
131
- dependencies:
132
- args: ^2.5.0
133
- `);
134
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
135
- });
136
- it("returns false on a malformed pubspec.yaml (graceful failure)", () => {
137
- fs.writeFileSync(path.join(tmpDir, "pubspec.yaml"), "::: not yaml ::: \x00");
138
- // Our regex-based check still works on string content; this is more of
139
- // a "doesn't throw" test. Returns false because the malformed content
140
- // doesn't match the sdk: flutter pattern.
141
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
142
- });
143
- it("returns true even with extra whitespace and comments in pubspec.yaml", () => {
144
- fs.writeFileSync(path.join(tmpDir, "pubspec.yaml"), `name: birdle
145
- # This is the SDK dep
146
- dependencies:
147
- flutter:
148
- sdk: flutter
149
- `);
150
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
151
- });
152
- // Subdir search — common shapes in real Flutter repos.
153
- it("returns true when pubspec.yaml lives in app/", () => {
154
- fs.mkdirSync(path.join(tmpDir, "app"));
155
- fs.writeFileSync(path.join(tmpDir, "app", "pubspec.yaml"), "name: app\ndependencies:\n flutter:\n sdk: flutter\n");
156
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
157
- });
158
- it("returns true when pubspec.yaml lives in mobile/", () => {
159
- fs.mkdirSync(path.join(tmpDir, "mobile"));
160
- fs.writeFileSync(path.join(tmpDir, "mobile", "pubspec.yaml"), "name: app\ndependencies:\n flutter:\n sdk: flutter\n");
161
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
162
- });
163
- it("returns true for monorepo with apps/<name>/pubspec.yaml", () => {
164
- fs.mkdirSync(path.join(tmpDir, "apps", "customer-app"), { recursive: true });
165
- fs.writeFileSync(path.join(tmpDir, "apps", "customer-app", "pubspec.yaml"), "name: customer_app\ndependencies:\n flutter:\n sdk: flutter\n");
166
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
167
- });
168
- it("returns true for monorepo with packages/<name>/pubspec.yaml", () => {
169
- fs.mkdirSync(path.join(tmpDir, "packages", "ui"), { recursive: true });
170
- fs.writeFileSync(path.join(tmpDir, "packages", "ui", "pubspec.yaml"), "name: ui\ndependencies:\n flutter:\n sdk: flutter\n");
171
- expect(hasFlutterSdkDep(tmpDir)).toBe(true);
172
- });
173
- it("returns false when monorepo subdirs only contain pure-Dart packages", () => {
174
- // Mixed monorepo: a Dart CLI in packages/cli/, no Flutter app anywhere.
175
- fs.mkdirSync(path.join(tmpDir, "packages", "cli"), { recursive: true });
176
- fs.writeFileSync(path.join(tmpDir, "packages", "cli", "pubspec.yaml"), "name: cli\ndependencies:\n args: ^2.5.0\n");
177
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
178
- });
179
- it("does not walk arbitrary subdirs (e.g. node_modules-style nested deps)", () => {
180
- // A pubspec deep under an unsupported subdir should NOT be picked up.
181
- // Without this guard, a transitive dependency's pubspec could falsely
182
- // flag a non-Flutter repo as Flutter.
183
- fs.mkdirSync(path.join(tmpDir, "vendor", "nested", "lib"), { recursive: true });
184
- fs.writeFileSync(path.join(tmpDir, "vendor", "nested", "lib", "pubspec.yaml"), "name: nested\ndependencies:\n flutter:\n sdk: flutter\n");
185
- expect(hasFlutterSdkDep(tmpDir)).toBe(false);
186
- });
187
- });
188
- // ---------------------------------------------------------------------------
189
- // isTestFile
190
- // ---------------------------------------------------------------------------
191
- describe("isTestFile", () => {
192
- it("matches Skyramp-generated test suffix patterns", () => {
193
- expect(isTestFile("backend/tests/orders_integration_test.py")).toBe(true);
194
- expect(isTestFile("frontend/tests/cart_ui_test.ts")).toBe(true);
195
- expect(isTestFile("backend/tests/users_contract_test.py")).toBe(true);
196
- expect(isTestFile("backend/tests/load_test.py")).toBe(true);
197
- });
198
- it("matches Skyramp scenario JSON files", () => {
199
- expect(isTestFile("tests/scenario_orders.json")).toBe(true);
200
- expect(isTestFile("scenario_checkout.json")).toBe(true);
201
- });
202
- it("matches conventional Vitest/Jest/Playwright spec naming", () => {
203
- expect(isTestFile("frontend/tests/cart_labels_baseline.spec.ts")).toBe(true);
204
- expect(isTestFile("src/components/Button.test.tsx")).toBe(true);
205
- expect(isTestFile("e2e/login.spec.js")).toBe(true);
206
- expect(isTestFile("packages/foo/Bar.test.jsx")).toBe(true);
207
- // `.e2e.` dot form (Playwright/Cypress) — discovery's UI_TEST_EXT treats it as a UI test.
208
- expect(isTestFile("e2e/login.e2e.ts")).toBe(true);
209
- expect(isTestFile("packages/foo/Members.e2e.tsx")).toBe(true);
210
- });
211
- it("matches files under __tests__/ directories", () => {
212
- expect(isTestFile("src/__tests__/utils.ts")).toBe(true);
213
- expect(isTestFile("packages/foo/__tests__/Bar.tsx")).toBe(true);
214
- });
215
- it("returns false for ordinary source files", () => {
216
- expect(isTestFile("frontend/src/pages/Cart.tsx")).toBe(false);
217
- expect(isTestFile("frontend/src/components/Button.tsx")).toBe(false);
218
- expect(isTestFile("backend/src/handlers/orders.py")).toBe(false);
219
- });
220
- it("returns false for non-spec .ts files in tests/ directories that aren't Skyramp-generated", () => {
221
- // Tests/ directory alone doesn't trigger isTestFile — only the suffix matters.
222
- expect(isTestFile("frontend/tests/helpers/setup.ts")).toBe(false);
223
- });
224
- });
225
- // ---------------------------------------------------------------------------
226
- // buildScopeAssessmentSection
227
- // ---------------------------------------------------------------------------
228
- describe("buildScopeAssessmentSection", () => {
229
- it("produces a valid range in Step C for normal inputs (topN > maxGenerate)", () => {
230
- const section = buildScopeAssessmentSection(10, 3);
231
- // minTotal = min(3+1, 10) = 4; range should be "4–10"
232
- expect(section).toContain("4–10");
233
- expect(section).toContain("3 (generate) + 1 (min additional) = 4");
234
- });
235
- it("clamps minTotal to maxTotal when maxTotal === maxGenerate (regression: no inverted range)", () => {
236
- // Edge case from review: topN=4, maxGenerate=4 → minTotal must not exceed maxTotal
237
- const section = buildScopeAssessmentSection(4, 4);
238
- // minTotal = min(4+1, 4) = 4; range should be "4–4", NOT "5–4"
239
- expect(section).toContain("4–4");
240
- // minAdditional = 4 - 4 = 0; baseline should say "0 (min additional)"
241
- expect(section).toContain("4 (generate) + 0 (min additional) = 4");
242
- // Must NOT contain an inverted range
243
- expect(section).not.toMatch(/\b5–4\b/);
244
- });
245
- it("clamps minTotal to maxTotal when maxTotal < maxGenerate", () => {
246
- // Defensive: maxGenerate clamped to topN upstream, but guard applies here too
247
- const section = buildScopeAssessmentSection(3, 5);
248
- // effectiveGenerate = min(5, 3) = 3; minTotal = min(3+1, 3) = 3; range "3–3"
249
- expect(section).toContain("3–3");
250
- expect(section).not.toMatch(/\b[6-9]–3\b/);
251
- // Must not show original maxGenerate (5) in the formula
252
- expect(section).toContain("3 (generate)");
253
- expect(section).not.toContain("5 (generate)");
254
- });
255
- it("embeds UI/E2E confirmation step when isUIOnly=true", () => {
256
- const section = buildScopeAssessmentSection(10, 3, true);
257
- expect(section).toContain("frontend-only PR");
258
- expect(section).toContain("100% UI/E2E");
259
- expect(section).not.toContain("Step D — Determine UI vs backend split");
260
- });
261
- it("embeds UI vs backend split step when isUIOnly=false", () => {
262
- const section = buildScopeAssessmentSection(10, 3, false);
263
- expect(section).toContain("Step D — Determine UI vs backend split");
264
- expect(section).not.toContain("UI/E2E confirmation");
265
- });
266
- it("uses defaults matching MAX_RECOMMENDATIONS and MAX_TESTS_TO_GENERATE", () => {
267
- // Should not throw and should produce a non-empty string
268
- const section = buildScopeAssessmentSection();
269
- expect(section.length).toBeGreaterThan(0);
270
- expect(section).toContain("Budget Plan");
271
- });
272
- // ---------------------------------------------------------------------------
273
- // New branches added in PR 453 (4a) — precomputedUIPct / hasFrontendChanges
274
- // ---------------------------------------------------------------------------
275
- it("emits a single Budget Plan line for backend-only PR (precomputedUIPct=0)", () => {
276
- // isUIOnlyPR=false, hasFrontendChanges=false → precomputedUIPct=0
277
- const section = buildScopeAssessmentSection(10, 3, false, 0, false);
278
- expect(section).toContain("Budget Plan: 10 total (3 generate + 7 additional), 0% UI/E2E");
279
- expect(section).toContain("Use these exact numbers throughout the rest of the prompt.");
280
- // Must NOT include the step-based assessment
281
- expect(section).not.toContain("Step A");
282
- expect(section).not.toContain("Step B");
283
- expect(section).not.toContain("Step C");
284
- expect(section).not.toContain("Step D");
285
- });
286
- // ---------------------------------------------------------------------------
287
- // SKYR-3820 — zero-classified backend diff: budget defaults to 0
288
- // ---------------------------------------------------------------------------
289
- it("defaults the Budget Plan to 0 total when precomputedUIPct=0 and hasClassifiedApiChanges=false (SKYR-3820)", () => {
290
- const section = buildScopeAssessmentSection(20, 3, false, 0, false, false);
291
- expect(section).toContain("Budget Plan: 0 total");
292
- // The fixed budget mandate must NOT be asserted
293
- expect(section).not.toContain("Budget Plan: 20 total (3 generate + 17 additional)");
294
- expect(section).not.toContain("Use these exact numbers throughout the rest of the prompt.");
295
- // The conditional ceiling names the numbers the agent may claim after code review
296
- expect(section).toContain("up to 20 total (3 generate + 17 additional)");
297
- });
298
- it("keeps the fixed budget line when hasClassifiedApiChanges is omitted (back-compat default true)", () => {
299
- const withDefault = buildScopeAssessmentSection(10, 3, false, 0, false);
300
- const explicitTrue = buildScopeAssessmentSection(10, 3, false, 0, false, true);
301
- expect(withDefault).toBe(explicitTrue);
302
- expect(withDefault).toContain("Budget Plan: 10 total (3 generate + 7 additional), 0% UI/E2E");
303
- expect(withDefault).not.toContain("Budget Plan: 0 total");
304
- });
305
- it("does not apply the zero-classified override to UI-only PRs (precomputedUIPct=100)", () => {
306
- // UI-only PRs have hasApiChanges=false by construction — the override must be
307
- // gated on the backend branch (precomputedUIPct === 0) only.
308
- const section = buildScopeAssessmentSection(10, 3, true, 100, false, false);
309
- expect(section).toContain("Budget Plan: 10 total (3 generate + 7 additional), 100% UI/E2E");
310
- expect(section).not.toContain("Budget Plan: 0 total");
311
- });
312
- it("does not apply the zero-classified override to the mixed-PR branch", () => {
313
- const section = buildScopeAssessmentSection(10, 3, false, undefined, true, false);
314
- expect(section).toContain("Budget Plan (total already determined)");
315
- expect(section).toContain("Cosmetic-only override");
316
- expect(section).not.toContain("Budget Plan: 0 total");
317
- });
318
- it("emits a single Budget Plan line for UI-only PR (precomputedUIPct=100)", () => {
319
- const section = buildScopeAssessmentSection(10, 3, true, 100, false);
320
- expect(section).toContain("Budget Plan: 10 total (3 generate + 7 additional), 100% UI/E2E");
321
- expect(section).not.toContain("Step A");
322
- expect(section).not.toContain("Step D");
323
- });
324
- it("emits Step D only for mixed PR (hasFrontendChanges=true, precomputedUIPct=undefined)", () => {
325
- const section = buildScopeAssessmentSection(10, 3, false, undefined, true);
326
- // Total is pre-determined — shows in the Budget Plan header
327
- expect(section).toContain("Budget Plan (total already determined)");
328
- expect(section).toContain("10 total (3 generate + 7 additional)");
329
- // Step D is kept for UI/E2E split judgment
330
- expect(section).toContain("Step D");
331
- // The "Append your UI%" instruction must appear (comment #3222061560)
332
- expect(section).toContain("Append your UI%");
333
- // Steps A–C are skipped
334
- expect(section).not.toContain("Step A");
335
- expect(section).not.toContain("Step B");
336
- expect(section).not.toContain("Step C");
337
- });
338
- it("offers a cosmetic-only abstention override in the mixed-PR branch", () => {
339
- // Regression: a CSS-only diff classifies as frontend (hasFrontendChanges=true),
340
- // which previously handed the agent a fixed total with no path to zero tests,
341
- // tanking d1 coverage to 0 (eval 14-cart-css-cleanup).
342
- const section = buildScopeAssessmentSection(10, 3, false, undefined, true);
343
- expect(section).toContain("Cosmetic-only override");
344
- expect(section).toContain("0 total");
345
- // The override is self-contained: it must NOT depend on a "Task 3" that
346
- // doesn't exist in standalone (non-testbot) render contexts, and it must
347
- // tell the agent to skip the now-irrelevant UI% step.
348
- expect(section).not.toContain("Task 3");
349
- expect(section).toContain("skip Step D");
350
- });
351
- it("clamps additional to 0 when maxGenerate equals maxTotal (precomputed path)", () => {
352
- // maxGenerate=5, maxTotal=5 → additional must be 0, not negative
353
- const section = buildScopeAssessmentSection(5, 5, false, 0, false);
354
- expect(section).toContain("5 generate + 0 additional");
355
- expect(section).not.toMatch(/\d+ generate \+ -\d+ additional/);
356
- });
357
- it("clamps additional to 0 when maxGenerate exceeds maxTotal (defensive, precomputed path)", () => {
358
- // Should never happen in normal usage but guard must hold
359
- const section = buildScopeAssessmentSection(3, 5, false, 0, false);
360
- expect(section).toContain("3 generate + 0 additional");
361
- expect(section).not.toMatch(/\+ -\d+ additional/);
362
- // Must not show unclamped maxGenerate
363
- expect(section).not.toContain("5 generate");
364
- });
365
- it("clamps generate in mixed PR path when maxGenerate exceeds maxTotal", () => {
366
- const section = buildScopeAssessmentSection(3, 5, false, undefined, true);
367
- expect(section).toContain("3 generate + 0 additional");
368
- expect(section).not.toContain("5 generate");
369
- expect(section).not.toMatch(/\+ -\d+ additional/);
370
- });
371
- });