@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 +0,0 @@
1
- export {};
@@ -1,578 +0,0 @@
1
- // @ts-nocheck - Jest ESM type inference issues
2
- import { jest } from "@jest/globals";
3
- import { TestType } from "../types/TestTypes.js";
4
- import { AUTH_PLACEHOLDER_TOKEN } from "../types/TestTypes.js";
5
- import fs from "fs";
6
- import os from "os";
7
- import path from "path";
8
- // Mock @skyramp/skyramp before importing TestGenerationService to avoid
9
- // pulling in playwright (dynamic imports fail on Node 18 in CI). Under native
10
- // ESM, jest.mock is not hoisted — use unstable_mockModule + dynamic import.
11
- jest.unstable_mockModule("@skyramp/skyramp", () => ({
12
- SkyrampClient: jest.fn().mockImplementation(() => ({})),
13
- }));
14
- const { TestGenerationService, deriveEffectiveFramework } = await import("./TestGenerationService.js");
15
- const { SkyrampClient } = await import("@skyramp/skyramp");
16
- class StubService extends TestGenerationService {
17
- buildGenerationOptions() {
18
- return {};
19
- }
20
- getTestType() {
21
- return TestType.SMOKE;
22
- }
23
- validate(params) {
24
- return this.validateInputs(params);
25
- }
26
- }
27
- const BASE = {
28
- outputDir: "/tmp/tests",
29
- force: true,
30
- };
31
- function validateOutput(framework, output) {
32
- const svc = new StubService();
33
- return svc.validate({ ...BASE, framework, output });
34
- }
35
- function playwrightError(result) {
36
- for (const c of result.content) {
37
- if (c.type === "text" && c.text.includes("Playwright")) {
38
- return c.text;
39
- }
40
- }
41
- return undefined;
42
- }
43
- describe("TestGenerationService — Playwright filename validation", () => {
44
- it.each([
45
- "my_test.spec.ts",
46
- "my_test.test.ts",
47
- "my_test.spec.js",
48
- "my_test.test.js",
49
- ])("accepts valid Playwright filename: %s", (filename) => {
50
- const result = validateOutput("playwright", filename);
51
- expect(playwrightError(result)).toBeUndefined();
52
- });
53
- it.each([
54
- "my_test.ts",
55
- "my_test.py",
56
- "my_test.java",
57
- "tests",
58
- "my_test.js",
59
- ])("rejects invalid Playwright filename: %s", (filename) => {
60
- const result = validateOutput("playwright", filename);
61
- expect(playwrightError(result)).toBeDefined();
62
- expect(playwrightError(result)).toContain("Playwright requires");
63
- });
64
- it("suggests .spec.ts replacement for .ts file", () => {
65
- const err = playwrightError(validateOutput("playwright", "crud_items.ts"));
66
- expect(err).toContain("crud_items.spec.ts");
67
- });
68
- it("suggests .spec.ts replacement for .js file", () => {
69
- const err = playwrightError(validateOutput("playwright", "crud_items.js"));
70
- expect(err).toContain("crud_items.spec.ts");
71
- });
72
- it("appends .spec.ts for non-JS extension (e.g. .java)", () => {
73
- const err = playwrightError(validateOutput("playwright", "my_test.java"));
74
- expect(err).toContain("my_test.java.spec.ts");
75
- });
76
- it("appends .spec.ts for extensionless filename", () => {
77
- const err = playwrightError(validateOutput("playwright", "tests"));
78
- expect(err).toContain("tests.spec.ts");
79
- });
80
- it("skips validation when output is empty string", () => {
81
- expect(playwrightError(validateOutput("playwright", ""))).toBeUndefined();
82
- });
83
- it("skips validation for non-playwright frameworks", () => {
84
- expect(playwrightError(validateOutput("pytest", "my_test.py"))).toBeUndefined();
85
- });
86
- it("is case-insensitive on framework name", () => {
87
- expect(playwrightError(validateOutput("Playwright", "bad.ts"))).toBeDefined();
88
- });
89
- });
90
- describe("TestGenerationService — language/output extension consistency (SKYR-3899)", () => {
91
- function validateLangOutput(language, framework, output) {
92
- const svc = new StubService();
93
- return svc.validate({ ...BASE, language, framework, output });
94
- }
95
- function errorText(result) {
96
- for (const c of result.content) {
97
- if (c.type === "text")
98
- return c.text;
99
- }
100
- return undefined;
101
- }
102
- it("rejects TypeScript output written to a .py file with no explicit framework (the reported bug)", () => {
103
- // language typescript + no framework derives to playwright, so ui_test.py is
104
- // rejected instead of emitting TypeScript into a Python file.
105
- const result = validateLangOutput("typescript", "", "ui_test.py");
106
- expect(result.isError).toBe(true);
107
- expect(errorText(result)).toContain("Playwright requires");
108
- });
109
- it("accepts a TypeScript UI test named *.spec.ts with no explicit framework", () => {
110
- const result = validateLangOutput("typescript", "", "ui_test.spec.ts");
111
- expect(result.isError).toBe(false);
112
- });
113
- it("rejects a Python-language test written to a .ts file", () => {
114
- const result = validateLangOutput("python", "", "my_test.ts");
115
- expect(result.isError).toBe(true);
116
- expect(errorText(result)).toContain('language "python" requires a .py');
117
- expect(errorText(result)).toContain("my_test.py");
118
- });
119
- it("accepts a Python-language test written to a .py file", () => {
120
- const result = validateLangOutput("python", "", "my_test.py");
121
- expect(result.isError).toBe(false);
122
- });
123
- it("rejects a mismatched extension even when a non-playwright framework is explicit", () => {
124
- const result = validateLangOutput("typescript", "pytest", "foo.py");
125
- expect(result.isError).toBe(true);
126
- expect(errorText(result)).toContain('language "typescript" requires a .ts');
127
- });
128
- it("accepts a Python Playwright test (pytest-playwright) written to a .py file", () => {
129
- // Playwright supports Python via pytest-playwright — language: "python" +
130
- // framework: "playwright" must validate against .py, not the js/ts spec rule.
131
- const result = validateLangOutput("python", "playwright", "test_login.py");
132
- expect(result.isError).toBe(false);
133
- });
134
- it("rejects a Python Playwright test written to a .spec.ts file", () => {
135
- const result = validateLangOutput("python", "playwright", "foo.spec.ts");
136
- expect(result.isError).toBe(true);
137
- expect(errorText(result)).toContain('language "python" requires a .py');
138
- });
139
- });
140
- describe("deriveEffectiveFramework — validation/generation share one derivation (SKYR-3899)", () => {
141
- it("derives playwright for ts/js when framework is undefined", () => {
142
- expect(deriveEffectiveFramework("typescript", undefined)).toBe("playwright");
143
- expect(deriveEffectiveFramework("javascript", undefined)).toBe("playwright");
144
- });
145
- it("treats a blank/whitespace framework as unset (no drift vs undefined)", () => {
146
- // The empty-string edge the two call sites used to disagree on: validation
147
- // derived playwright while generation kept "". Both now agree.
148
- expect(deriveEffectiveFramework("typescript", "")).toBe("playwright");
149
- expect(deriveEffectiveFramework("typescript", " ")).toBe("playwright");
150
- });
151
- it("keeps an explicit framework and defaults non-js/ts to empty", () => {
152
- expect(deriveEffectiveFramework("typescript", "pytest")).toBe("pytest");
153
- expect(deriveEffectiveFramework("python", undefined)).toBe("");
154
- });
155
- });
156
- describe("TestGenerationService — authType/authScheme not passed to library", () => {
157
- let mockGenerateRestTest;
158
- beforeEach(() => {
159
- mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
160
- SkyrampClient.mockImplementation(() => ({
161
- generateRestTest: mockGenerateRestTest,
162
- }));
163
- });
164
- it("maps authScheme to authType for the npm client", async () => {
165
- const svc = new StubService();
166
- svc.buildGenerationOptions = () => ({
167
- authHeader: "Authorization",
168
- authScheme: "Token",
169
- authType: "Token",
170
- outputDir: "/tmp/tests",
171
- language: "python",
172
- framework: "pytest",
173
- });
174
- svc.handleApiAnalysis = async () => null;
175
- await svc.generateTest({ ...BASE });
176
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
177
- expect(callArgs.authType).toBe("Token");
178
- expect(callArgs.authScheme).toBeUndefined();
179
- // authHeader is cleared for Authorization when authType is set (CLI conflict fix)
180
- expect(callArgs.authHeader).toBeUndefined();
181
- });
182
- it("passes authHeader through to library without modification", async () => {
183
- const svc = new StubService();
184
- svc.buildGenerationOptions = () => ({
185
- authHeader: "X-Api-Key",
186
- outputDir: "/tmp/tests",
187
- language: "python",
188
- framework: "pytest",
189
- });
190
- svc.handleApiAnalysis = async () => null;
191
- await svc.generateTest({ ...BASE });
192
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
193
- expect(callArgs.authHeader).toBe("X-Api-Key");
194
- expect(callArgs.authType).toBeUndefined();
195
- expect(callArgs.authScheme).toBeUndefined();
196
- });
197
- });
198
- describe("TestGenerationService — extractAuthFromTrace", () => {
199
- let tmpDir;
200
- beforeEach(() => {
201
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-test-"));
202
- });
203
- afterEach(() => {
204
- fs.rmSync(tmpDir, { recursive: true, force: true });
205
- });
206
- function writeTrace(requests) {
207
- const filePath = path.join(tmpDir, "trace.json");
208
- fs.writeFileSync(filePath, JSON.stringify(requests), "utf8");
209
- return filePath;
210
- }
211
- function extract(filePath, include, exclude) {
212
- const svc = new StubService();
213
- return svc.extractAuthFromTrace(filePath, include, exclude);
214
- }
215
- it("extracts Authorization + Bearer scheme from trace", () => {
216
- const fp = writeTrace([
217
- {
218
- RequestHeaders: {
219
- "Content-Type": ["application/json"],
220
- Authorization: [`Bearer ${AUTH_PLACEHOLDER_TOKEN}`],
221
- },
222
- },
223
- ]);
224
- expect(extract(fp)).toEqual({
225
- authHeader: "Authorization",
226
- authScheme: "Bearer",
227
- });
228
- });
229
- it("extracts Authorization + Token scheme from trace", () => {
230
- const fp = writeTrace([
231
- {
232
- RequestHeaders: {
233
- "Content-Type": ["application/json"],
234
- Authorization: [`Token ${AUTH_PLACEHOLDER_TOKEN}`],
235
- },
236
- },
237
- ]);
238
- expect(extract(fp)).toEqual({
239
- authHeader: "Authorization",
240
- authScheme: "Token",
241
- });
242
- });
243
- it("extracts X-Api-Key with empty scheme from trace", () => {
244
- const fp = writeTrace([
245
- {
246
- RequestHeaders: {
247
- "Content-Type": ["application/json"],
248
- "X-Api-Key": [AUTH_PLACEHOLDER_TOKEN],
249
- },
250
- },
251
- ]);
252
- expect(extract(fp)).toEqual({
253
- authHeader: "X-Api-Key",
254
- authScheme: "",
255
- });
256
- });
257
- it("returns null when no auth header in trace", () => {
258
- const fp = writeTrace([
259
- {
260
- RequestHeaders: {
261
- "Content-Type": ["application/json"],
262
- },
263
- },
264
- ]);
265
- expect(extract(fp)).toBeNull();
266
- });
267
- it("returns null for invalid JSON", () => {
268
- const fp = path.join(tmpDir, "bad.json");
269
- fs.writeFileSync(fp, "not json", "utf8");
270
- expect(extract(fp)).toBeNull();
271
- });
272
- it("returns null for non-existent file", () => {
273
- expect(extract("/tmp/does-not-exist-xyz.json")).toBeNull();
274
- });
275
- it("skips Pragma header (standard HTTP/1.0 caching header, not auth)", () => {
276
- const fp = writeTrace([
277
- {
278
- RequestHeaders: {
279
- "Cache-Control": ["no-cache"],
280
- Pragma: ["no-cache"],
281
- "User-Agent": ["Mozilla/5.0"],
282
- },
283
- },
284
- ]);
285
- expect(extract(fp)).toBeNull();
286
- });
287
- it("skips Pragma and finds real auth header behind it", () => {
288
- const fp = writeTrace([
289
- {
290
- RequestHeaders: {
291
- "Cache-Control": ["no-cache"],
292
- Pragma: ["no-cache"],
293
- "User-Agent": ["Mozilla/5.0"],
294
- Authorization: [`Bearer ${AUTH_PLACEHOLDER_TOKEN}`],
295
- },
296
- },
297
- ]);
298
- expect(extract(fp)).toEqual({
299
- authHeader: "Authorization",
300
- authScheme: "Bearer",
301
- });
302
- });
303
- it("uses include filter to skip noise and find auth on matching requests", () => {
304
- const fp = writeTrace([
305
- {
306
- // requests[0]: unrelated traffic (e.g. Google time sync) with no auth
307
- Destination: "clients2.google.com",
308
- Path: "/time/1/current",
309
- RequestHeaders: {
310
- "Cache-Control": ["no-cache"],
311
- "User-Agent": ["Mozilla/5.0"],
312
- },
313
- },
314
- {
315
- // requests[1]: actual API request matching include filter
316
- Destination: "demoshop.skyramp.dev",
317
- Path: "/api/v1/products",
318
- RequestHeaders: {
319
- "Content-Type": ["application/json"],
320
- Authorization: [`Bearer ${AUTH_PLACEHOLDER_TOKEN}`],
321
- },
322
- },
323
- ]);
324
- expect(extract(fp, ["demoshop.skyramp.dev/api/*"])).toEqual({
325
- authHeader: "Authorization",
326
- authScheme: "Bearer",
327
- });
328
- });
329
- it("uses exclude filter to skip noise and find auth on remaining requests", () => {
330
- const fp = writeTrace([
331
- {
332
- Destination: "clients2.google.com",
333
- Path: "/time/1/current",
334
- RequestHeaders: {
335
- "Cache-Control": ["no-cache"],
336
- "User-Agent": ["Mozilla/5.0"],
337
- },
338
- },
339
- {
340
- Destination: "demoshop.skyramp.dev",
341
- Path: "/api/v1/products",
342
- RequestHeaders: {
343
- "Content-Type": ["application/json"],
344
- Authorization: [`Bearer ${AUTH_PLACEHOLDER_TOKEN}`],
345
- },
346
- },
347
- ]);
348
- expect(extract(fp, undefined, ["clients2.google.com/*"])).toEqual({
349
- authHeader: "Authorization",
350
- authScheme: "Bearer",
351
- });
352
- });
353
- it("prefers Authorization over Cookie even when Cookie appears first", () => {
354
- const fp = writeTrace([
355
- {
356
- RequestHeaders: {
357
- "Content-Type": ["application/json"],
358
- Cookie: ["cf_clearance=abc123; _dd_s=xyz"],
359
- Authorization: [`Bearer ${AUTH_PLACEHOLDER_TOKEN}`],
360
- },
361
- },
362
- ]);
363
- expect(extract(fp)).toEqual({
364
- authHeader: "Authorization",
365
- authScheme: "Bearer",
366
- });
367
- });
368
- it("falls back to known auth header (X-Api-Key) when no Authorization present", () => {
369
- const fp = writeTrace([
370
- {
371
- RequestHeaders: {
372
- "Content-Type": ["application/json"],
373
- "Sec-Fetch-Mode": ["cors"],
374
- "X-Api-Key": ["my-secret-key"],
375
- Traceparent: ["00-abc-def-01"],
376
- },
377
- },
378
- ]);
379
- expect(extract(fp)).toEqual({
380
- authHeader: "X-Api-Key",
381
- authScheme: "",
382
- });
383
- });
384
- it("skips standard headers like Accept", () => {
385
- const fp = writeTrace([
386
- {
387
- RequestHeaders: {
388
- "Content-Type": ["application/json"],
389
- Accept: ["application/json"],
390
- Authorization: [`Token ${AUTH_PLACEHOLDER_TOKEN}`],
391
- },
392
- },
393
- ]);
394
- expect(extract(fp)).toEqual({
395
- authHeader: "Authorization",
396
- authScheme: "Token",
397
- });
398
- });
399
- });
400
- describe("TestGenerationService — trace-based auth in executeGeneration", () => {
401
- let mockGenerateRestTest;
402
- let tmpDir;
403
- beforeEach(() => {
404
- mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
405
- SkyrampClient.mockImplementation(() => ({
406
- generateRestTest: mockGenerateRestTest,
407
- }));
408
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-test-"));
409
- });
410
- afterEach(() => {
411
- fs.rmSync(tmpDir, { recursive: true, force: true });
412
- });
413
- function writeTrace(requests) {
414
- const filePath = path.join(tmpDir, "trace.json");
415
- fs.writeFileSync(filePath, JSON.stringify(requests), "utf8");
416
- return filePath;
417
- }
418
- it("populates authScheme from trace when not provided (clears Authorization authHeader)", async () => {
419
- const traceFile = writeTrace([
420
- {
421
- RequestHeaders: {
422
- "Content-Type": ["application/json"],
423
- Authorization: [`Token ${AUTH_PLACEHOLDER_TOKEN}`],
424
- },
425
- },
426
- ]);
427
- const svc = new StubService();
428
- svc.buildGenerationOptions = () => ({
429
- traceFilePath: traceFile,
430
- authHeader: "",
431
- authScheme: "",
432
- outputDir: "/tmp/tests",
433
- language: "python",
434
- framework: "pytest",
435
- });
436
- svc.handleApiAnalysis = async () => null;
437
- await svc.generateTest({ ...BASE });
438
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
439
- // authHeader is cleared for Authorization when authType is set (CLI conflict fix)
440
- expect(callArgs.authHeader).toBeUndefined();
441
- expect(callArgs.authType).toBe("Token");
442
- expect(callArgs.authScheme).toBeUndefined();
443
- });
444
- it("populates X-Api-Key from trace with empty authScheme", async () => {
445
- const traceFile = writeTrace([
446
- {
447
- RequestHeaders: {
448
- "Content-Type": ["application/json"],
449
- "X-Api-Key": [AUTH_PLACEHOLDER_TOKEN],
450
- },
451
- },
452
- ]);
453
- const svc = new StubService();
454
- svc.buildGenerationOptions = () => ({
455
- traceFilePath: traceFile,
456
- authHeader: "",
457
- authScheme: "",
458
- outputDir: "/tmp/tests",
459
- language: "python",
460
- framework: "pytest",
461
- });
462
- svc.handleApiAnalysis = async () => null;
463
- await svc.generateTest({ ...BASE });
464
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
465
- expect(callArgs.authHeader).toBe("X-Api-Key");
466
- expect(callArgs.authType).toBe("");
467
- expect(callArgs.authScheme).toBeUndefined();
468
- });
469
- it("overrides conflicting authScheme with trace value and clears Authorization authHeader", async () => {
470
- const traceFile = writeTrace([
471
- {
472
- RequestHeaders: {
473
- "Content-Type": ["application/json"],
474
- Authorization: [`Token ${AUTH_PLACEHOLDER_TOKEN}`],
475
- },
476
- },
477
- ]);
478
- const svc = new StubService();
479
- svc.buildGenerationOptions = () => ({
480
- traceFilePath: traceFile,
481
- authHeader: "Authorization",
482
- authScheme: "Bearer",
483
- outputDir: "/tmp/tests",
484
- language: "python",
485
- framework: "pytest",
486
- });
487
- svc.handleApiAnalysis = async () => null;
488
- await svc.generateTest({ ...BASE });
489
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
490
- // authHeader is cleared for Authorization when authType is set (CLI conflict fix)
491
- expect(callArgs.authHeader).toBeUndefined();
492
- expect(callArgs.authType).toBe("Token");
493
- expect(callArgs.authScheme).toBeUndefined();
494
- });
495
- it("does not override auth when trace has no auth header (clears Authorization authHeader)", async () => {
496
- const traceFile = writeTrace([
497
- {
498
- RequestHeaders: {
499
- "Content-Type": ["application/json"],
500
- },
501
- },
502
- ]);
503
- const svc = new StubService();
504
- svc.buildGenerationOptions = () => ({
505
- traceFilePath: traceFile,
506
- authHeader: "Authorization",
507
- authScheme: "Bearer",
508
- outputDir: "/tmp/tests",
509
- language: "python",
510
- framework: "pytest",
511
- });
512
- svc.handleApiAnalysis = async () => null;
513
- await svc.generateTest({ ...BASE });
514
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
515
- // authHeader is cleared for Authorization when authType is set (CLI conflict fix)
516
- expect(callArgs.authHeader).toBeUndefined();
517
- expect(callArgs.authType).toBe("Bearer");
518
- expect(callArgs.authScheme).toBeUndefined();
519
- });
520
- });
521
- describe("TestGenerationService — workspace skipTLSVerify auto-resolve (SKYR-3961)", () => {
522
- let mockGenerateRestTest;
523
- let wsDir;
524
- beforeEach(() => {
525
- mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
526
- SkyrampClient.mockImplementation(() => ({
527
- generateRestTest: mockGenerateRestTest,
528
- }));
529
- wsDir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-ws-"));
530
- });
531
- afterEach(() => {
532
- fs.rmSync(wsDir, { recursive: true, force: true });
533
- });
534
- function writeWorkspace(api) {
535
- const dir = path.join(wsDir, ".skyramp");
536
- fs.mkdirSync(dir, { recursive: true });
537
- fs.writeFileSync(path.join(dir, "workspace.yml"), [
538
- "workspace:",
539
- " repoName: org/sut",
540
- "services:",
541
- " - serviceName: sut",
542
- " api:",
543
- ...Object.entries(api).map(([k, v]) => ` ${k}: ${v}`),
544
- ].join("\n"), "utf8");
545
- }
546
- it("sets insecure from workspace when the caller did not request it", async () => {
547
- writeWorkspace({ baseUrl: "https://127.0.0.1:45643", skipTLSVerify: true });
548
- const svc = new StubService();
549
- svc.buildGenerationOptions = () => ({
550
- authHeader: "",
551
- authScheme: "",
552
- outputDir: wsDir,
553
- language: "python",
554
- framework: "pytest",
555
- });
556
- svc.handleApiAnalysis = async () => null;
557
- await svc.generateTest({ ...BASE });
558
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
559
- // generateInsecure is the key SkyrampClient reads (buildBaseGenerationOptions
560
- // maps the tool param `insecure` onto it).
561
- expect(callArgs.generateInsecure).toBe(true);
562
- });
563
- it("leaves insecure unset when the workspace does not declare it", async () => {
564
- writeWorkspace({ baseUrl: "https://127.0.0.1:45643" });
565
- const svc = new StubService();
566
- svc.buildGenerationOptions = () => ({
567
- authHeader: "",
568
- authScheme: "",
569
- outputDir: wsDir,
570
- language: "python",
571
- framework: "pytest",
572
- });
573
- svc.handleApiAnalysis = async () => null;
574
- await svc.generateTest({ ...BASE });
575
- const callArgs = mockGenerateRestTest.mock.calls[0][0];
576
- expect(callArgs.generateInsecure).not.toBe(true);
577
- });
578
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,49 +0,0 @@
1
- import { TOOL_PHASE_MAP, TOOLS_WITHOUT_PHASE } from "./tool-phases.js";
2
- import * as fs from "fs";
3
- import * as path from "path";
4
- import { fileURLToPath } from "url";
5
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
- function findAllToolNames() {
7
- const toolNames = [];
8
- function walk(dir) {
9
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
10
- const full = path.join(dir, entry.name);
11
- if (entry.isDirectory()) {
12
- walk(full);
13
- continue;
14
- }
15
- if (!entry.name.endsWith(".ts"))
16
- continue;
17
- const content = fs.readFileSync(full, "utf-8");
18
- const matches = content.matchAll(/const TOOL_NAME\s*=\s*["']([^"']+)["']/g);
19
- for (const m of matches)
20
- toolNames.push(m[1]);
21
- }
22
- }
23
- walk(path.resolve(__dirname, "./tools"));
24
- return toolNames;
25
- }
26
- describe("tool-phase-coverage", () => {
27
- it("every registered tool has a phase or is explicitly excluded", () => {
28
- const allTools = findAllToolNames();
29
- expect(allTools.length).toBeGreaterThan(0);
30
- const missing = allTools.filter(name => !(name in TOOL_PHASE_MAP) && !TOOLS_WITHOUT_PHASE.has(name));
31
- if (missing.length > 0) {
32
- throw new Error(`These tools are not in TOOL_PHASE_MAP or TOOLS_WITHOUT_PHASE in src/tool-phases.ts:\n` +
33
- missing.map(n => ` - ${n}`).join("\n") +
34
- `\nAdd them to the appropriate export in src/tool-phases.ts`);
35
- }
36
- });
37
- it("TOOL_PHASE_MAP contains only valid phases", () => {
38
- const validPhases = new Set(["analyzing", "generating", "executing", "maintaining", "reporting"]);
39
- for (const [tool, mapping] of Object.entries(TOOL_PHASE_MAP)) {
40
- if (typeof mapping === "string") {
41
- expect(validPhases.has(mapping)).toBe(true);
42
- }
43
- else {
44
- expect(validPhases.has(mapping.before)).toBe(true);
45
- expect(validPhases.has(mapping.after)).toBe(true);
46
- }
47
- }
48
- });
49
- });
@@ -1 +0,0 @@
1
- export {};