browser-debugger-cli 0.8.0 → 0.10.0

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 (304) hide show
  1. package/README.md +7 -1
  2. package/dist/cdp/schema.d.ts +4 -1
  3. package/dist/cdp/schema.js +48 -7
  4. package/dist/commands/cdp.js +3 -2
  5. package/dist/commands/cleanup.d.ts +11 -0
  6. package/dist/commands/cleanup.js +161 -57
  7. package/dist/commands/console.d.ts +20 -1
  8. package/dist/commands/console.js +57 -17
  9. package/dist/commands/details.js +3 -2
  10. package/dist/commands/dom/DomElementResolver.d.ts +10 -3
  11. package/dist/commands/dom/DomElementResolver.js +35 -17
  12. package/dist/commands/dom/a11y.d.ts +10 -0
  13. package/dist/commands/dom/a11y.js +29 -6
  14. package/dist/commands/dom/eval.d.ts +3 -1
  15. package/dist/commands/dom/eval.js +29 -4
  16. package/dist/commands/dom/form.js +16 -62
  17. package/dist/commands/dom/formInteraction.js +189 -119
  18. package/dist/commands/dom/formSummary.d.ts +49 -0
  19. package/dist/commands/dom/formSummary.js +180 -0
  20. package/dist/commands/dom/frames.d.ts +2 -1
  21. package/dist/commands/dom/frames.js +17 -2
  22. package/dist/commands/dom/get.d.ts +6 -5
  23. package/dist/commands/dom/get.js +92 -82
  24. package/dist/commands/dom/helpers/index.d.ts +1 -1
  25. package/dist/commands/dom/helpers/index.js +1 -1
  26. package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
  27. package/dist/commands/dom/helpers/keyAttributes.js +54 -0
  28. package/dist/commands/dom/helpers/query.d.ts +44 -17
  29. package/dist/commands/dom/helpers/query.js +300 -106
  30. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  31. package/dist/commands/dom/helpers/runElementCommand.js +98 -30
  32. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  33. package/dist/commands/dom/helpers/screenshot.js +239 -51
  34. package/dist/commands/dom/index.d.ts +4 -1
  35. package/dist/commands/dom/index.js +22 -7
  36. package/dist/commands/dom/inspect.d.ts +15 -0
  37. package/dist/commands/dom/inspect.js +82 -0
  38. package/dist/commands/dom/layout.d.ts +14 -0
  39. package/dist/commands/dom/layout.js +54 -0
  40. package/dist/commands/dom/listeners.d.ts +5 -1
  41. package/dist/commands/dom/listeners.js +15 -5
  42. package/dist/commands/dom/query.js +2 -3
  43. package/dist/commands/dom/screenshot.d.ts +12 -2
  44. package/dist/commands/dom/screenshot.js +27 -3
  45. package/dist/commands/dom/semanticUtils.d.ts +16 -10
  46. package/dist/commands/dom/semanticUtils.js +53 -16
  47. package/dist/commands/dom/wait.d.ts +13 -0
  48. package/dist/commands/dom/wait.js +83 -0
  49. package/dist/commands/helpJson.js +2 -2
  50. package/dist/commands/network/list.js +17 -13
  51. package/dist/commands/optionBehaviors.js +154 -21
  52. package/dist/commands/page.d.ts +3 -2
  53. package/dist/commands/page.js +100 -5
  54. package/dist/commands/peek.js +4 -11
  55. package/dist/commands/sessions.d.ts +8 -0
  56. package/dist/commands/sessions.js +19 -0
  57. package/dist/commands/shared/CommandRunner.js +4 -4
  58. package/dist/commands/shared/commonOptions.d.ts +4 -0
  59. package/dist/commands/shared/commonOptions.js +9 -0
  60. package/dist/commands/shared/dataFetcher.js +2 -2
  61. package/dist/commands/shared/followMode.d.ts +21 -1
  62. package/dist/commands/shared/followMode.js +29 -2
  63. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  64. package/dist/commands/shared/handleValidationError.js +12 -3
  65. package/dist/commands/shared/optionTypes.d.ts +61 -5
  66. package/dist/commands/shared/startHelpers.d.ts +66 -0
  67. package/dist/commands/shared/startHelpers.js +103 -13
  68. package/dist/commands/shared/validation.d.ts +14 -2
  69. package/dist/commands/shared/validation.js +20 -3
  70. package/dist/commands/start.d.ts +63 -0
  71. package/dist/commands/start.js +115 -15
  72. package/dist/commands/status.js +29 -7
  73. package/dist/commands/stop.js +7 -6
  74. package/dist/commands/tail.js +4 -11
  75. package/dist/commands/types.d.ts +2 -0
  76. package/dist/commands.js +2 -0
  77. package/dist/connection/chromeIdentity.d.ts +65 -0
  78. package/dist/connection/chromeIdentity.js +143 -0
  79. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  80. package/dist/connection/launcher/profilePreferences.js +151 -0
  81. package/dist/connection/launcher.d.ts +21 -2
  82. package/dist/connection/launcher.js +42 -16
  83. package/dist/connection/portReservation.d.ts +14 -4
  84. package/dist/connection/portReservation.js +21 -6
  85. package/dist/connection/startupExit.d.ts +8 -0
  86. package/dist/connection/startupExit.js +15 -6
  87. package/dist/constants.d.ts +6 -2
  88. package/dist/constants.js +9 -2
  89. package/dist/daemon/SessionController.js +23 -7
  90. package/dist/daemon/errors.d.ts +1 -1
  91. package/dist/daemon/errors.js +1 -1
  92. package/dist/daemon/launcher.d.ts +10 -2
  93. package/dist/daemon/launcher.js +8 -7
  94. package/dist/daemon/server/SocketServer.js +1 -2
  95. package/dist/daemon/session/Session.d.ts +20 -0
  96. package/dist/daemon/session/Session.js +80 -9
  97. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  98. package/dist/daemon/session/chromeConnection.js +45 -8
  99. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  100. package/dist/daemon/session/commandRegistry.js +113 -67
  101. package/dist/daemon/session/interactions.d.ts +48 -9
  102. package/dist/daemon/session/interactions.js +46 -9
  103. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  104. package/dist/daemon/session/triggeredRequests.js +157 -0
  105. package/dist/daemon/session/types.d.ts +5 -1
  106. package/dist/daemon.js +10630 -3601
  107. package/dist/errors/messages.d.ts +456 -24
  108. package/dist/errors/messages.js +862 -67
  109. package/dist/index.js +6915 -3401
  110. package/dist/ipc/client.d.ts +21 -1
  111. package/dist/ipc/client.js +35 -3
  112. package/dist/ipc/protocol/commands.d.ts +145 -5
  113. package/dist/ipc/protocol/commands.js +4 -0
  114. package/dist/ipc/protocol/domTypes.d.ts +291 -7
  115. package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
  116. package/dist/ipc/protocol/inspectTypes.js +10 -0
  117. package/dist/ipc/session/lifecycle.d.ts +8 -1
  118. package/dist/ipc/session/queries.d.ts +5 -1
  119. package/dist/ipc/session/types.d.ts +5 -0
  120. package/dist/ipc/transport/index.d.ts +2 -1
  121. package/dist/ipc/transport/index.js +2 -2
  122. package/dist/runtime/dom/actionEffects.d.ts +185 -0
  123. package/dist/runtime/dom/actionEffects.js +402 -0
  124. package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
  125. package/dist/runtime/dom/actionEffectsScripts.js +426 -0
  126. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  127. package/dist/runtime/dom/elementGeometry.js +553 -0
  128. package/dist/runtime/dom/elementInfo.d.ts +103 -0
  129. package/dist/runtime/dom/elementInfo.js +256 -0
  130. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  131. package/dist/runtime/dom/evalHelpers.js +136 -26
  132. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  133. package/dist/runtime/dom/eventListeners.js +184 -47
  134. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  135. package/dist/runtime/dom/formDiscovery.js +116 -16
  136. package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
  137. package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
  138. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  139. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  140. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  141. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  142. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  143. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  144. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  145. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  146. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  147. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  148. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  149. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  150. package/dist/runtime/dom/frameLayout.js +140 -0
  151. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  152. package/dist/runtime/dom/frameOrigin.js +62 -0
  153. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  154. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  155. package/dist/runtime/dom/frameSelection.d.ts +12 -1
  156. package/dist/runtime/dom/frameSelection.js +22 -3
  157. package/dist/runtime/dom/frames.d.ts +61 -5
  158. package/dist/runtime/dom/frames.js +329 -75
  159. package/dist/runtime/dom/inspect.d.ts +28 -0
  160. package/dist/runtime/dom/inspect.js +557 -0
  161. package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
  162. package/dist/runtime/dom/inspectAllStyles.js +385 -0
  163. package/dist/runtime/dom/inspectCascade.d.ts +94 -0
  164. package/dist/runtime/dom/inspectCascade.js +371 -0
  165. package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
  166. package/dist/runtime/dom/inspectCascadeModel.js +232 -0
  167. package/dist/runtime/dom/inspectHints.d.ts +62 -0
  168. package/dist/runtime/dom/inspectHints.js +305 -0
  169. package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
  170. package/dist/runtime/dom/inspectLayoutModel.js +346 -0
  171. package/dist/runtime/dom/inspectModel.d.ts +74 -0
  172. package/dist/runtime/dom/inspectModel.js +184 -0
  173. package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
  174. package/dist/runtime/dom/inspectPaintModel.js +461 -0
  175. package/dist/runtime/dom/inspectRules.d.ts +37 -0
  176. package/dist/runtime/dom/inspectRules.js +101 -0
  177. package/dist/runtime/dom/inspectScripts.d.ts +132 -0
  178. package/dist/runtime/dom/inspectScripts.js +263 -0
  179. package/dist/runtime/dom/inspectTree.d.ts +40 -0
  180. package/dist/runtime/dom/inspectTree.js +134 -0
  181. package/dist/runtime/dom/inspectVariables.d.ts +33 -0
  182. package/dist/runtime/dom/inspectVariables.js +94 -0
  183. package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
  184. package/dist/runtime/dom/inspectWhyModel.js +134 -0
  185. package/dist/runtime/dom/layout.d.ts +71 -0
  186. package/dist/runtime/dom/layout.js +340 -0
  187. package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
  188. package/dist/runtime/dom/listenerPageScripts.js +365 -0
  189. package/dist/runtime/dom/listenerSummary.d.ts +136 -11
  190. package/dist/runtime/dom/listenerSummary.js +361 -22
  191. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  192. package/dist/runtime/dom/pageActivity.js +123 -0
  193. package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
  194. package/dist/runtime/dom/reactEventHelpers.js +220 -41
  195. package/dist/runtime/dom/targetNode.d.ts +80 -27
  196. package/dist/runtime/dom/targetNode.js +249 -33
  197. package/dist/runtime/dom/wait.d.ts +25 -0
  198. package/dist/runtime/dom/wait.js +199 -0
  199. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  200. package/dist/runtime/dom/waitCondition.js +75 -0
  201. package/dist/runtime/page/emulation.d.ts +71 -0
  202. package/dist/runtime/page/emulation.js +117 -0
  203. package/dist/runtime/page/loadingState.d.ts +36 -0
  204. package/dist/runtime/page/loadingState.js +86 -0
  205. package/dist/runtime/page/navigation.d.ts +46 -2
  206. package/dist/runtime/page/navigation.js +69 -33
  207. package/dist/session/QueryCacheManager.d.ts +11 -1
  208. package/dist/session/QueryCacheManager.js +25 -3
  209. package/dist/session/chromeOwners.d.ts +34 -0
  210. package/dist/session/chromeOwners.js +51 -0
  211. package/dist/session/cleanup/staleSession.d.ts +11 -1
  212. package/dist/session/cleanup/staleSession.js +17 -6
  213. package/dist/session/cleanup/userCommands.js +2 -4
  214. package/dist/session/metadata.d.ts +5 -1
  215. package/dist/session/metadata.js +2 -1
  216. package/dist/session/paths.d.ts +77 -3
  217. package/dist/session/paths.js +111 -5
  218. package/dist/session/port.d.ts +31 -7
  219. package/dist/session/port.js +50 -43
  220. package/dist/session/portClaims.d.ts +66 -0
  221. package/dist/session/portClaims.js +284 -0
  222. package/dist/session/sessionList.d.ts +58 -0
  223. package/dist/session/sessionList.js +199 -0
  224. package/dist/session/sessionName.d.ts +46 -0
  225. package/dist/session/sessionName.js +97 -0
  226. package/dist/telemetry/a11y.d.ts +18 -3
  227. package/dist/telemetry/a11y.js +170 -29
  228. package/dist/telemetry/console.d.ts +1 -0
  229. package/dist/telemetry/console.js +100 -5
  230. package/dist/telemetry/network.js +3 -1
  231. package/dist/telemetry/requestKinds.d.ts +32 -0
  232. package/dist/telemetry/requestKinds.js +61 -0
  233. package/dist/telemetry/requestState.d.ts +31 -0
  234. package/dist/telemetry/requestState.js +38 -0
  235. package/dist/types.d.ts +112 -3
  236. package/dist/ui/formatters/a11y.js +3 -0
  237. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  238. package/dist/ui/formatters/console/chronological.js +17 -4
  239. package/dist/ui/formatters/console/json.js +3 -4
  240. package/dist/ui/formatters/console/shared.d.ts +12 -0
  241. package/dist/ui/formatters/console.d.ts +2 -2
  242. package/dist/ui/formatters/console.js +1 -1
  243. package/dist/ui/formatters/details.d.ts +8 -0
  244. package/dist/ui/formatters/details.js +61 -4
  245. package/dist/ui/formatters/dom.d.ts +27 -14
  246. package/dist/ui/formatters/dom.js +88 -59
  247. package/dist/ui/formatters/form.js +29 -18
  248. package/dist/ui/formatters/inspect.d.ts +39 -0
  249. package/dist/ui/formatters/inspect.js +596 -0
  250. package/dist/ui/formatters/keyAttributes.d.ts +19 -0
  251. package/dist/ui/formatters/keyAttributes.js +84 -0
  252. package/dist/ui/formatters/layout.d.ts +31 -0
  253. package/dist/ui/formatters/layout.js +53 -0
  254. package/dist/ui/formatters/listeners.d.ts +3 -2
  255. package/dist/ui/formatters/listeners.js +73 -9
  256. package/dist/ui/formatters/networkHeaders.d.ts +13 -0
  257. package/dist/ui/formatters/networkHeaders.js +36 -3
  258. package/dist/ui/formatters/networkList.d.ts +29 -1
  259. package/dist/ui/formatters/networkList.js +86 -20
  260. package/dist/ui/formatters/preview.js +2 -1
  261. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  262. package/dist/ui/formatters/requestStatus.js +2 -30
  263. package/dist/ui/formatters/sessions.d.ts +12 -0
  264. package/dist/ui/formatters/sessions.js +40 -0
  265. package/dist/ui/formatters/status.d.ts +21 -2
  266. package/dist/ui/formatters/status.js +47 -10
  267. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  268. package/dist/ui/formatters/triggeredRequests.js +65 -0
  269. package/dist/ui/formatting.d.ts +19 -0
  270. package/dist/ui/formatting.js +31 -36
  271. package/dist/ui/messages/chrome.d.ts +9 -0
  272. package/dist/ui/messages/chrome.js +17 -5
  273. package/dist/ui/messages/commands.d.ts +504 -14
  274. package/dist/ui/messages/commands.js +835 -21
  275. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  276. package/dist/ui/messages/consoleMessages.js +17 -0
  277. package/dist/ui/messages/hints.js +2 -1
  278. package/dist/ui/messages/networkMessages.d.ts +14 -0
  279. package/dist/ui/messages/networkMessages.js +18 -0
  280. package/dist/ui/messages/preview.js +5 -4
  281. package/dist/ui/messages/session.d.ts +30 -21
  282. package/dist/ui/messages/session.js +48 -26
  283. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  284. package/dist/ui/messages/sessionCommand.js +52 -0
  285. package/dist/utils/async.d.ts +17 -0
  286. package/dist/utils/async.js +36 -0
  287. package/dist/utils/color.d.ts +84 -0
  288. package/dist/utils/color.js +376 -0
  289. package/dist/utils/cssValues.d.ts +109 -0
  290. package/dist/utils/cssValues.js +236 -0
  291. package/dist/utils/http.d.ts +22 -1
  292. package/dist/utils/http.js +28 -9
  293. package/dist/utils/selectorFilters.d.ts +48 -8
  294. package/dist/utils/selectorFilters.js +296 -53
  295. package/dist/utils/shellDetection.d.ts +8 -2
  296. package/dist/utils/shellDetection.js +120 -33
  297. package/dist/utils/suggestions.d.ts +26 -0
  298. package/dist/utils/suggestions.js +73 -0
  299. package/dist/utils/taskMappings.js +10 -0
  300. package/dist/utils/url.d.ts +12 -2
  301. package/dist/utils/url.js +69 -7
  302. package/package.json +1 -1
  303. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  304. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -7,18 +7,21 @@
