@skyramp/mcp 0.4.1 → 0.4.2-rc.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 (583) hide show
  1. package/build/commands/localDevTestChangesCommand.js +2 -1
  2. package/build/commands/recommendTestsAndExecuteCommand.js +15 -7
  3. package/build/commands/testThisEndpointCommand.js +35 -6
  4. package/build/execution/wrapperConfig.d.ts +56 -0
  5. package/build/execution/wrapperConfig.js +155 -0
  6. package/build/index.js +40 -10
  7. package/build/playwright/blueprintDigest.js +28 -7
  8. package/build/playwright/registerPlaywrightTools.js +47 -28
  9. package/build/playwright/traceExportStore.d.ts +22 -0
  10. package/build/playwright/traceExportStore.js +81 -0
  11. package/build/playwright/traceRecordingPrompt.js +11 -3
  12. package/build/prompts/code-reuse.js +118 -49
  13. package/build/prompts/fix-error-prompt.d.ts +9 -1
  14. package/build/prompts/fix-error-prompt.js +31 -28
  15. package/build/prompts/local-dev/local-dev-plan.d.ts +3 -0
  16. package/build/prompts/local-dev/local-dev-plan.js +8 -23
  17. package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
  18. package/build/prompts/local-dev/local-dev-prompts.js +31 -4
  19. package/build/prompts/modularization/integration-test-modularization.js +13 -6
  20. package/build/prompts/modularization/ui-test-modularization.js +1 -1
  21. package/build/prompts/personas.js +1 -1
  22. package/build/prompts/pom-aware-code-reuse.js +7 -9
  23. package/build/prompts/reuse-hand-off.d.ts +64 -0
  24. package/build/prompts/reuse-hand-off.js +130 -0
  25. package/build/prompts/shared-helper-policy.d.ts +124 -2
  26. package/build/prompts/shared-helper-policy.js +178 -12
  27. package/build/prompts/startTraceCollectionPrompts.js +1 -1
  28. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +7 -8
  29. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +1 -1
  30. package/build/prompts/sut-setup/shared.d.ts +4 -1
  31. package/build/prompts/sut-setup/shared.js +6 -4
  32. package/build/prompts/test-maintenance/actionsInstructions.d.ts +19 -11
  33. package/build/prompts/test-maintenance/actionsInstructions.js +47 -26
  34. package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +16 -8
  35. package/build/prompts/test-maintenance/drift-analysis-prompt.js +93 -38
  36. package/build/prompts/test-maintenance/driftAnalysisSections.js +5 -3
  37. package/build/prompts/test-maintenance/driftAnalysisShared.js +4 -2
  38. package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +8 -5
  39. package/build/prompts/test-recommendation/recommendationSections.js +19 -8
  40. package/build/prompts/test-recommendation/recommendationShared.d.ts +1 -1
  41. package/build/prompts/test-recommendation/recommendationShared.js +0 -1
  42. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +5 -2
  43. package/build/prompts/test-recommendation/test-recommendation-prompt.js +10 -7
  44. package/build/prompts/testbot/testbot-prompts.js +133 -63
  45. package/build/recommendation/answers.js +18 -9
  46. package/build/recommendation/pullRequestText.js +1 -1
  47. package/build/recommendation/registerPlan.js +31 -17
  48. package/build/recommendation/subjectStep.d.ts +8 -10
  49. package/build/recommendation/subjectStep.js +17 -16
  50. package/build/recommendation/types.d.ts +71 -17
  51. package/build/recommendation/types.js +9 -15
  52. package/build/recommendation/verifierContracts.d.ts +7 -3
  53. package/build/recommendation/verifierContracts.js +8 -4
  54. package/build/recommendation/verifiers/changedFile.js +11 -13
  55. package/build/recommendation/verifiers/citedPath.d.ts +8 -0
  56. package/build/recommendation/verifiers/citedPath.js +16 -2
  57. package/build/recommendation/verifiers/coverage.d.ts +2 -2
  58. package/build/recommendation/verifiers/coverage.js +190 -134
  59. package/build/recommendation/verifiers/defects.js +56 -16
  60. package/build/recommendation/verifiers/deliveredMatchesPlan.d.ts +7 -1
  61. package/build/recommendation/verifiers/deliveredMatchesPlan.js +28 -14
  62. package/build/recommendation/verifiers/endpointGrounded.js +14 -8
  63. package/build/recommendation/verifiers/existingCoverage.d.ts +6 -0
  64. package/build/recommendation/verifiers/existingCoverage.js +30 -21
  65. package/build/recommendation/verifiers/expectedOutcome.js +17 -8
  66. package/build/recommendation/verifiers/expectedValueSourced.js +54 -43
  67. package/build/recommendation/verifiers/issueTraceability.d.ts +5 -0
  68. package/build/recommendation/verifiers/issueTraceability.js +64 -7
  69. package/build/recommendation/verifiers/removedElementGuarded.js +19 -11
  70. package/build/recommendation/verifiers/reportedCategory.js +9 -4
  71. package/build/recommendation/verifiers/requirementSourced.js +34 -21
  72. package/build/recommendation/verifiers/screenRoute.js +15 -10
  73. package/build/recommendation/verifiers/statedDifference.js +15 -8
  74. package/build/recommendation/verifiers/uiElementGrounded.js +50 -16
  75. package/build/resources/analysisResources.js +7 -3
  76. package/build/resources/progressResource.js +4 -2
  77. package/build/resources/sutSetupResource.js +20 -2
  78. package/build/resources/testbotResource.js +19 -1
  79. package/build/services/AnalyticsService.js +3 -1
  80. package/build/services/ScenarioGenerationService.js +5 -5
  81. package/build/services/TestDiscoveryService.js +53 -9
  82. package/build/services/TestExecutionService.js +63 -21
  83. package/build/services/TestGenerationService.d.ts +1 -1
  84. package/build/services/TestGenerationService.js +43 -24
  85. package/build/skills/enhanceAssertionsSkill.d.ts +45 -0
  86. package/build/skills/enhanceAssertionsSkill.js +103 -0
  87. package/build/skills/fixTestImportErrorsSkill.d.ts +2 -2
  88. package/build/skills/fixTestImportErrorsSkill.js +2 -2
  89. package/build/skills/runTestSkill.d.ts +6 -0
  90. package/build/skills/runTestSkill.js +17 -0
  91. package/build/skills/skillFiles.d.ts +38 -0
  92. package/build/skills/skillFiles.js +94 -0
  93. package/build/skills/validateAssertionAlignmentSkill.d.ts +34 -0
  94. package/build/skills/validateAssertionAlignmentSkill.js +59 -0
  95. package/build/tool-phases.js +4 -1
  96. package/build/tools/auth/loginTool.js +3 -1
  97. package/build/tools/auth/logoutTool.js +3 -1
  98. package/build/tools/budgetExcuse.d.ts +15 -0
  99. package/build/tools/budgetExcuse.js +113 -0
  100. package/build/tools/code-refactor/alignAssertionsTool.d.ts +2 -0
  101. package/build/tools/code-refactor/alignAssertionsTool.js +51 -0
  102. package/build/tools/code-refactor/assertion-state.d.ts +1 -1
  103. package/build/tools/code-refactor/assertion-state.js +1 -1
  104. package/build/tools/code-refactor/assertionOperations.d.ts +44 -0
  105. package/build/tools/code-refactor/assertionOperations.js +82 -0
  106. package/build/tools/code-refactor/assertionSkillTools.d.ts +3 -0
  107. package/build/tools/code-refactor/assertionSkillTools.js +86 -0
  108. package/build/tools/code-refactor/codeReuseTool.js +27 -3
  109. package/build/tools/code-refactor/enhanceAssertionsTool.js +19 -83
  110. package/build/tools/code-refactor/gate-markers.d.ts +51 -0
  111. package/build/tools/code-refactor/gate-markers.js +95 -0
  112. package/build/tools/code-refactor/retrofit-state.d.ts +3 -1
  113. package/build/tools/code-refactor/retrofit-state.js +44 -2
  114. package/build/tools/code-refactor/reuse-outcome.d.ts +23 -1
  115. package/build/tools/code-refactor/reuse-outcome.js +36 -13
  116. package/build/tools/code-refactor/reuse-state.d.ts +90 -16
  117. package/build/tools/code-refactor/reuse-state.js +191 -61
  118. package/build/tools/code-refactor/utils-verify-gates.d.ts +4 -0
  119. package/build/tools/code-refactor/utils-verify-gates.js +269 -30
  120. package/build/tools/code-refactor/verify-gates.d.ts +15 -1
  121. package/build/tools/code-refactor/verify-gates.js +36 -4
  122. package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
  123. package/build/tools/enrichTestWithMocksTool.js +9 -5
  124. package/build/tools/executeSkyrampTestTool.d.ts +118 -48
  125. package/build/tools/executeSkyrampTestTool.js +998 -372
  126. package/build/tools/execution-video-state.js +1 -1
  127. package/build/tools/fixErrorTool.js +5 -6
  128. package/build/tools/generate-tests/batchMockGenerationTool.js +1 -1
  129. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +114 -73
  130. package/build/tools/generate-tests/generateContractRestTool.js +34 -16
  131. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -0
  132. package/build/tools/generate-tests/generateE2ERestTool.js +9 -1
  133. package/build/tools/generate-tests/generateIntegrationRestTool.js +22 -7
  134. package/build/tools/generate-tests/generateMockRestTool.js +3 -1
  135. package/build/tools/generate-tests/generateUIRestTool.d.ts +2 -0
  136. package/build/tools/generate-tests/generateUIRestTool.js +11 -2
  137. package/build/tools/generate-tests/loadTestSchema.js +1 -3
  138. package/build/tools/generate-tests/planGuard.js +6 -3
  139. package/build/tools/generate-tests/scenarioFileIdentity.js +4 -1
  140. package/build/tools/generate-tests/scenarioLint.js +17 -5
  141. package/build/tools/generate-tests/trace-reuse-guard.js +5 -2
  142. package/build/tools/generateEnrichedIntegrationTestTool.js +9 -3
  143. package/build/tools/one-click/oneClickTool.js +3 -1
  144. package/build/tools/preflightMockCheckTool.js +23 -7
  145. package/build/tools/submitReportTool.d.ts +51 -12
  146. package/build/tools/submitReportTool.js +988 -161
  147. package/build/tools/test-management/actionsTool.js +241 -51
  148. package/build/tools/test-management/analyzeChangesTool.d.ts +8 -9
  149. package/build/tools/test-management/analyzeChangesTool.js +127 -68
  150. package/build/tools/test-management/analyzeTestHealthTool.d.ts +0 -11
  151. package/build/tools/test-management/analyzeTestHealthTool.js +42 -76
  152. package/build/tools/test-management/registerTestPlanTool.d.ts +44 -34
  153. package/build/tools/test-management/registerTestPlanTool.js +255 -111
  154. package/build/tools/test-management/resolveScreenTool.js +33 -9
  155. package/build/tools/test-management/testsOwedBeforeRun.d.ts +28 -0
  156. package/build/tools/test-management/testsOwedBeforeRun.js +53 -0
  157. package/build/tools/trace/startTraceCollectionTool.js +3 -1
  158. package/build/tools/trace/stopTraceCollectionTool.js +42 -6
  159. package/build/tools/verifyTestDependenciesTool.d.ts +3 -0
  160. package/build/tools/verifyTestDependenciesTool.js +54 -0
  161. package/build/tools/workspace/initScanWorkspaceTool.js +9 -3
  162. package/build/tools/workspace/initializeWorkspaceTool.js +3 -1
  163. package/build/types/AssertionOutcome.d.ts +1 -1
  164. package/build/types/EnhanceType.d.ts +6 -0
  165. package/build/types/EnhanceType.js +1 -0
  166. package/build/types/RepositoryAnalysis.d.ts +32 -72
  167. package/build/types/ReuseOutcome.d.ts +100 -7
  168. package/build/types/ReuseOutcome.js +16 -0
  169. package/build/types/StepMethod.js +20 -6
  170. package/build/types/TestAnalysis.d.ts +10 -2
  171. package/build/types/TestExecution.d.ts +45 -0
  172. package/build/types/TestRecommendation.d.ts +1 -1
  173. package/build/types/TestRecommendation.js +4 -1
  174. package/build/types/TestTypes.d.ts +16 -0
  175. package/build/types/TestTypes.js +40 -3
  176. package/build/types/TestbotPromptOptions.d.ts +9 -1
  177. package/build/types/TestbotReport.d.ts +45 -9
  178. package/build/utils/AnalysisStateManager.d.ts +137 -34
  179. package/build/utils/AnalysisStateManager.js +228 -44
  180. package/build/utils/assertion-verify/api-shared-lints.js +34 -16
  181. package/build/utils/assertion-verify/metrics.js +39 -6
  182. package/build/utils/assertion-verify/ui-lints.js +4 -2
  183. package/build/utils/branchDiff.js +47 -12
  184. package/build/utils/canonicalJson.js +3 -1
  185. package/build/utils/connectionErrors.d.ts +10 -0
  186. package/build/utils/connectionErrors.js +10 -0
  187. package/build/utils/dartRouteExtractor.js +36 -7
  188. package/build/utils/fixAttempts.d.ts +26 -0
  189. package/build/utils/fixAttempts.js +109 -0
  190. package/build/utils/frontendSelectors.js +23 -4
  191. package/build/utils/generatedTestRecord.d.ts +19 -0
  192. package/build/utils/generatedTestRecord.js +61 -0
  193. package/build/utils/gitStaging.js +7 -2
  194. package/build/utils/initAgent.js +26 -6
  195. package/build/utils/language-helper.js +60 -45
  196. package/build/utils/pathMatching.js +2 -1
  197. package/build/utils/pathSignatures.js +6 -2
  198. package/build/utils/planMatchKeys.d.ts +2 -2
  199. package/build/utils/planMatchKeys.js +20 -14
  200. package/build/utils/pom-catalog-parse.js +7 -2
  201. package/build/utils/pom-scope/import-expansion.js +6 -1
  202. package/build/utils/pom-scope/index.js +50 -12
  203. package/build/utils/pom-scope/scoring.js +13 -3
  204. package/build/utils/pom-scope/selector-extractor.js +16 -3
  205. package/build/utils/pom-scope/strip.d.ts +8 -0
  206. package/build/utils/pom-scope/strip.js +238 -0
  207. package/build/utils/pom-scope/testIdDiscovery.js +14 -2
  208. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.d.ts +1 -1
  209. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.js +4 -2
  210. package/build/utils/pom-verify/__fixtures__/af-style/report.iframe.page.js +3 -1
  211. package/build/utils/pom-verify/__fixtures__/af-style/workflow-footer.page.js +3 -1
  212. package/build/utils/pom-verify/bindings.js +5 -1
  213. package/build/utils/pom-verify/calls.js +9 -2
  214. package/build/utils/pom-verify/verify.js +27 -5
  215. package/build/utils/pr-comment-parser.js +20 -7
  216. package/build/utils/progress.d.ts +1 -1
  217. package/build/utils/progress.js +1 -1
  218. package/build/utils/proxy-terminal.d.ts +19 -1
  219. package/build/utils/proxy-terminal.js +346 -21
  220. package/build/utils/rebaselineSnapshots.d.ts +1 -1
  221. package/build/utils/rebaselineSnapshots.js +6 -16
  222. package/build/utils/removedUiElements.js +1 -1
  223. package/build/utils/reportLanguage.js +35 -7
  224. package/build/utils/reportVerification.d.ts +14 -8
  225. package/build/utils/reportVerification.js +19 -19
  226. package/build/utils/repositorySlug.d.ts +32 -0
  227. package/build/utils/repositorySlug.js +77 -0
  228. package/build/utils/reuseRouting.d.ts +10 -0
  229. package/build/utils/reuseRouting.js +21 -2
  230. package/build/utils/runContextGauge.d.ts +27 -0
  231. package/build/utils/runContextGauge.js +181 -0
  232. package/build/utils/runSerialized.d.ts +3 -0
  233. package/build/utils/runSerialized.js +39 -0
  234. package/build/utils/screenRoutes.js +74 -18
  235. package/build/utils/skyrampMdContent.d.ts +1 -1
  236. package/build/utils/skyrampMdContent.js +1 -1
  237. package/build/utils/skyrampSdkVersion.d.ts +9 -0
  238. package/build/utils/skyrampSdkVersion.js +16 -0
  239. package/build/utils/sourceRouteExtractor.js +13 -6
  240. package/build/utils/telemetry.d.ts +1 -0
  241. package/build/utils/telemetry.js +8 -5
  242. package/build/utils/testDependencyPolicy.d.ts +9 -0
  243. package/build/utils/testDependencyPolicy.js +809 -0
  244. package/build/utils/testExecutionRecord.d.ts +94 -0
  245. package/build/utils/testExecutionRecord.js +269 -0
  246. package/build/utils/testFileClassification.d.ts +8 -0
  247. package/build/utils/testFileClassification.js +39 -4
  248. package/build/utils/trace-parser.js +62 -14
  249. package/build/utils/urlPath.js +3 -1
  250. package/build/utils/utils-verify/action-key.d.ts +46 -0
  251. package/build/utils/utils-verify/action-key.js +120 -38
  252. package/build/utils/utils-verify/action-sites.d.ts +32 -0
  253. package/build/utils/utils-verify/action-sites.js +202 -0
  254. package/build/utils/utils-verify/allow.d.ts +122 -3
  255. package/build/utils/utils-verify/allow.js +146 -21
  256. package/build/utils/utils-verify/body-reach.d.ts +120 -0
  257. package/build/utils/utils-verify/body-reach.js +333 -0
  258. package/build/utils/utils-verify/call-sites.d.ts +31 -7
  259. package/build/utils/utils-verify/call-sites.js +80 -13
  260. package/build/utils/utils-verify/delivered-imports.d.ts +43 -0
  261. package/build/utils/utils-verify/delivered-imports.js +84 -0
  262. package/build/utils/utils-verify/fixed-sleep.d.ts +96 -0
  263. package/build/utils/utils-verify/fixed-sleep.js +461 -0
  264. package/build/utils/utils-verify/in-house.d.ts +93 -0
  265. package/build/utils/utils-verify/in-house.js +719 -0
  266. package/build/utils/utils-verify/incumbent.d.ts +3 -0
  267. package/build/utils/utils-verify/incumbent.js +75 -0
  268. package/build/utils/utils-verify/index.d.ts +2 -0
  269. package/build/utils/utils-verify/index.js +2 -0
  270. package/build/utils/utils-verify/language-spec.d.ts +51 -10
  271. package/build/utils/utils-verify/language-spec.js +232 -21
  272. package/build/utils/utils-verify/locate.d.ts +26 -0
  273. package/build/utils/utils-verify/locate.js +125 -23
  274. package/build/utils/utils-verify/module-name.d.ts +40 -0
  275. package/build/utils/utils-verify/module-name.js +98 -0
  276. package/build/utils/utils-verify/parse.d.ts +56 -7
  277. package/build/utils/utils-verify/parse.js +195 -40
  278. package/build/utils/utils-verify/retrofit-equivalence.d.ts +5 -0
  279. package/build/utils/utils-verify/retrofit-equivalence.js +4 -2
  280. package/build/utils/utils-verify/stage.d.ts +5 -0
  281. package/build/utils/utils-verify/stage.js +47 -2
  282. package/build/utils/utils-verify/status-once.d.ts +62 -0
  283. package/build/utils/utils-verify/status-once.js +207 -0
  284. package/build/utils/utils-verify/typecheck.d.ts +61 -0
  285. package/build/utils/utils-verify/typecheck.js +338 -0
  286. package/build/utils/utils-verify/verify.d.ts +79 -3
  287. package/build/utils/utils-verify/verify.js +531 -61
  288. package/build/utils/versions.d.ts +3 -3
  289. package/build/utils/versions.js +1 -1
  290. package/build/utils/workspaceAuth.js +107 -37
  291. package/build/workspace/queryParamResolution.js +11 -4
  292. package/build/workspace/workspace.d.ts +72 -52
  293. package/build/workspace/workspace.js +19 -15
  294. package/node_modules/playwright/ThirdPartyNotices.txt +19 -19
  295. package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +8 -2
  296. package/node_modules/playwright/lib/mcp/skyramp/common/cssValue.js +87 -0
  297. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -0
  298. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +3 -0
  299. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +181 -15
  300. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +24 -0
  301. package/node_modules/playwright/lib/transform/babelBundleImpl.js +2353 -190
  302. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +62 -34
  303. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.package-lock.json +72 -41
  304. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.js +1 -1
  305. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.mjs +1 -1
  306. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/package.json +2 -2
  307. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/README.md +16 -1
  308. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/index.js +4 -20
  309. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/read.js +17 -17
  310. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/json.js +60 -32
  311. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/raw.js +3 -3
  312. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/text.js +3 -3
  313. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/urlencoded.js +16 -20
  314. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/utils.js +18 -16
  315. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/LICENSE +22 -0
  316. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/README.md +71 -0
  317. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +46 -0
  318. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js +176 -0
  319. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -0
  320. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/package.json +52 -0
  321. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/package.json +23 -10
  322. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/CHANGELOG.md +21 -14
  323. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/isObject.d.ts +1 -1
  324. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/package.json +6 -7
  325. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/tsconfig.json +1 -0
  326. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/index.js +266 -45
  327. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/schemes.js +9 -4
  328. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/utils.js +396 -92
  329. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/package.json +1 -1
  330. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -0
  331. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/equal.test.js +31 -3
  332. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
  333. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
  334. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-validation.test.js +124 -0
  335. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
  336. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
  337. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/parse.test.js +7 -3
  338. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  339. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
  340. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
  341. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security-normalization.test.js +101 -0
  342. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security.test.js +301 -3
  343. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
  344. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
  345. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/CHANGELOG.md +7 -0
  346. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/index.d.ts +0 -1
  347. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/package.json +4 -5
  348. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/client.js +30 -16
  349. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/utils.js +4 -1
  350. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/context.js +32 -13
  351. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
  352. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
  353. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
  354. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/utils.js +30 -10
  355. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  356. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/hono-base.js +10 -8
  357. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/base.js +44 -23
  358. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/components.js +25 -26
  359. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/context.js +5 -5
  360. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
  361. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/server.js +5 -1
  362. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/hooks/index.js +16 -13
  363. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/intrinsic-element/components.js +3 -3
  364. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/streaming.js +4 -5
  365. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cache/index.js +103 -8
  366. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/compress/index.js +5 -0
  367. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cors/index.js +17 -14
  368. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/csrf/index.js +1 -1
  369. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/digest.js +47 -1
  370. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/index.js +7 -4
  371. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +9 -4
  372. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +9 -4
  373. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
  374. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +90 -0
  375. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +3 -1
  376. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +16 -7
  377. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/request.js +20 -13
  378. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/linear-router/router.js +7 -2
  379. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/pattern-router/router.js +3 -9
  380. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +65 -59
  381. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +71 -128
  382. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +14 -5
  383. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/node.js +47 -70
  384. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/router.js +3 -11
  385. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/utils.js +27 -0
  386. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router.js +1 -1
  387. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  388. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/body.js +21 -3
  389. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/cookie.js +4 -3
  390. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/ipaddr.js +5 -3
  391. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/stream.js +12 -3
  392. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/url.js +19 -11
  393. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/client.js +30 -16
  394. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/utils.js +4 -1
  395. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/context.js +32 -13
  396. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
  397. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/proxy/index.js +4 -0
  398. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
  399. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/utils.js +30 -10
  400. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  401. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/hono-base.js +10 -8
  402. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/base.js +41 -23
  403. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/components.js +26 -27
  404. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/context.js +6 -6
  405. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/render.js +2 -0
  406. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/server.js +5 -1
  407. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/hooks/index.js +16 -13
  408. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/intrinsic-element/components.js +4 -4
  409. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/streaming.js +5 -6
  410. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cache/index.js +103 -8
  411. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/compress/index.js +5 -0
  412. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cors/index.js +17 -14
  413. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/csrf/index.js +1 -1
  414. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/digest.js +47 -1
  415. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/index.js +7 -4
  416. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwk/jwk.js +9 -4
  417. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwt/jwt.js +9 -4
  418. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/language/language.js +10 -6
  419. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/method-not-allowed/index.js +68 -0
  420. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/pretty-json/index.js +3 -1
  421. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +16 -7
  422. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/request.js +21 -14
  423. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/linear-router/router.js +7 -2
  424. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/pattern-router/router.js +3 -9
  425. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/node.js +61 -58
  426. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/router.js +77 -129
  427. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/trie.js +14 -5
  428. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/node.js +47 -70
  429. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/router.js +3 -11
  430. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/utils.js +5 -0
  431. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router.js +1 -1
  432. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  433. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/client/types.d.ts +1 -1
  434. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/context.d.ts +6 -2
  435. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/hono-base.d.ts +4 -3
  436. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/base.d.ts +7 -2
  437. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/index.d.ts +5 -5
  438. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
  439. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/server.d.ts +5 -5
  440. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/hooks/index.d.ts +8 -6
  441. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/index.d.ts +5 -5
  442. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cache/index.d.ts +6 -4
  443. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  444. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cors/index.d.ts +1 -1
  445. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
  446. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +2 -0
  447. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +2 -0
  448. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
  449. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/secure-headers/permissions-policy.d.ts +3 -3
  450. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +4 -1
  451. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +2 -1
  452. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/node.d.ts +1 -2
  453. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/router.d.ts +0 -1
  454. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/utils.d.ts +1 -0
  455. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router.d.ts +1 -1
  456. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/headers.d.ts +2 -2
  457. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/url.d.ts +5 -0
  458. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/accept.js +1 -1
  459. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/body.js +21 -3
  460. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/cookie.js +5 -4
  461. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/ipaddr.js +5 -3
  462. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/stream.js +12 -3
  463. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/url.js +17 -10
  464. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/package.json +11 -4
  465. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/README.md +173 -143
  466. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.d.ts +11 -0
  467. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.js.map +1 -1
  468. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.d.ts +49 -0
  469. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js +79 -4
  470. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js.map +1 -1
  471. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  472. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js +119 -24
  473. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js.map +1 -1
  474. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  475. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js +316 -90
  476. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js.map +1 -1
  477. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  478. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js +45 -2
  479. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  480. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  481. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js +50 -3
  482. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  483. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/package.json +6 -4
  484. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  485. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/CHANGELOG.md +26 -0
  486. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/README.md +19 -1
  487. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/dist/qs.js +25 -25
  488. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/eslint.config.mjs +1 -1
  489. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/parse.js +16 -6
  490. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/stringify.js +23 -8
  491. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/utils.js +57 -11
  492. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/package.json +8 -7
  493. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/parse.js +419 -0
  494. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/stringify.js +317 -0
  495. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/utils.js +206 -0
  496. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/CHANGELOG.md +10 -0
  497. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/README.md +1 -1
  498. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/index.js +5 -2
  499. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/package.json +10 -10
  500. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/test/index.js +16 -0
  501. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/index.js +8 -18
  502. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/LICENSE +22 -0
  503. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/README.md +71 -0
  504. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.d.ts +46 -0
  505. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js +176 -0
  506. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -0
  507. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/package.json +52 -0
  508. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/package.json +9 -5
  509. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/package-lock.json +72 -41
  510. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.package-lock.json +6 -6
  511. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/README.md +23 -1
  512. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/index.js +265 -86
  513. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/package.json +1 -1
  514. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/README.md +173 -143
  515. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.d.ts +11 -0
  516. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.js.map +1 -1
  517. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.d.ts +49 -0
  518. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js +79 -4
  519. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js.map +1 -1
  520. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  521. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js +119 -24
  522. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js.map +1 -1
  523. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  524. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js +316 -90
  525. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js.map +1 -1
  526. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  527. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js +45 -2
  528. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  529. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  530. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js +50 -3
  531. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  532. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/package.json +6 -4
  533. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/package-lock.json +6 -6
  534. package/node_modules/playwright/node_modules/playwright-core/lib/cli/program.js +18 -9
  535. package/node_modules/playwright/node_modules/playwright-core/lib/mcpBundleImpl/index.js +47 -47
  536. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +3 -0
  537. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +42 -0
  538. package/node_modules/playwright/node_modules/playwright-core/lib/utilsBundleImpl/index.js +121 -121
  539. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.B7KbSQcC.js → index.BAkLd5DX.js} +1 -1
  540. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
  541. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  542. package/node_modules/playwright/node_modules/playwright-core/src/cli/program.ts +31 -9
  543. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -0
  544. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderRunner.ts +57 -1
  545. package/node_modules/playwright/package.json +2 -2
  546. package/package.json +7 -6
  547. package/plugin/prompts/code-reuse/hand-off.md +30 -0
  548. package/plugin/prompts/generate-tests/generation.md +1 -1
  549. package/plugin/prompts/plan-tests.md +14 -14
  550. package/plugin/prompts/testbot-task1.md +2 -2
  551. package/plugin/skills/enhance-assertions/SKILL.md +25 -0
  552. package/plugin/skills/enhance-assertions/reference/contract.md +51 -0
  553. package/plugin/skills/enhance-assertions/reference/integration.md +58 -0
  554. package/plugin/skills/enhance-assertions/reference/shared-rules.md +220 -0
  555. package/plugin/skills/enhance-assertions/reference/ui.md +373 -0
  556. package/plugin/skills/fix-test-import-errors/SKILL.md +45 -50
  557. package/plugin/skills/run-test/SKILL.md +16 -0
  558. package/plugin/skills/validate-assertion-alignment-post-execution/SKILL.md +32 -0
  559. package/plugin/skills/validate-assertion-alignment-post-execution/reference/checks.md +44 -0
  560. package/plugin/skills/validate-assertion-alignment-post-execution/reference/evidence.md +47 -0
  561. package/build/adapters/jestAdapter.d.ts +0 -14
  562. package/build/adapters/jestAdapter.js +0 -113
  563. package/build/adapters/mochaAdapter.d.ts +0 -13
  564. package/build/adapters/mochaAdapter.js +0 -87
  565. package/build/adapters/playwrightAdapter.d.ts +0 -17
  566. package/build/adapters/playwrightAdapter.js +0 -182
  567. package/build/adapters/pytestAdapter.d.ts +0 -15
  568. package/build/adapters/pytestAdapter.js +0 -108
  569. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +0 -2
  570. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.js +0 -29
  571. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +0 -2
  572. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.js +0 -36
  573. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +0 -16
  574. package/build/prompts/enhance-assertions/sharedAssertionRules.js +0 -284
  575. package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +0 -2
  576. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +0 -388
  577. package/build/tools/runExistingTestsTool.d.ts +0 -138
  578. package/build/tools/runExistingTestsTool.js +0 -644
  579. package/build/types/ExternalTestExecution.d.ts +0 -67
  580. package/build/types/ExternalTestExecution.js +0 -8
  581. package/build/workspace/testSuites.d.ts +0 -20
  582. package/build/workspace/testSuites.js +0 -17
  583. package/node_modules/playwright/node_modules/playwright-core/.DS_Store +0 -0