7
7
  * subscriptions for network-stability waits) on behalf of the CLI.
8
8
  */
9
9
  import { InvalidArgumentError } from 'commander';
10
- import { DomElementResolver } from './DomElementResolver.js';
11
10
  import { runElementCommand } from './helpers/runElementCommand.js';
12
11
  import { runCommand } from '../shared/CommandRunner.js';
13
- import { jsonOption } from '../shared/commonOptions.js';
12
+ import { jsonOption, SELECTOR_OR_INDEX_ARGUMENT } from '../shared/commonOptions.js';
14
13
  import { integerOption } from '../shared/validation.js';
15
14
  import { CommandError } from '../../errors/index.js';
16
- import { conflictingOptionsMessage, internalError, scrollOptionsError } from '../../errors/messages.js';
15
+ import { VIA_LABEL_SUFFIX, conflictingOptionsMessage, indexSourceText, internalError, scrollOptionsError, } from '../../errors/messages.js';
17
16
  import { domClick, domFill, domPressKey, domScroll, domSubmit } from '../../ipc/client.js';
18
17
  import { findUnknownModifiers } from '../../runtime/dom/keyMapping.js';
18
+ import { formatTriggeredRequestLines, formatTriggeredRequestsTitle, } from '../../ui/formatters/triggeredRequests.js';
19
19
  import { OutputFormatter } from '../../ui/formatting.js';
20
- import { POINTER_ACTION_DONE, dialogConsoleText } from '../../ui/messages/commands.js';
20
+ import { CLICK_RESULT_WAIT_HELP, POINTER_ACTION_DONE, POINTER_ACTION_NOUN, actionStatusLine, dialogConsoleText, newMessageText, pageNavigationText, shownElementText, stillChangingNote, } from '../../ui/messages/commands.js';
21
+ import { sessionCommand } from '../../ui/messages/sessionCommand.js';
21
22
  import { EXIT_CODES } from '../../utils/exitCodes.js';
23
+ /** Help of `--strict` on click and hover */
24
+ const STRICT_OPTION_HELP = 'Fail (exit 90) instead of using DOM events when a real mouse cannot reach the element (covered, hidden, zero-size)';
22
25
  /**
23
26
  * Commander parser for `--modifiers`: rejects unknown names instead of
24
27
  * silently pressing the bare key.
@@ -53,7 +56,7 @@ export function registerFormInteractionCommands(program) {
53
56
  domCommand
54
57
  .command('fill')
55
58
  .description('Fill a form field with a value (React-compatible, waits for stability)')
56
- .argument('<selectorOrIndex>', 'CSS selector or numeric index from query results (0-based)')
59
+ .argument('<selectorOrIndex>', SELECTOR_OR_INDEX_ARGUMENT)
57
60
  .argument('<value>', 'Value to fill (file inputs: paths separated by commas, "" clears)')
58
61
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
59
62
  .option('--no-blur', 'Do not blur after filling (keeps focus on element)')
@@ -71,6 +74,7 @@ export function registerFormInteractionCommands(program) {
71
74
  wait: options.wait !== false,
72
75
  }),
73
76
  call: domFill,
77
+ command: 'fill',
74
78
  action: 'fill element',
75
79
  failureSuggestion: 'Verify the selector matches a fillable element (input, textarea, select)',
76
80
  }), options, formatFillOutput);
@@ -78,12 +82,14 @@ export function registerFormInteractionCommands(program) {
78
82
  domCommand
79
83
  .command('click')
80
84
  .description('Click an element and wait for stability (accepts selector or index)')
81
- .argument('<selectorOrIndex>', 'CSS selector or numeric index from query results (0-based)')
85
+ .argument('<selectorOrIndex>', SELECTOR_OR_INDEX_ARGUMENT)
82
86
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
83
87
  .option('--double', 'Double-click')
84
88
  .option('--right', 'Right-click (opens the context menu)')
89
+ .option('--strict', STRICT_OPTION_HELP)
85
90
  .option('--no-wait', 'Skip waiting for network stability after click')
86
91
  .addOption(jsonOption())
92
+ .addHelpText('after', CLICK_RESULT_WAIT_HELP)
87
93
  .action(async (selectorOrIndex, options) => {
88
94
  const action = options.double ? 'double' : options.right ? 'right' : 'click';
89
95
  await runPointerCommand(selectorOrIndex, options, action);
@@ -91,8 +97,9 @@ export function registerFormInteractionCommands(program) {
91
97
  domCommand
92
98
  .command('hover')
93
99
  .description('Move the mouse over an element (shows hover menus and tooltips)')
94
- .argument('<selectorOrIndex>', 'CSS selector or numeric index from query results (0-based)')
100
+ .argument('<selectorOrIndex>', SELECTOR_OR_INDEX_ARGUMENT)
95
101
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
102
+ .option('--strict', STRICT_OPTION_HELP)
96
103
  .option('--no-wait', 'Skip waiting for network stability after hovering')
97
104
  .addOption(jsonOption())
98
105
  .action(async (selectorOrIndex, options) => {
@@ -101,12 +108,13 @@ export function registerFormInteractionCommands(program) {
101
108
  domCommand
102
109
  .command('submit')
103
110
  .description('Submit a form by clicking submit button and waiting for completion')
104
- .argument('<selectorOrIndex>', 'CSS selector or numeric index from query results (0-based)')
111
+ .argument('<selectorOrIndex>', SELECTOR_OR_INDEX_ARGUMENT)
105
112
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
106
113
  .option('--wait-navigation', 'Wait for page navigation after submit')
107
114
  .option('--wait-network <ms>', 'Wait for network idle after submit (milliseconds)', integerOption(0), 1000)
108
115
  .option('--timeout <ms>', 'Maximum time to wait (milliseconds)', integerOption(1), 10000)
109
116
  .addOption(jsonOption())
117
+ .addHelpText('after', CLICK_RESULT_WAIT_HELP)
110
118
  .action(async (selectorOrIndex, options) => {
111
119
  await runCommand(() => runElementCommand({
112
120
  selectorOrIndex,
@@ -120,6 +128,7 @@ export function registerFormInteractionCommands(program) {
120
128
  timeout: options.timeout,
121
129
  }),
122
130
  call: domSubmit,
131
+ command: 'submit',
123
132
  action: 'submit form',
124
133
  failureSuggestion: 'Verify the selector matches a form or submit button',
125
134
  }), options, formatSubmitOutput);
@@ -127,7 +136,7 @@ export function registerFormInteractionCommands(program) {
127
136
  domCommand
128
137
  .command('pressKey')
129
138
  .description('Press a key on an element (for Enter-to-submit, keyboard navigation)')
130
- .argument('<selectorOrIndex>', 'CSS selector or numeric index from query results (0-based)')
139
+ .argument('<selectorOrIndex>', SELECTOR_OR_INDEX_ARGUMENT)
131
140
  .argument('<key>', 'Key to press (Enter, Tab, Escape, Space, ArrowUp, etc.)')
132
141
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
133
142
  .option('--times <n>', 'Press key multiple times (default: 1)', integerOption(1, 1000))
@@ -146,6 +155,7 @@ export function registerFormInteractionCommands(program) {
146
155
  wait: options.wait !== false,
147
156
  }),
148
157
  call: domPressKey,
158
+ command: 'pressKey',
149
159
  action: 'press key',
150
160
  failureSuggestion: 'Verify the selector matches a focusable element',
151
161
  }), options, formatPressKeyOutput);
@@ -164,64 +174,62 @@ export function registerFormInteractionCommands(program) {
164
174
  .option('--no-wait', 'Skip waiting for lazy-loaded content after scroll')
165
175
  .addOption(jsonOption())
166
176
  .action(async (selector, options) => {
167
- await runCommand(async () => {
168
- const problem = scrollOptionsProblem(selector, options);
169
- if (problem) {
170
- const err = scrollOptionsError(problem);
171
- return {
172
- success: false,
173
- error: err.message,
174
- exitCode: EXIT_CODES.INVALID_ARGUMENTS,
175
- errorContext: { suggestion: err.suggestion },
176
- };
177
- }
178
- const target = selector
179
- ? await DomElementResolver.getInstance().resolve(selector, options.index)
180
- : undefined;
181
- if (target && !target.success) {
182
- return {
183
- success: false,
184
- error: target.error,
185
- exitCode: target.exitCode,
186
- ...(target.suggestion && { errorContext: { suggestion: target.suggestion } }),
187
- };
188
- }
189
- const response = await domScroll({
190
- ...(target && { selector: target.selector }),
191
- ...(target?.index !== undefined && { index: target.index }),
192
- ...(target?.backendNodeId !== undefined && { backendNodeId: target.backendNodeId }),
193
- ...(options.down !== undefined && { down: options.down }),
194
- ...(options.up !== undefined && { up: options.up }),
195
- ...(options.left !== undefined && { left: options.left }),
196
- ...(options.right !== undefined && { right: options.right }),
197
- ...(options.top !== undefined && { top: options.top }),
198
- ...(options.bottom !== undefined && { bottom: options.bottom }),
199
- wait: options.wait !== false,
200
- });
201
- if (response.status === 'error' || !response.data) {
202
- return {
203
- success: false,
204
- error: response.error ?? 'Failed to scroll',
205
- exitCode: response.exitCode ?? EXIT_CODES.INVALID_ARGUMENTS,
206
- ...(response.suggestion && { errorContext: { suggestion: response.suggestion } }),
207
- };
208
- }
209
- const result = response.data;
210
- if (!result.success) {
211
- return {
212
- success: false,
213
- error: result.error ?? 'Failed to scroll',
214
- exitCode: result.exitCode ?? EXIT_CODES.INVALID_ARGUMENTS,
215
- errorContext: {
216
- suggestion: result.suggestion ?? 'Verify the selector exists on the page',
217
- },
218
- };
219
- }
220
- const { success: _success, ...data } = result;
221
- return { success: true, data };
222
- }, options, formatScrollOutput);
177
+ await runCommand(() => runScroll(selector, options), options, formatScrollOutput);
223
178
  });
224
179
  }
180
+ /**
181
+ * Scroll to an element (selector or cached index) or by offsets/to an edge.
182
+ *
183
+ * @param selector - Selector or index argument, if any
184
+ * @param options - Scroll options
185
+ * @returns Command result
186
+ */
187
+ async function runScroll(selector, options) {
188
+ const problem = scrollOptionsProblem(selector, options);
189
+ if (problem) {
190
+ const err = scrollOptionsError(problem);
191
+ return {
192
+ success: false,
193
+ error: err.message,
194
+ exitCode: EXIT_CODES.INVALID_ARGUMENTS,
195
+ errorContext: { suggestion: err.suggestion },
196
+ };
197
+ }
198
+ const request = {
199
+ ...(options.down !== undefined && { down: options.down }),
200
+ ...(options.up !== undefined && { up: options.up }),
201
+ ...(options.left !== undefined && { left: options.left }),
202
+ ...(options.right !== undefined && { right: options.right }),
203
+ ...(options.top !== undefined && { top: options.top }),
204
+ ...(options.bottom !== undefined && { bottom: options.bottom }),
205
+ wait: options.wait !== false,
206
+ };
207
+ if (selector) {
208
+ return runElementCommand({
209
+ selectorOrIndex: selector,
210
+ index: options.index,
211
+ buildRequest: (target) => ({ ...target, ...request }),
212
+ call: domScroll,
213
+ command: 'scroll',
214
+ action: 'scroll',
215
+ failureSuggestion: 'Verify the selector exists on the page',
216
+ });
217
+ }
218
+ const response = await domScroll(request);
219
+ const result = response.data;
220
+ if (response.status === 'error' || !result?.success) {
221
+ return {
222
+ success: false,
223
+ error: result?.error ?? response.error ?? 'Failed to scroll',
224
+ exitCode: result?.exitCode ?? response.exitCode ?? EXIT_CODES.INVALID_ARGUMENTS,
225
+ ...((result?.suggestion ?? response.suggestion) && {
226
+ errorContext: { suggestion: result?.suggestion ?? response.suggestion ?? '' },
227
+ }),
228
+ };
229
+ }
230
+ const { success: _success, ...data } = result;
231
+ return { success: true, data };
232
+ }
225
233
  /**
226
234
  * The first rule `bdg dom scroll` options break, if any: one target (an
227
235
  * element, or offsets/edges), and no opposite directions.
@@ -266,89 +274,159 @@ async function runPointerCommand(selectorOrIndex, options, action) {
266
274
  ...target,
267
275
  wait: options.wait !== false,
268
276
  ...(action !== 'click' && { action }),
277
+ ...(options.strict && { strict: true }),
269
278
  }),
270
279
  call: domClick,
280
+ command: action === 'hover' ? 'hover' : 'click',
271
281
  action: action === 'hover' ? 'hover element' : 'click element',
272
282
  failureSuggestion: 'Verify the selector matches a clickable element',
273
283
  }), options, formatClickOutput);
274
284
  }
275
285
  /**
276
- * Add an action's warning and the dialogs it caused to the output.
286
+ * Build an action's output: the status line ("✓ Element Clicked",
287
+ * "⚠ Element Clicked (with warnings)" with the warning right below it,
288
+ * "⚠ Element Clicked (page still changing)" with what it was still working
289
+ * on, or "⚠ Element Clicked (no visible effect: …)"), the details, what
290
+ * changed on the page (`Page:` navigation, `New text:` messages, `Shown:`
291
+ * elements), then the network requests it triggered and the dialogs it
292
+ * caused. No request list is shown when there were none (JSON has an empty
293
+ * `triggeredRequests` then).
277
294
  *
278
- * @param fmt - Output being built
295
+ * @param done - What was done, e.g. "Element Clicked"
296
+ * @param details - Label/value rows
279
297
  * @param result - Action result
298
+ * @param options - Width of the labels; what the action is called in notes (e.g. "click")
299
+ * @returns Output being built (more can be appended)
280
300
  */