@@ -0,0 +1,220 @@
1
+ # Shared assertion rules
2
+
3
+ Read this file first for `contract` and `integration` tests. For `ui` tests only the "Scope by mode" section below applies; the UI rule set in `reference/ui.md` replaces the rest.
4
+
5
+ ## What to assert
6
+
7
+ Each test evaluates ONE behaviour — the one the recommendation it came from asked for. Assert that behaviour, and the values it depends on, exactly. Leave the rest of the response alone.
8
+
9
+ A field belongs in the test when a wrong value in it would mean the behaviour is broken. A field does not belong when its value can change for reasons that have nothing to do with the behaviour — a generated id, a timestamp, an unrelated sibling field. Asserting those does not make the test stronger. It makes the test fail for reasons the test is not about, and it buries the one assertion a reader needs to understand what the test is for.
10
+
11
+ So the rules below say how to assert a value, not how many values to assert. Apply a rule to the fields the behaviour depends on. `[]` is the correct answer for a rule whose fields this test does not depend on.
12
+
13
+ If nothing in the response distinguishes the behaviour working from the behaviour broken, the test is exercising the wrong request or reading the wrong response. Say so; do not pad it with assertions on whatever else the body carries.
14
+
15
+ ## Scope by mode
16
+
17
+ ### When enhancing a freshly generated test (`$1` = `generation`)
18
+
19
+ Apply the rules to every test function in `$2`.
20
+
21
+ ### When maintaining an existing test (`$1` = `maintenance`)
22
+
23
+ Apply only to new test functions you are adding and existing test functions affected by changes in the diff. Do NOT modify test functions unrelated to the diff. A test function you do touch is held to the same standard as a new one: the behaviour the diff changed must be asserted by its exact value there too, so an existing `is not None` on a field the diff gives a knowable value becomes that value.
24
+
25
+ ## Pre-Edit Assertion Analysis
26
+
27
+ Before editing `$2`, you must output a `<thinking>` block. It states the behaviour each test evaluates, then works through the rules for the responses that behaviour depends on, so no rule that applies is overlooked. The JSON array must match the `rule_checklist` template that accompanies the `$0` rules. Use the template's keys verbatim; each key is the slug shown in that rule's heading. Every key must appear — `[]` where the rule does not apply.
28
+
29
+ 1. For each test function in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from. A generated test function may carry a name that states its behaviour — trust that name when it does. A function still named `test_integration` or `testUi` claims nothing, so use the name only when it is specific enough to add something, and never treat a generic one as evidence the test has no single behaviour. Then scan `$2` and the expected responses for the code change tested.
30
+ 2. Classify each response first by its response status type and then assign the applicable assertion rules to the response.
31
+ - Success with body (2xx with a response body): all assertion rules below may apply — echo-back of request fields, computed response fields, array / items validation, and chained values across steps.
32
+ - Success with no body (200/202/204 with an empty body — e.g. logout/cancel/submit action endpoints): assert the status code only. Also apply chained-values rules if a follow-up step uses this response's ID.
33
+ - Error response (the status is not 2xx, or the body is an error object such as `{"error": "..."}` with no resource payload): assert that the request was refused, as the Error path rule below states. Read the record back unchanged where the flow allows. Assert the exact status code or the exact error text only when a source states it. Where a source does state the wording, apply array / items validation to the `errors[]` array (exact length + per-item fields + next index null).
34
+ 3. For each in-scope response, output one JSON object using that `rule_checklist` template. The output is an array — one object per in-scope response.
35
+ Classify by the response the recorded trace or `expected_response_body` shows this request returning. The one exception is a test the plan declared `expected.outcome: fail` (typically a `bug_caught` or `requirement_conflict` candidate; read the declaration first and fall back to the category only when none was made): there the expected response is the intended behaviour established by the diff, the PR statement, or the code's evident intent, and the test is expected to fail until the code is fixed.
36
+ - `step`: the HTTP method, path, and response variable name for this request (e.g. `POST /products → products_POST_response`).
37
+ - `response_status`: one of `success`, `no_body`, or `error` based on the classification in step 2.
38
+ - `behaviour_under_test`: the one-line behaviour from step 1 that this response is evidence for. When a response is evidence for no behaviour any test in scope claims, write `none` and add nothing for it.
39
+ - `rule_checklist`: an object that MUST contain every rule title — every title in the shared rules plus every title in the `$0` rules — as a key. For each rule, the value is the assertion lines you will add for this response under that rule. `[]` means the rule does not apply here, which is a normal and expected answer: it is the right one whenever the rule's fields are not part of `behaviour_under_test`. Listing every key keeps a rule that DOES apply from being skipped; it is not a quota to fill.
40
+
41
+ ## SDK Helpers
42
+
43
+ Access response body fields via the SDK helper already imported in the generated file (never dict/attribute access on the response variable): Python `skyramp.get_response_value(response, "json.path")`; TypeScript / JavaScript `getValue(response, "json.path")` or `getResponseValue(response, "json.path")` from `@skyramp/skyramp`; Java `getValue(response, "json.path")`.
44
+
45
+ ## Assertion Rules with Examples
46
+
47
+ ### Assert the behaviour under test (`behaviour-under-test`)
48
+
49
+ Every test needs at least one assertion that fails when the behaviour it claims is broken. This is the rule the others support; a test that satisfies every rule below and still does not distinguish the behaviour working from the behaviour broken has not been enhanced.
50
+
51
+ - Name the behaviour, then ask what value in the response changes when it breaks. Assert that value exactly.
52
+ - When the test claims a state change ("Updates X", "Increments Y", "rejects Z"), the assertion must prove the change, not merely that the call succeeded.
53
+ - When the PR changed the behaviour, the expected value is the one the diff, the PR description, or the referenced spec establishes — even when the running service still returns the old value. The test is expected to fail until the code is fixed.
54
+
55
+ ```javascript
56
+ // "PATCH /orders applies the coupon discount" — the discount is the behaviour.
57
+ expect(getResponseValue(patchResponse, "discount_amount"), 'discount applied').toBe(20);
58
+ expect(getResponseValue(patchResponse, "total_amount"), 'total after discount').toBe(80);
59
+ ```
60
+
61
+ ### Echo-back the request fields (`req-fields-echo-back`)
62
+
63
+ For every field returned unchanged from the request body, assert the exact sent value.
64
+
65
+ - `is not None` / `not.toBeNull()` is only acceptable when the value is genuinely unknown — for server-generated timestamps or opaque IDs. This rule does not apply to computed fields.
66
+ - When a response field's value equals the value sent in the request body, path, or query, assert that exact value rather than a null-check — the sent value is known and reproducible.
67
+ - Assert the exact value of a response-only field when the request this test sends determines it (`filename_download`, `content_type`, `size`, an enum status after creation). When the behaviour is that a resource was created with the fields sent, the id alone does not prove it — assert those fields.
68
+ - Range matchers like `toBeGreaterThanOrEqual(0)` and type-only checks like `typeof X === 'number'` are not acceptable for fields whose exact values are known.
69
+ - On a SUCCESSFUL response, assert the exact status code from the recorded trace or `expected_response_body` — for example, `201` for resource-creation endpoints. (A refused request is judged by the Error path rule below, which does not pin today's code.) Action-style endpoints with verb path segments like `/run`, `/trigger`, `/execute`, `/deploy`, `/submit`, `/start`, `/stop`, or `/cancel` often use `200`, but assert the recorded or expected code. Permissive status matchers are never acceptable.
70
+
71
+ ```javascript
72
+ expect(getValue(response, "data.filename_download")).toBe("invoice.pdf");
73
+ expect(getValue(response, "data.type")).toBe("application/pdf");
74
+ expect(response.statusCode).toBe(201);
75
+ ```
76
+
77
+ ```javascript
78
+ expect(getResponseValue(productsPostResponse, "name"), 'name').toBe("Skyramp Tester");
79
+ ```
80
+
81
+ ### Error path (HTTP 4xx/5xx, or a 2xx carrying only an error body) (`error-path`)
82
+
83
+ A request is refused when the status is not 2xx, or when the body is an error object (`error`, `message`, `errors[]`) and the resource fields carry no value. Assert the refusal: assert that the body carries the error field, and that the resource fields carry no value. Read the record back and assert it is unchanged, where the flow allows. Assert the exact status code or the exact error text only when a source states it — the plan's test case, the pull request, or a requirements file.
84
+
85
+ - Where a source states the wording, also apply the array-validation rule to the errors array.
86
+ - For a response with no body — a successful DELETE (204), or a refusal that returns nothing — assert the status code only. The status is the only evidence such a response carries, so assert it exactly even when no source states it.
87
+ - For a 2xx error body, assert that the error field is present and that the resource fields carry no value (`toBeNull()` / `is None` — the SDK helper reads a missing path and an explicit null the same way, so this asserts "no payload", not "key absent"; use `checkSchema` when the two must be told apart). Assert the exact status code and the error field's exact value only when a source states them. Never assert the success shape (a non-empty collection, `error` absent) against a response the recorded trace or `expected_response_body` shows returning an error or no-match body — classify the response by what this request returns, not by the outcome the test was meant to check for. The one exception is a test the plan declared `expected.outcome: fail` (typically a `bug_caught` or `requirement_conflict` candidate; the category is only the fallback when nothing was declared): it asserts the intended behaviour established by the diff, the PR statement, or the code's evident intent — keep that assertion and let the test fail.
88
+
89
+ ```javascript
90
+ // No source states the code or the wording, so neither is pinned
91
+ expect(getValue(response, "errors.0.message")).not.toBeNull();
92
+ expect(getValue(response, "data")).toBeNull();
93
+ expect(getValue(itemGetResponse, "data.name")).toBe("Wireless keyboard");
94
+ ```
95
+
96
+ ```javascript
97
+ // The plan's test case states 400 and the message
98
+ expect(recordPostResponse.statusCode, 'status code').toBe(400);
99
+ expect(getResponseValue(recordPostResponse, "error"), 'error').toBe("level must be one of Intern, Junior, Senior");
100
+ expect(getResponseValue(recordPostResponse, "insertedId"), 'insertedId carries no value').toBeNull();
101
+ ```
102
+
103
+ ```python
104
+ # A 2xx error body. The pull request states the wording; no source states the code.
105
+ assert skyramp.get_response_value(search_post_response, "error") == "No items matched the criteria."
106
+ assert skyramp.get_response_value(search_post_response, "results") is None
107
+ ```
108
+
109
+ ### Specific known values (`known-values`)
110
+
111
+ For enum or status fields where only one outcome is valid for this flow, assert the exact expected value.
112
+
113
+ - When the OpenAPI schema defines allowed values, assert the schema-defined value.
114
+ - Also assert cross-field invariants when one field encodes the count or summary of another (e.g. `total_count == results.length`).
115
+
116
+ ```javascript
117
+ expect(getResponseValue(ordersPostResponse, "status"), 'status').toBe("pending");
118
+ ```
119
+
120
+ ### Array / Items validation (`array-items`)
121
+
122
+ Only assert indices that exist in the recorded response — never infer array length from the request or scenario name.
123
+
124
+ - When the response is an empty array: assert the length is 0 and that the first index is absent. Never assert a field on index 0 of an empty array.
125
+ - When the response is a non-empty array: assert the exact length, key fields on each item, and that the index after the last item is absent.
126
+ - Shape-only checks such as `Array.isArray` or `typeof` are not sufficient when the response contains actual values.
127
+ - If the response is sorted or ordered: assert the ordering direction across the first two items.
128
+ - When the response is an empty or minimal body (an empty object, empty array, null, or only a few keys): assert the empty or minimal shape and the absence of error fields — do not stop at the status code. A minimal body that is itself an error object falls under the Error path rule instead.
129
+ - When the request includes pagination or filter parameters, assert the response reflects them.
130
+
131
+ ```javascript
132
+ expect(getResponseValue(patchResponse, "items.0.product_id")).toBe(getResponseValue(productPostResponse, "id"));
133
+ expect(getResponseValue(patchResponse, "items.0.quantity")).toBe(2);
134
+ expect(getResponseValue(patchResponse, "items.1.product_id")).toBeNull();
135
+ expect(getValue(response, "data").length).toBeLessThanOrEqual(10); // request sent limit=10
136
+ ```
137
+
138
+ ```javascript
139
+ expect(getValue(response, "results").length).toBe(2);
140
+ expect(getValue(response, "results.0.id")).toBe("prod_001");
141
+ expect(getValue(response, "results.2")).toBeNull();
142
+ ```
143
+
144
+ ```javascript
145
+ expect(getValue(response, "data").length).toBe(0);
146
+ expect(getValue(response, "data.0")).toBeNull();
147
+ ```
148
+
149
+ ### Fields whose value varies across runs (`varying-values`)
150
+
151
+ For a field whose exact value varies across runs — an ISO timestamp, an IP address, an email, a URL, or a number with no knowable exact value — assert its format or its range instead of its value, and only when the behaviour under test depends on that field.
152
+
153
+ - ISO timestamp matches `/^\d{4}-\d{2}-\d{2}T/`.
154
+ - IP address matches IPv4 or IPv6 format.
155
+ - Email contains `@` and a domain.
156
+ - URL starts with `http://` or `https://`.
157
+ - Use format info from the OpenAPI schema (`format: date-time`) to identify these fields.
158
+ - A numeric field with no knowable exact value takes a range from the field name, the domain, or the OpenAPI `minimum` / `maximum` — a range is the weakest assertion in this rule set, so use it only where no exact value exists and the behaviour depends on the field.
159
+
160
+ ```javascript
161
+ expect(getResponseValue(productsPostResponse, "created_at")).toMatch(/^\d{4}-\d{2}-\d{2}T/);
162
+ ```
163
+
164
+ ### Use exact recorded JSON paths (`exact-json-paths`)
165
+
166
+ Read every field at the path the recorded body actually uses. A wrapper prefix the response does not have makes the assertion read null and the test fail for a reason that is not the behaviour — if the body is flat (`{"id": "acc_...", "tax_exempt": true}`), the path is `"tax_exempt"`, never `"account.tax_exempt"`.
167
+
168
+ ```javascript
169
+ expect(getResponseValue(accountResponse, "tax_exempt")).toBe(true);
170
+ ```
171
+
172
+ ### Computed response fields, derived using dynamic formulas (`computed-fields`)
173
+
174
+ When the response contains a field whose value is derived from a calculation, assert the result using a formula built from prior response values and request inputs, not a hardcoded literal.
175
+
176
+ - Use a dynamic formula when the formula is visible in source.
177
+ - Fall back to the exact pre-computed value from `expected_response_body` only when no formula is knowable — all inputs must come from the inline request body or the response.
178
+
179
+ ```javascript
180
+ expect(getResponseValue(patchResponse, "discount_amount")).toBe(getResponseValue(patchResponse, "total_amount") * (getResponseValue(patchResponse, "discount_value") / 100));
181
+ ```
182
+
183
+ ```javascript
184
+ expect(getResponseValue(patchResponse, "total_amount")).toBe(getResponseValue(productPostResponse, "price") * quantitySent);
185
+ ```
186
+
187
+ ### Assert a nullable field is present, not merely null (`nullable-present`)
188
+
189
+ Reading a field's value cannot tell a null field from a missing one — `get_response_value` / `getValue` return the same result for both, so `is None` does not prove the field exists. Use a schema check with an example body instead.
190
+
191
+ - An example carrying `null` for the field asserts presence and nullness together, and fails when the field is absent.
192
+ - An example carrying a concrete value only asserts that value's type, so a nullable field checked against a string example fails once the real value is null.
193
+ - `check_schema` / `checkSchema` takes the RESPONSE OBJECT, not a parsed body. The `@skyramp/skyramp` type declaration says otherwise and is wrong — passing a plain object makes every check silently return false (SKYR-4189).
194
+
195
+ ```python
196
+ assert skyramp.check_schema(order_response, '{"cancelled_at": null}')
197
+ ```
198
+
199
+ ```javascript
200
+ expect(checkSchema(orderResponse, '{"cancelled_at": null}')).toBe(true);
201
+ ```
202
+
203
+ ## What not to do
204
+
205
+ - Do not access response fields via dict syntax (`response["field"]`) or attribute access (`response.field`) — always use the SDK helper.
206
+ - Do not assert `not.toBeNull()` / `is not None` on a field whose exact value is in the request body or a prior response.
207
+ - Do not assert an exact value you learned only from a request you sent yourself while writing the test. Take the value from the diff, from what the request determines, or from a response this test received earlier.
208
+ - Do not assert a field only because the body carries it. If a wrong value there would not mean the behaviour under test is broken, leave it alone.
209
+ - Do not leave a test whose assertions would all still pass with the behaviour under test broken.
210
+ - Do not use permissive status matchers (`.toMatch(/^2/)`, `.toBeGreaterThanOrEqual(200)`, `checkStatusCode(response, '20x')`).
211
+ - Do not use shape-only or type-only assertions as a substitute for exact value validation. Forbidden patterns: `Array.isArray(...)`, `typeof X === '...'`, `X instanceof Array`, `Object.keys(X).length > 0`. When a field's value comes from one of those sources, assert it exactly.
212
+ - Do not use shape-only, containment-only, range-only, or weak-length as the sole assertion on a populated array.
213
+ - Do not swap between `getValue` and `getResponseValue` — keep whichever SDK helper the file already imports.
214
+ - Do not restructure, reformat, reorder, or modify existing code; do not add comments or docstrings.
215
+ - Do not change function signatures or variable names. You may add an import when a new assertion or a fix needs a helper — from `@skyramp/skyramp` or from the test's own helper module.
216
+ - Do not remove existing assertions.
217
+
218
+ ## Verification of Assertions
219
+
220
+ After adding the assertion lines in `$2`, re-read each test and check two things: every rule that applies to the behaviour under test has been applied correctly, and the test now fails if that behaviour breaks. Fix anything missing or weakly applied before completing. Remove any assertion you added that the behaviour does not depend on.
@@ -0,0 +1,373 @@
1
+ # UI test assertions
2
+
3
+ ## What to assert
4
+
5
+ Each test evaluates ONE behaviour — the one the recommendation it came from asked for. Assert that behaviour on the page where it shows, and the rendered values it depends on, exactly. A page the test only passes through, and an element the behaviour does not touch, need no assertion: asserting them makes the test fail for reasons the test is not about and buries what the test is for. The rules below say how to assert a value, not how many values to assert.
6
+
7
+ ## Scope of this file
8
+
9
+ This file is the complete rule set for UI tests. It replaces the response-body rules in `reference/shared-rules.md`; only that file's "Scope by mode" section also applies.
10
+
11
+ ## First Check
12
+
13
+ If `$2` has no `expect()` assertions, you MUST manually add them before anything else. Use `import { expect } from '@skyramp/skyramp';` — never from `@playwright/test`. If an existing import pulls `expect` from `@playwright/test`, move it to `@skyramp/skyramp` (keep `test` on the playwright line).
14
+
15
+ ## Flutter Web Check
16
+
17
+ If the test targets a Flutter web app (detected by `flt-semantics`, `flt-glass-pane`, or `flt-semantics-placeholder` appearing anywhere in `$2`, OR if the test navigates to a URL that served a Flutter app during recording), you MUST add the following two blocks immediately after `page.setDefaultTimeout(pageTimeout);` and before the `newSkyrampPlaywrightPage` wrap:
18
+
19
+ ```typescript
20
+ // Flutter headless fix: patch Event.isTrusted so synthetic clicks activate Flutter semantics
21
+ await page.context().addInitScript(() => {
22
+ Object.defineProperty(Event.prototype, 'isTrusted', { get: () => true, configurable: true });
23
+ });
24
+ ```
25
+
26
+ And immediately after **every** `page.goto()` call in the test, add exactly these three statements — do NOT substitute a different activation approach or different `waitForFunction` bodies:
27
+
28
+ ```typescript
29
+ // Wait for Flutter to bootstrap (confirms Flutter engine is ready before activating)
30
+ await page.waitForFunction(
31
+ () => !!document.querySelector('flt-semantics-placeholder, flt-glass-pane, flutter-view'),
32
+ undefined,
33
+ { timeout: 30000 }
34
+ );
35
+ // Activate Flutter accessibility semantics by clicking the hidden placeholder
36
+ await page.evaluate(() => { const el = document.querySelector('flt-semantics-placeholder'); if (el) el.dispatchEvent(new MouseEvent('click', { isTrusted: true, bubbles: true, cancelable: true })); });
37
+ // Wait for the semantics tree to be live: the activation placeholder is gone AND
38
+ // at least one flt-semantics node exists. Requiring a populated tree (not just the
39
+ // placeholder's absence) guards against a vacuous pass when the bootstrap wait
40
+ // above resolved on flt-glass-pane/flutter-view before the placeholder ever mounted.
41
+ await page.waitForFunction(
42
+ () => document.querySelector('flt-semantics-placeholder') === null
43
+ && document.querySelector('flt-semantics') !== null,
44
+ undefined,
45
+ { timeout: 20000 }
46
+ );
47
+ ```
48
+
49
+ Use exactly the three statements above. Do NOT use the two-argument form `waitForFunction(fn, { timeout })` — the timeout must be the third argument with `undefined` as the second. If you see an existing body click, `locator.click`, or old-style `waitForFunction` after a goto, replace the entire block with the exact three statements above.
50
+
51
+ This is required because Flutter web renders to a `<canvas>` element (no traditional DOM). The first `waitForFunction` ensures Flutter has bootstrapped before activation; the `dispatchEvent` activates semantics; the second `waitForFunction` confirms the semantics tree is live (placeholder removed **and** `flt-semantics` nodes present). The combined gate handles both modes — when accessibility is pre-enabled (semantics active from frame 1, no placeholder ever shown) and when activation depends on the click — without passing prematurely on a frame where neither has happened yet.
52
+
53
+ **Then wait for the first element you interact with.** The gate above confirms the semantics tree *started* building, but Flutter populates it incrementally — individual widgets (a textbox, a button) can still be a beat behind when the gate passes, especially on a cold start where accessibility was not pre-enabled. The wrapped Skyramp page also enforces a short internal action timeout, so a lagging widget fails fast rather than waiting out the page default. Guard against this: immediately after the activation block (and after any later `page.goto()`'s block), add an explicit `waitFor` on the **first locator the test interacts with on that page**, before the interaction itself. Example:
54
+
55
+ ```typescript
56
+ // Wait for the specific target to be present before interacting (tree may still be filling in)
57
+ await page.getByRole('textbox', { name: 'Username' }).waitFor({ state: 'visible', timeout: 20000 });
58
+ await page.getByRole('textbox', { name: 'Username' }).fill('admin');
59
+ ```
60
+
61
+ Use the **same locator** that the next interaction uses — do not invent a new selector. This waits for exactly the widget the test needs, which is more reliable than any generic tree-node count (those are app-specific magic numbers); it is the per-target wait that Flutter-web automation guidance recommends over a one-size-fits-all readiness check.
62
+
63
+ **Also check for brittle flt-semantic-node-* selectors:** If the test uses `page.locator("#flt-semantic-node-N")` for any interaction (clicks, navigations), replace it with a semantic selector (`getByRole`, `getByText`, or `getByLabel`) — `flt-semantic-node-N` IDs change between sessions and across devices, making the test brittle. Example: replace `page.locator("#flt-semantic-node-78").click()` with `page.getByText("Settings").click()` using the visible label from the same line's context.
64
+
65
+ **Flutter assertion grounding rule:** For Flutter web tests, use the following priority order when adding `expect()` assertions:
66
+
67
+ 1. **Existing selectors in the test file** — prefer these first; they were captured from the live accessibility tree during recording.
68
+ 2. **`browser_blueprint` snapshot** — if a blueprint was captured, use element roles, names, and text that appear verbatim in the snapshot.
69
+ 3. **Source code / diff** — only consult source code after exhausting the above. Flutter's accessibility tree frequently omits or transforms text (e.g. CJK characters split into individual nodes, `ExcludeSemantics` widgets, icon-only buttons), so what appears in the Dart source may not exist in the ARIA tree at runtime. If a selector derived from source cannot be confirmed in the blueprint or recorded trace, skip the assertion rather than risk a false positive.
70
+
71
+ ## Idempotent Setup Check
72
+
73
+ Apply this check when — and only when — the test body contains a create-entity sequence: a "Create X" / "New X" / "Add X" button click that opens a dialog or form, followed by filling in a name or identifier, followed by a confirm/submit action whose result subsequent steps depend on.
74
+
75
+ **Why:** Multiple generated tests run sequentially against a single shared SUT instance within the same CI job. The agent's own exploration phase may also create the entity before tests execute. Whichever test runs first succeeds; all later tests collide with the already-existing entity and time out on the "Create X" button.
76
+
77
+ **This is the one exception to the "do not restructure" rule.** Wrapping entity creation in an existence check does not change the test's intent — it makes it robust to pre-existing state.
78
+
79
+ **How to wrap it:**
80
+
81
+ 1. Before the create sequence, check whether the entity already exists (using `isVisible()` on the entity's list item or link, wrapped in `.catch(() => false)` to avoid throwing on timeout).
82
+ 2. If it exists: navigate to it directly.
83
+ 3. If it does not exist: run the original create sequence.
84
+
85
+ For the existence check, use selectors already present in `$2`. If no list-item selector exists, fall back to `getByRole('link', { name: <entityName> })` or `getByText(<entityName>)` where `<entityName>` is the value filled into the creation form.
86
+
87
+ **Example — entity located by link:**
88
+
89
+ ```typescript
90
+ // Before (fragile — times out if entity already exists):
91
+ await page.getByRole('button', { name: 'Create Project' }).click();
92
+ await page.getByPlaceholder('Project name').fill('TestProject');
93
+ await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
94
+
95
+ // After (idempotent — works whether entity exists or not):
96
+ const existingProject = page.getByRole('link', { name: 'TestProject' });
97
+ if (await existingProject.isVisible().catch(() => false)) {
98
+ await existingProject.click();
99
+ } else {
100
+ await page.getByRole('button', { name: 'Create Project' }).click();
101
+ await page.getByPlaceholder('Project name').fill('TestProject');
102
+ await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
103
+ }
104
+ ```
105
+
106
+ **Example — entity located by table row:**
107
+
108
+ ```typescript
109
+ // Before (fragile):
110
+ await page.getByRole('button', { name: 'Add Secret' }).click();
111
+ await page.getByLabel('Secret name').fill('API_KEY');
112
+ await page.getByRole('button', { name: 'Save' }).click();
113
+
114
+ // After (idempotent):
115
+ const existingSecret = page.getByRole('row', { name: 'API_KEY' });
116
+ if (await existingSecret.isVisible().catch(() => false)) {
117
+ await existingSecret.click();
118
+ } else {
119
+ await page.getByRole('button', { name: 'Add Secret' }).click();
120
+ await page.getByLabel('Secret name').fill('API_KEY');
121
+ await page.getByRole('button', { name: 'Save' }).click();
122
+ }
123
+ ```
124
+
125
+ ## Pre-Edit Assertion Analysis
126
+
127
+ Before editing `$2`, you must output a `<thinking>` block. It states the behaviour each test evaluates, then works through the rules for the items that behaviour depends on, so no rule that applies is overlooked. The JSON array should match the template below — every assertion category and every rule title under it must appear as a key, with `[]` where the rule does not apply.
128
+
129
+ 1. For each test in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from, and name the page where that behaviour shows. A generated spec may carry a title that names its behaviour — trust that title when it does. A spec still named `testUi` claims nothing, so use the name only when it is specific enough to add something.
130
+ 2. Selector inventory — list every selector already present in `$2` (`data-testid`, role + name, text, label, etc.). New assertions may use only selectors from this list. An assertion the recorder dropped because it failed during recording may use the selector of the element named in that recording's blueprint capture. Do not invent `data-testid` values, role names, or aria attributes. Also note captured network responses, repeated element patterns, exact rendered text/value/attribute from trace/source, and existing `toBeVisible()` assertions whose exact text is knowable.
131
+ 3. Process — Replay → Identify → Fix or Add — walk through these three steps explicitly.
132
+ a. Replay the scenario mentally. At each state-changing action (form submit, item add/edit/delete), ask: "What is the EXPECTED outcome based on the action performed?"
133
+ b. Identify expectation mismatches. If the recorded trace shows a result that contradicts the action (e.g. removing 1 of 2 items but the page shows 3, submitting a form but getting a blank page, editing a field but the old value persists), that is an app bug the test should catch. List every mismatch you find.
134
+ c. Fix or add assertions for each mismatch.
135
+ - If an existing assertion uses the wrong (buggy) value, edit it to assert the correct expected value.
136
+ - If no assertion exists for the buggy behavior, add one immediately after the action that triggers it.
137
+ 4. Classify each in-scope action / selector / captured response by its applicable assertion category, marking each category APPLICABLE or NOT APPLICABLE.
138
+ - Critical UI Assertions applies when there is a collection / repeated element (`toHaveCount`), a pageerror handler, a captured network response, a negative-only or URL-only test needing a positive-path companion, a tautological locator-by-text + assert-text to replace, or a colour / class / size / element-order change the diff states (Appearance and layout changes), or an element the PR removed (Removed element guard).
139
+ - Computed Values applies when there is a knowable exact text / value / attribute, including a definition-page displayed value or an image `src`.
140
+ - Post-edit State applies whenever EITHER (a) the test contains a state-changing action (form fill+submit, save / delete / create / toggle, checkbox click, hover / mouseout, refresh, reload, JS update, form edit), OR (b) the PR changes interactive behavior — in case (b), add the triggering action and assert the before/after transition (see "Exercise the changed interaction"). Mark NOT APPLICABLE only when the PR changes no interactive behavior and the test has no state-changing action.
141
+ 5. For each in-scope item, output one JSON object using the template below. The output is an array — repeat the object template below once per in-scope item.
142
+ - `action_or_selector_or_response`: the selector, action, or captured network response this entry covers.
143
+ - `behaviour_under_test`: the one-line behaviour from step 1 that this item is evidence for. When an item is evidence for no behaviour any test in scope claims, write `none` and add nothing for it.
144
+ - `assertion_categories`: an object that MUST contain every category name below as a key. The value of each category is itself an object that MUST contain every rule title under that category as a key. For each rule, the value is the assertion lines you will add for this item under that rule. `[]` means the rule does not apply here, which is a normal and expected answer: it is the right one whenever the rule's elements are not part of `behaviour_under_test`. Listing every key keeps a rule that DOES apply from being skipped; it is not a quota to fill.
145
+
146
+ ```json
147
+ [{
148
+ "action_or_selector_or_response": "<selector | action | response>",
149
+ "behaviour_under_test": "<the one-line behaviour this item is evidence for, or none>",
150
+ "assertion_categories": {
151
+ "Critical UI Assertions": {
152
+ "Exercise the changed interaction (dynamic behavior)": [],
153
+ "Appearance and layout changes": [],
154
+ "Selector constraints": [],
155
+ "Removed element guard": [],
156
+ "Page errors": [],
157
+ "Correct intended behavior": [],
158
+ "Tests target the changed behavior introduced by the pull request": [],
159
+ "Collection / repeated UI elements": [],
160
+ "Positive-path companion": [],
161
+ "Captured network responses": []
162
+ },
163
+ "Computed Values": {
164
+ "Exact rendered values": []
165
+ },
166
+ "Post-edit State": {
167
+ "Post-action visible state": []
168
+ }
169
+ }
170
+ }]
171
+ ```
172
+
173
+ ## Assertion Rules with Examples
174
+
175
+ Most-violated patterns — whenever the behaviour under test involves one of these, this is the shape it takes. (1) repeated elements → `toHaveCount(N)` + per-item `toHaveText`/`toHaveValue`/`toHaveAttribute` (Collection / repeated UI elements). (2) post-action state → `toHaveText`/`toHaveValue`/`toHaveAttribute`/`toBeChecked`, not `toBeVisible` when exact value is knowable (Post-action visible state). (3) routing/URL-only tests → at least one rendered-element exact text (Positive-path companion).
176
+
177
+ Strength order. `toHaveCount`/`toHaveText`/`toHaveValue`/`toHaveAttribute` > `toContainText` (only when string is genuinely dynamic) > `toBeVisible` (only when presence is the actual test).
178
+
179
+ ### Critical UI Assertions
180
+
181
+ #### Exercise the changed interaction (dynamic behavior)
182
+
183
+ When the PR introduces or changes interactive behavior (toggle, theme switch, expand/collapse, dialog open/close, focus management, optimistic update), the test MUST perform the triggering action and assert BOTH the state before AND after the action — not only the default or resting state. WHY: the PR's change IS the transition; a test that asserts only the initial/resting state would still pass even if the interaction were completely broken, so it gives zero coverage of what changed. If the test asserts only the resting state, add the action that triggers the change and assert the resulting transition — never mark this not applicable merely because the generated test lacks an action.
184
+
185
+ - Toggle / switch: click the control and assert the observable flips (e.g. data-theme 'light' -> 'dark'), then click again and assert it reverses.
186
+ - Dialog / modal: open it and assert focus moves into the dialog; close via ESC or Cancel and assert focus returns to the trigger.
187
+ - The after-state must differ from the before-state — a single assertion of the unchanged default value does not verify the change.
188
+
189
+ ```javascript
190
+ await expect(page.locator('html')).toHaveAttribute('data-theme', 'light');
191
+ await page.getByTestId('theme-toggle').click();
192
+ await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark');
193
+ ```
194
+
195
+ ```python
196
+ trigger = page.get_by_test_id('delete-recipe')
197
+ trigger.click()
198
+ expect(page.get_by_role('dialog')).to_be_focused()
199
+ page.keyboard.press('Escape')
200
+ # focus returns to the trigger
201
+ expect(trigger).to_be_focused()
202
+ ```
203
+
204
+ #### Appearance and layout changes
205
+
206
+ When the PR changes how an element looks or where it sits (colour, class, size, `flex-direction`, a moved block), assert the changed property on the element that OWNS it — `flex-direction` belongs to the flex container, not the clicked child, and an order check needs both compared elements. Use a selector already in the file; if the owner has none, report a recording gap in your `<thinking>` block — do not invent one or screenshot it.
207
+
208
+ - Colour / class: a class assertion recorded at capture is already written as a bounded regex (`toHaveClass(/(^|\s)bg-blue-600(\s|$)/)`) — leave it as generated. Use `toContainClass('bg-blue-600')` only for a class assertion you add yourself (1.52+; it matches one token, unlike a bare `/bg-blue-600/` which also passes on `hover:bg-blue-600`). For a style, `toHaveCSS('background-color', <the value the app computes>)` — take it from the app, do not convert the diff's hex: Tailwind v4 serializes `oklch(...)`, not `rgb(...)`.
209
+ - Order: compare both elements' `boundingBox()` on the changed axis (holds for `flex-direction` / `order` / `dir` / grid); `toHaveCSS('flex-direction', 'row-reverse')` only when the container is `display: flex` with an unconditional class.
210
+ - Size: `toHaveCSS('width', <the computed width>)`. Name the value; never copy a `...` or `/…/` placeholder.
211
+
212
+ A `toHaveScreenshot()` baseline is right only for a look no property expresses (image, gradient, chart) or to refresh an already-committed baseline (SKYR-4298) — never a new one for a colour, class or order change.
213
+
214
+ #### Selector constraints
215
+
216
+ Every assertion uses a selector already in the file. Never invent `data-testid`, role names, or classes. One exception: a `data-*` attribute + value listed in `uiContext.removedElements` (from the `skyramp_analyze_changes` output in your context) may be asserted `toBeHidden()` even though no element carries it any more — `getByTestId(value)` for `data-testid`, `page.locator('[data-cy="value"]')` for any other attribute — see Removed element guard. A `-` line in the raw diff is not enough on its own: renames and moved elements also appear there.
217
+
218
+ - No tautological assertions — locating an element by text X, then asserting it contains X.
219
+
220
+ ```javascript
221
+ await expect(page.getByTestId('badge-count')).toHaveText('3');
222
+ ```
223
+
224
+ #### Removed element guard
225
+
226
+ When the PR deletes a rendered element (a `data-*` attribute + value listed in `uiContext.removedElements`) and the test visits the page that rendered it, assert `toBeHidden()` on it — `getByTestId(value)` when the attribute is `data-testid`, otherwise `page.locator('[<attribute>="<value>"]')` (never `getByTestId` for `data-cy`/`data-qa`: Playwright resolves it against `data-testid` and the guard would pass vacuously). `toBeHidden` passes when the locator matches nothing or a single non-visible node (it is strict on multiple matches, like every locator assertion), which is the right contract for a removed element; do not substitute a `toBeVisible` on an unrelated element. Pair it with at least one positive assertion on a retained element of the same page so the test cannot pass on a blank or un-rendered page.
227
+
228
+ - Anchor on the removed attribute+value or role+name, never on text or position — a text-based absence check breaks when unrelated siblings change.
229
+ - Do not add a guard for an element whose whole page or route was removed — that is maintenance of the tests that covered it, not a new assertion; a spec that opens a deleted route must be anchored on a surviving page first (a retained element asserted on a live page in the same spec) — a spec whose only visited page is the dead URL is not a valid guard.
230
+ - A renamed test id or accessible name (a removed `aria-label` included) is not a removed element: assert the element under its new identifier and never assert the retired identifier `toBeHidden()` — it passes today and turns into a false failure the day the name is reused.
231
+ - An element that exists only inside a control the page has to open — an `option` of a `select`, an item of a closed menu or dropdown — takes `toHaveCount(0)`, not `toBeHidden()`. A closed control's contents have no bounding box, so `toBeHidden()` passes whether the element was removed or not, and the guard stays green the day it comes back. If the spec opens the control before asserting, the element would have had a box had it survived, so assert both.
232
+ - The positive companion for that guard is counted or read, never `toBeVisible`: the same missing bounding box that makes `toBeHidden()` a false green on the removed entry makes `toBeVisible()` a false red on the one that stayed. Assert a retained sibling with `toHaveCount(1)` or `toHaveText`, or assert the control itself, which does have a box.
233
+
234
+ ```javascript
235
+ await expect(page.getByTestId('navbar-sessionid-row')).toBeHidden();
236
+ await expect(page.locator('[data-cy="checkout-btn"]')).toBeHidden();
237
+ await expect(page.getByTestId('navbar-products')).toHaveText('Products');
238
+ ```
239
+
240
+ ```python
241
+ expect(page.get_by_test_id('navbar-sessionid-row')).to_be_hidden()
242
+ expect(page.get_by_test_id('navbar-products')).to_have_text('Products')
243
+ ```
244
+
245
+ #### Page errors
246
+
247
+ Register `page.on('pageerror', ...)` before the first navigation and assert `expect(errors).toHaveLength(0)` at the end of the test.
248
+
249
+ #### Correct intended behavior
250
+
251
+ Assertions encode the expected outcome of the action, not the buggy runtime output observed in the trace.
252
+
253
+ ```javascript
254
+ await expect(page.locator('[data-testid="session-row"]')).toHaveCount(3);
255
+ ```
256
+
257
+ #### Tests target the changed behavior introduced by the pull request
258
+
259
+ Every test needs at least one assertion that fails when the behaviour it claims is broken. This is the rule the others support: a test that satisfies every rule below and still does not distinguish the behaviour working from the behaviour broken has not been enhanced. Target it on populated or updated state, not only on empty or zero state, and assert it on the page where the behaviour shows.
260
+
261
+ When the PR changed the behaviour, the expected value is the one the diff, the PR description, or the referenced spec establishes — even when the running app still renders the old value. The test is expected to fail until the code is fixed.
262
+
263
+ #### Collection / repeated UI elements
264
+
265
+ For every collection page or selector matching multiple rendered nodes (items, rows, cards, badges, tabs, chips, definition rows, nav items), assert the exact count plus per-item content.
266
+
267
+ - Use `toHaveCount(N)` where N comes from the trace array length or rendered DOM (`0` for empty state).
268
+ - Add at least one concrete per-item content assertion (`toHaveText`, `toHaveValue`, `toHaveAttribute`).
269
+ - Empty trace → `toHaveCount(0)` paired with the empty-state text.
270
+
271
+ ```javascript
272
+ await expect(page.getByRole('row')).toHaveCount(2);
273
+ await expect(page.getByRole('cell', { name: 'admin@example.com' })).toHaveText('admin@example.com');
274
+ ```
275
+
276
+ ```javascript
277
+ await expect(page.getByTestId('notification-badge')).toHaveText('3');
278
+ await expect(page.getByTestId('notification-row')).toHaveCount(3);
279
+ ```
280
+
281
+ ```javascript
282
+ await expect(page.getByTestId('definition-row')).toHaveCount(3);
283
+ await expect(page.getByTestId('definition-row').nth(0)).toHaveText('Version 10.2.1');
284
+ ```
285
+
286
+ #### Positive-path companion
287
+
288
+ Negative-only checks and URL-only routing tests must include at least one positive rendered-element assertion such as a heading, breadcrumb, title, link, count, or exact text.
289
+
290
+ ```javascript
291
+ await expect(page).toHaveURL(/\/users/);
292
+ await expect(page.getByRole('heading')).toHaveText('User Directory');
293
+ ```
294
+
295
+ #### Captured network responses
296
+
297
+ For every `page.waitForResponse`, `page.on`, or `page.route`, assert at least one status, body, or header field. Body values used downstream must also appear as visible UI text.
298
+
299
+ ```javascript
300
+ const loginResp = await page.waitForResponse('**/login');
301
+ expect(loginResp.status()).toBe(200);
302
+ expect((await loginResp.json()).user.email).toBe('admin@example.com');
303
+ ```
304
+
305
+ ### Computed Values
306
+
307
+ #### Exact rendered values
308
+
309
+ When the exact text, value, or attribute is knowable from the trace or source, use `toHaveText`, `toHaveValue`, or `toHaveAttribute` — never `toBeVisible` or `toContainText`.
310
+
311
+ - Definition / info pages: assert the actual displayed values (version, count, date), not just the static label text.
312
+ - Images: assert `toHaveAttribute('src', ...)` with the exact src — never visibility alone.
313
+
314
+ ```javascript
315
+ await expect(page.getByTestId('status')).toHaveText('Active');
316
+ ```
317
+
318
+ ```javascript
319
+ await expect(page.getByTestId('product-image')).toHaveAttribute('src', /expected-pattern/);
320
+ ```
321
+
322
+ ### Post-edit State
323
+
324
+ Apply only when the test contains a state-changing action. Otherwise mark NOT APPLICABLE.
325
+
326
+ #### Post-action visible state
327
+
328
+ After a state-changing action (form fill+submit, save / delete / create / toggle, checkbox click, hover / mouseout, refresh, reload, JS update, form edit), assert the visible updated outcome via `toHaveText`, `toHaveValue`, `toHaveAttribute`, or `toBeChecked`. The displayed values must reflect the edit.
329
+
330
+ - Toggle / checkbox renames: assert the new label or state, not `toBeVisible` on the renamed element.
331
+ - Hover / mouseout: assert the overlay or state visible / hidden after the event.
332
+ - List edit: when the test submits N items, assert exactly N rows. When the count is unknown before the action, read it before and assert the delta after.
333
+
334
+ ```javascript
335
+ await expect(page.getByTestId('description-checkbox')).toBeChecked();
336
+ await expect(page.getByTestId('description-label')).toHaveText('check_box Description');
337
+ ```
338
+
339
+ ```javascript
340
+ await expect(page.getByTestId('total')).toHaveText('\$19.98');
341
+ ```
342
+
343
+ ```javascript
344
+ await expect(page.getByTestId('version')).toHaveText('10.2.1');
345
+ ```
346
+
347
+ ## What Not to Do
348
+
349
+ - Do not invent selectors, values, attributes, or assertions
350
+ - Do not use `toBeVisible` when exact text/value/state is knowable
351
+ - Do not use tautological locator-by-text + assert-text
352
+ - Do not use `toContainText` when the full string is known
353
+ - Do not assert static page headings, intermediate states, or values guaranteed by the action you just took
354
+ - Do not assert the same value with multiple selectors
355
+ - Do not import `expect` from `@playwright/test`
356
+ - Do not restructure, reorder, or modify existing code/imports/signatures
357
+ - Do not add comments or docstrings
358
+ - Do not remove or modify existing assertions
359
+ - Do not assert buggy/error text as expected (unless the intended UX is an error state)
360
+ - Do not add a `toHaveScreenshot()` baseline for a colour, class, size or order change the diff states — assert the property (Appearance and layout changes); a baseline created on this run cannot fail on it, unless that page already has a committed baseline PNG (then it is a rebaseline, not a new one)
361
+
362
+ ## Verification of Assertions
363
+
364
+ After adding the assertion lines in `$2`, re-read each test and check two things: every rule that applies to the behaviour under test has been applied correctly, and the test now fails if that behaviour breaks. Fix anything missing or weakly applied before completing. Remove any assertion you added that the behaviour does not depend on.
365
+
366
+ The goal is tests that FAIL when the app has bugs, not tests that simply replay what happened.
367
+
368
+ ## Additional checks in Testbot runs
369
+
370
+ Apply this section only inside a Skyramp Testbot run.
371
+
372
+ - If no suitable selector exists in `$2` for an assertion you need to add, go back and call `browser_assert` on the live page to record it with a valid selector, then re-export and regenerate.
373
+ - **After executing a UI test that documents a bug from `issuesFound`**: if it passed when you expected it to fail, the assertions are too weak — add a stronger `expect()` that directly targets the buggy behavior. This counts as the single allowed retry under the 2-attempt cap — do NOT re-run more than once.