281
- function appendNotices(fmt, result) {
282
- if (result.warning) {
283
- fmt.blank();
301
+ function formatActionOutput(done, details, result, options = {}) {
302
+ const keyWidth = options.keyWidth ?? 15;
303
+ const fmt = new OutputFormatter();
304
+ const stillChanging = result.settled === false && result.pending !== undefined;
305
+ fmt.text(actionStatusLine(done, {
306
+ warned: result.warning !== undefined,
307
+ noEffect: result.effect === 'none',
308
+ stillChanging,
309
+ }));
310
+ if (result.warning)
284
311
  fmt.text(`⚠ Warning: ${result.warning}`);
312
+ if (stillChanging && result.pending) {
313
+ fmt.text(`⚠ ${stillChangingNote(options.action ?? 'action', result.pending)}`);
314
+ }
315
+ fmt.blank();
316
+ fmt.keyValueList(details, keyWidth);
317
+ if (result.navigation)
318
+ fmt.keyValue('Page', pageNavigationText(result.navigation), keyWidth);
319
+ listRows(fmt, 'New text', (result.messages ?? []).map(newMessageText), keyWidth);
320
+ listRows(fmt, 'Shown', (result.shown ?? []).map(shownElementText), keyWidth);
321
+ const omitted = result.triggeredRequestsOmitted;
322
+ const requests = formatTriggeredRequestLines(result.triggeredRequests ?? [], omitted);
323
+ if (requests.length > 0) {
324
+ fmt
325
+ .blank()
326
+ .section(formatTriggeredRequestsTitle(result.triggeredRequests ?? [], omitted), requests);
285
327
  }
286
328
  for (const dialog of result.dialogs ?? []) {
287
329
  fmt.blank();
288
330
  fmt.text(`Dialog: ${dialogConsoleText(dialog)}`);
289
331
  }
332
+ return fmt;
333
+ }
334
+ /**
335
+ * Rows of a list under one label: the label on the first row, the rest
336
+ * indented below it.
337
+ *
338
+ * @param fmt - Output being built
339
+ * @param label - Label, e.g. "New text"
340
+ * @param texts - One text per row
341
+ * @param keyWidth - Width of the labels
342
+ */
343
+ function listRows(fmt, label, texts, keyWidth) {
344
+ texts.forEach((text, index) => {
345
+ if (index === 0)
346
+ fmt.keyValue(label, text, keyWidth);
347
+ else
348
+ fmt.text(' '.repeat(keyWidth) + text);
349
+ });
350
+ }
351
+ /**
352
+ * Row naming the element an action hit, e.g.
353
+ * `Element: input.toggle in div.view "Write report"` (just its tag when the
354
+ * page could not describe it), with the list a numeric index refers to
355
+ * (`(index 0 of the last dom query "h3")`).
356
+ *
357
+ * @param result - Action result
358
+ * @returns Label/value row
359
+ */
360
+ function elementRow(result) {
361
+ const source = result.indexSource ? ` (${indexSourceText(result.indexSource)})` : '';
362
+ if (result.element === undefined) {
363
+ return ['Element Type', `${result.elementType ?? 'unknown'}${source}`];
364
+ }
365
+ const viaLabel = result.elementType?.endsWith(VIA_LABEL_SUFFIX) ? VIA_LABEL_SUFFIX : '';
366
+ return ['Element', `${result.element}${viaLabel}${source}`];
367
+ }
368
+ /**
369
+ * Selector row of an action's output; none for an index into a11y query
370
+ * results, whose "selector" is the a11y pattern (the element row names it).
371
+ *
372
+ * @param result - Action result
373
+ * @returns The row, or none
374
+ */
375
+ function selectorRows(result) {
376
+ if (result.indexSource?.command === 'dom a11y query')
377
+ return [];
378
+ return [['Selector', result.selector ?? 'unknown']];
290
379
  }
291
380
  /**
292
381
  * Format fill command output for human-readable display.
293
382
  */
294
383
  function formatFillOutput(result) {
295
- const fmt = new OutputFormatter();
296
- fmt.text('✓ Element Filled');
297
- fmt.blank();
298
- const details = [
299
- ['Selector', result.selector ?? 'unknown'],
300
- ['Element Type', result.elementType ?? 'unknown'],
301
- ];
384
+ const details = [...selectorRows(result), elementRow(result)];
302
385
  if (result.inputType)
303
386
  details.push(['Input Type', result.inputType]);
304
387
  if (result.checked !== undefined) {
305
388
  details.push(['Checked', result.checked ? 'true' : 'false']);
306
389
  }
307
- else if (result.value) {
308
- details.push(['Value', result.value]);
390
+ else if (result.value !== undefined) {
391
+ details.push(['Value', result.value === '' ? '(empty)' : result.value]);
309
392
  }
310
- fmt.keyValueList(details, 15);
311
- appendNotices(fmt, result);
312
- return fmt.build();
393
+ return formatActionOutput('Element Filled', details, result).build();
313
394
  }
314
395
  /**
315
396
  * Format click command output for human-readable display.
316
397
  */
317
398
  function formatClickOutput(result) {
318
- const fmt = new OutputFormatter();
319
- fmt.text(`✓ Element ${POINTER_ACTION_DONE[result.action ?? 'click']}`);
320
- fmt.blank();
321
- fmt.keyValueList([
322
- ['Selector', result.selector ?? 'unknown'],
323
- ['Element Type', result.elementType ?? 'unknown'],
399
+ return formatActionOutput(`Element ${POINTER_ACTION_DONE[result.action ?? 'click']}`, [
400
+ ...selectorRows(result),
401
+ elementRow(result),
324
402
  ['Method', result.method === 'dom' ? 'DOM events' : 'mouse events'],
325
- ], 15);
326
- appendNotices(fmt, result);
327
- return fmt.build();
403
+ ], result, { action: POINTER_ACTION_NOUN[result.action ?? 'click'] }).build();
328
404
  }
329
405
  /**
330
406
  * Format submit command output for human-readable display.
331
407
  */
332
408
  function formatSubmitOutput(result) {
333
- const fmt = new OutputFormatter();
334
- fmt.text('✓ Form Submitted');
335
- fmt.blank();
336
409
  const details = [
337
- ['Selector', result.selector ?? 'unknown'],
410
+ ...selectorRows(result),
411
+ ...(result.element !== undefined ? [elementRow(result)] : []),
338
412
  ['Submit Button', result.clicked ? 'used' : 'none'],
339
413
  ];
340
414
  if (result.networkRequests !== undefined)
341
415
  details.push(['Network Requests', result.networkRequests.toString()]);
342
- if (result.navigationOccurred !== undefined)
343
- details.push(['Navigation', result.navigationOccurred ? 'yes' : 'no']);
416
+ if (result.navigationOccurred === false)
417
+ details.push(['Navigation', 'no']);
418
+ if (result.navigationOccurred && !result.navigation)
419
+ details.push(['Navigation', 'yes']);
344
420
  if (result.waitTimeMs !== undefined)
345
421
  details.push(['Wait Time', `${result.waitTimeMs}ms`]);
346
- fmt.keyValueList(details, 20);
347
- appendNotices(fmt, result);
422
+ const fmt = formatActionOutput('Form Submitted', details, result, {
423
+ keyWidth: 20,
424
+ action: 'submit',
425
+ });
348
426
  fmt.hints('Next steps:', [
349
- 'bdg network list --last 10 Check network requests',
350
- 'bdg console --last 5 Check console messages',
351
- 'bdg status Check session state',
427
+ `${sessionCommand('bdg network list --last 10').padEnd(32)} Check network requests`,
428
+ `${sessionCommand('bdg console --last 5').padEnd(32)} Check console messages`,
429
+ `${sessionCommand('bdg status').padEnd(32)} Check session state`,
352
430
  ]);
353
431
  return fmt.build();
354
432
  }
@@ -356,42 +434,34 @@ function formatSubmitOutput(result) {
356
434
  * Format pressKey command output for human-readable display.
357
435
  */
358
436
  function formatPressKeyOutput(result) {
359
- const fmt = new OutputFormatter();
360
- fmt.text('✓ Key Pressed');
361
- fmt.blank();
362
437
  const details = [
363
438
  ['Key', result.key ?? 'unknown'],
364
- ['Selector', result.selector ?? 'unknown'],
365
- ['Element Type', result.elementType ?? 'unknown'],
439
+ ...selectorRows(result),
440
+ elementRow(result),
366
441
  ];
367
442
  if (result.times && result.times > 1)
368
443
  details.push(['Times', result.times.toString()]);
369
444
  if (result.modifiers?.length)
370
445
  details.push(['Modifiers', result.modifiers.join('+')]);
371
- fmt.keyValueList(details, 15);
372
- appendNotices(fmt, result);
373
- return fmt.build();
446
+ return formatActionOutput('Key Pressed', details, result, { action: 'key press' }).build();
374
447
  }
375
448
  /**
376
449
  * Format scroll command output for human-readable display.
377
450
  */
378
451
  function formatScrollOutput(result) {
379
- const fmt = new OutputFormatter();
380
- fmt.text('✓ Page Scrolled');
381
- fmt.blank();
382
452
  const details = [['Scroll Type', result.scrollType]];
383
453
  if (result.selector)
384
- details.push(['Selector', result.selector]);
454
+ details.push(...selectorRows(result));
455
+ if (result.element)
456
+ details.push(elementRow(result));
385
457
  if (result.scrolledTo)
386
458
  details.push(['Position', `(${result.scrolledTo.x}, ${result.scrolledTo.y})`]);
387
459
  if (result.scrolledBy && (result.scrolledBy.x !== 0 || result.scrolledBy.y !== 0))
388
460
  details.push(['Scrolled By', `(${result.scrolledBy.x}, ${result.scrolledBy.y})`]);
389
461
  if (result.viewportSize)
390
- details.push(['Viewport', `${result.viewportSize.width}x${result.viewportSize.height}`]);
462
+ details.push(['Viewport', `${result.viewportSize.width}×${result.viewportSize.height}`]);
391
463
  if (result.pageSize)
392
- details.push(['Page Size', `${result.pageSize.width}x${result.pageSize.height}`]);
393
- fmt.keyValueList(details, 15);
394
- appendNotices(fmt, result);
395
- return fmt.build();
464
+ details.push(['Page Size', `${result.pageSize.width}×${result.pageSize.height}`]);
465
+ return formatActionOutput('Page Scrolled', details, result).build();
396
466
  }
397
467
  //# sourceMappingURL=formInteraction.js.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Readiness of a discovered form (`bdg dom form`): which fields are filled,
3
+ * which required ones are still empty, and which button submits it.
4
+ */
5
+ import type { FormButton, FormField, FormSummary, RawButton, RawForm } from '../../runtime/dom/formTypes.js';
6
+ /**
7
+ * Fields a user fills as one: the options of a radio or checkbox group (same
8
+ * name in the same form), or a single field.
9
+ *
10
+ * @param fields - Form fields
11
+ * @returns Groups, in the order their first field appears
12
+ */
13
+ export declare function groupFields(fields: FormField[]): FormField[][];
14
+ /**
15
+ * Summarize a form's state. Only visible, editable fields count, and a radio
16
+ * or checkbox group counts once (filled when any option is checked; required
17
+ * when any option is). The form is ready when nothing blocks it and at least
18
+ * one field is filled (an untouched form is not ready), or it has no fields.
19
+ *
20
+ * @param fields - Form fields
21
+ * @param buttons - Form buttons
22
+ * @returns Form summary
23
+ */
24
+ export declare function calculateSummary(fields: FormField[], buttons: FormButton[]): FormSummary;
25
+ /**
26
+ * The button that submits the form, as a user would pick it. Buttons that
27
+ * cancel, reset, go back or delete ({@link DISMISSIVE_BUTTON_LABEL}) never
28
+ * are. Then, in order: a button written as a submit button
29
+ * (`type="submit"`, `<input type=submit>`); among the form's untyped
30
+ * `<button>`s (each submits it) one styled as primary, else the last one
31
+ * (forms put Cancel or Back first); else any button styled as primary.
32
+ * Buttons outside a form submit nothing, so only their style counts.
33
+ *
34
+ * @param buttons - Raw buttons of one form
35
+ * @returns Index of the primary button, or undefined when there is none
36
+ */
37
+ export declare function primaryButtonIndex(buttons: RawButton[]): number | undefined;
38
+ /**
39
+ * Put forms in listing order (by {@link visibilityRank}, then by relevance)
40
+ * and number them, their fields and their buttons in that order, so the
41
+ * first field listed is 0 and `bdg dom fill <index>` / `click <index>` reach
42
+ * the element listed with that index (the indices are cached in this order).
43
+ * Within a form, fields come before buttons, both in document order.
44
+ *
45
+ * @param forms - Raw forms in document order
46
+ * @returns Forms in listing order, renumbered (the input is not changed)
47
+ */
48
+ export declare function orderForms(forms: RawForm[]): RawForm[];
49
+ //# sourceMappingURL=formSummary.d.ts.map