browser-debugger-cli 0.6.5 → 0.6.7

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 (223) hide show
  1. package/README.md +48 -269
  2. package/dist/commands/__tests__/helpJson.contract.test.d.ts +12 -0
  3. package/dist/commands/__tests__/helpJson.contract.test.d.ts.map +1 -0
  4. package/dist/commands/__tests__/helpJson.contract.test.js +121 -0
  5. package/dist/commands/__tests__/helpJson.contract.test.js.map +1 -0
  6. package/dist/commands/__tests__/machineReadableHelp.contract.test.js +26 -7
  7. package/dist/commands/__tests__/machineReadableHelp.contract.test.js.map +1 -1
  8. package/dist/commands/cdp.d.ts.map +1 -1
  9. package/dist/commands/cdp.js.map +1 -1
  10. package/dist/commands/cleanup.d.ts.map +1 -1
  11. package/dist/commands/cleanup.js +17 -91
  12. package/dist/commands/cleanup.js.map +1 -1
  13. package/dist/commands/console.d.ts.map +1 -1
  14. package/dist/commands/console.js.map +1 -1
  15. package/dist/commands/details.d.ts.map +1 -1
  16. package/dist/commands/details.js +3 -1
  17. package/dist/commands/details.js.map +1 -1
  18. package/dist/commands/dom/DomElementResolver.d.ts +138 -0
  19. package/dist/commands/dom/DomElementResolver.d.ts.map +1 -0
  20. package/dist/commands/dom/DomElementResolver.js +173 -0
  21. package/dist/commands/dom/DomElementResolver.js.map +1 -0
  22. package/dist/commands/dom/a11y.d.ts.map +1 -1
  23. package/dist/commands/dom/a11y.js +37 -33
  24. package/dist/commands/dom/a11y.js.map +1 -1
  25. package/dist/commands/dom/evalHelpers.d.ts.map +1 -1
  26. package/dist/commands/dom/evalHelpers.js +1 -1
  27. package/dist/commands/dom/evalHelpers.js.map +1 -1
  28. package/dist/commands/dom/formFillHelpers.d.ts +68 -2
  29. package/dist/commands/dom/formFillHelpers.d.ts.map +1 -1
  30. package/dist/commands/dom/formFillHelpers.js +216 -70
  31. package/dist/commands/dom/formFillHelpers.js.map +1 -1
  32. package/dist/commands/dom/formInteraction.d.ts.map +1 -1
  33. package/dist/commands/dom/formInteraction.js +128 -15
  34. package/dist/commands/dom/formInteraction.js.map +1 -1
  35. package/dist/commands/dom/helpers.d.ts +11 -2
  36. package/dist/commands/dom/helpers.d.ts.map +1 -1
  37. package/dist/commands/dom/helpers.js +50 -1
  38. package/dist/commands/dom/helpers.js.map +1 -1
  39. package/dist/commands/dom/index.d.ts.map +1 -1
  40. package/dist/commands/dom/index.js +105 -52
  41. package/dist/commands/dom/index.js.map +1 -1
  42. package/dist/commands/dom/keyMapping.d.ts +56 -0
  43. package/dist/commands/dom/keyMapping.d.ts.map +1 -0
  44. package/dist/commands/dom/keyMapping.js +110 -0
  45. package/dist/commands/dom/keyMapping.js.map +1 -0
  46. package/dist/commands/dom/reactEventHelpers.d.ts +19 -20
  47. package/dist/commands/dom/reactEventHelpers.d.ts.map +1 -1
  48. package/dist/commands/dom/reactEventHelpers.js +73 -80
  49. package/dist/commands/dom/reactEventHelpers.js.map +1 -1
  50. package/dist/commands/helpJson.d.ts +165 -0
  51. package/dist/commands/helpJson.d.ts.map +1 -0
  52. package/dist/commands/helpJson.js +252 -0
  53. package/dist/commands/helpJson.js.map +1 -0
  54. package/dist/commands/machineReadableHelp.d.ts +21 -2
  55. package/dist/commands/machineReadableHelp.d.ts.map +1 -1
  56. package/dist/commands/machineReadableHelp.js +95 -60
  57. package/dist/commands/machineReadableHelp.js.map +1 -1
  58. package/dist/commands/network.d.ts.map +1 -1
  59. package/dist/commands/network.js.map +1 -1
  60. package/dist/commands/peek.d.ts.map +1 -1
  61. package/dist/commands/peek.js +20 -13
  62. package/dist/commands/peek.js.map +1 -1
  63. package/dist/commands/shared/CommandRunner.d.ts +4 -10
  64. package/dist/commands/shared/CommandRunner.d.ts.map +1 -1
  65. package/dist/commands/shared/CommandRunner.js +2 -2
  66. package/dist/commands/shared/CommandRunner.js.map +1 -1
  67. package/dist/commands/shared/commonOptions.d.ts +0 -15
  68. package/dist/commands/shared/commonOptions.d.ts.map +1 -1
  69. package/dist/commands/shared/commonOptions.js +0 -32
  70. package/dist/commands/shared/commonOptions.js.map +1 -1
  71. package/dist/commands/shared/optionTypes.d.ts +237 -0
  72. package/dist/commands/shared/optionTypes.d.ts.map +1 -0
  73. package/dist/commands/shared/optionTypes.js +20 -0
  74. package/dist/commands/shared/optionTypes.js.map +1 -0
  75. package/dist/commands/shared/startHelpers.d.ts.map +1 -1
  76. package/dist/commands/shared/startHelpers.js +3 -3
  77. package/dist/commands/shared/startHelpers.js.map +1 -1
  78. package/dist/commands/start.d.ts.map +1 -1
  79. package/dist/commands/start.js +8 -6
  80. package/dist/commands/start.js.map +1 -1
  81. package/dist/commands/status.d.ts.map +1 -1
  82. package/dist/commands/status.js.map +1 -1
  83. package/dist/commands/stop.d.ts.map +1 -1
  84. package/dist/commands/stop.js +17 -43
  85. package/dist/commands/stop.js.map +1 -1
  86. package/dist/commands/tail.d.ts.map +1 -1
  87. package/dist/commands/tail.js +49 -59
  88. package/dist/commands/tail.js.map +1 -1
  89. package/dist/connection/types.d.ts +2 -1
  90. package/dist/connection/types.d.ts.map +1 -1
  91. package/dist/constants.d.ts +19 -1
  92. package/dist/constants.d.ts.map +1 -1
  93. package/dist/constants.js +45 -2
  94. package/dist/constants.js.map +1 -1
  95. package/dist/daemon/handlers/responseHandler.d.ts.map +1 -1
  96. package/dist/daemon/handlers/responseHandler.js +1 -0
  97. package/dist/daemon/handlers/responseHandler.js.map +1 -1
  98. package/dist/daemon/ipcServer.js +8 -8
  99. package/dist/daemon/ipcServer.js.map +1 -1
  100. package/dist/daemon/lifecycle/signalHandlers.d.ts.map +1 -1
  101. package/dist/daemon/lifecycle/signalHandlers.js +19 -3
  102. package/dist/daemon/lifecycle/signalHandlers.js.map +1 -1
  103. package/dist/daemon/lifecycle/workerCleanup.d.ts.map +1 -1
  104. package/dist/daemon/lifecycle/workerCleanup.js +5 -2
  105. package/dist/daemon/lifecycle/workerCleanup.js.map +1 -1
  106. package/dist/daemon/patternDefinitions.d.ts +0 -13
  107. package/dist/daemon/patternDefinitions.d.ts.map +1 -1
  108. package/dist/daemon/patternDefinitions.js +0 -17
  109. package/dist/daemon/patternDefinitions.js.map +1 -1
  110. package/dist/daemon/worker/commandRegistry.d.ts.map +1 -1
  111. package/dist/daemon/worker/commandRegistry.js +1 -0
  112. package/dist/daemon/worker/commandRegistry.js.map +1 -1
  113. package/dist/index.js +34 -2
  114. package/dist/index.js.map +1 -1
  115. package/dist/ipc/__tests__/jsonl.unit.test.js +5 -5
  116. package/dist/ipc/__tests__/jsonl.unit.test.js.map +1 -1
  117. package/dist/ipc/protocol/commands.d.ts +2 -0
  118. package/dist/ipc/protocol/commands.d.ts.map +1 -1
  119. package/dist/ipc/protocol/commands.js.map +1 -1
  120. package/dist/ipc/session/queries.d.ts +2 -0
  121. package/dist/ipc/session/queries.d.ts.map +1 -1
  122. package/dist/ipc/utils/responseValidator.d.ts +7 -1
  123. package/dist/ipc/utils/responseValidator.d.ts.map +1 -1
  124. package/dist/ipc/utils/responseValidator.js +6 -1
  125. package/dist/ipc/utils/responseValidator.js.map +1 -1
  126. package/dist/session/QueryCacheManager.d.ts +140 -0
  127. package/dist/session/QueryCacheManager.d.ts.map +1 -0
  128. package/dist/session/QueryCacheManager.js +233 -0
  129. package/dist/session/QueryCacheManager.js.map +1 -0
  130. package/dist/session/cleanup.d.ts +63 -1
  131. package/dist/session/cleanup.d.ts.map +1 -1
  132. package/dist/session/cleanup.js +191 -65
  133. package/dist/session/cleanup.js.map +1 -1
  134. package/dist/session/queryCache.d.ts +25 -14
  135. package/dist/session/queryCache.d.ts.map +1 -1
  136. package/dist/session/queryCache.js +31 -60
  137. package/dist/session/queryCache.js.map +1 -1
  138. package/dist/telemetry/__tests__/roleInference.unit.test.d.ts +9 -0
  139. package/dist/telemetry/__tests__/roleInference.unit.test.d.ts.map +1 -0
  140. package/dist/telemetry/__tests__/roleInference.unit.test.js +138 -0
  141. package/dist/telemetry/__tests__/roleInference.unit.test.js.map +1 -0
  142. package/dist/telemetry/dom.d.ts +1 -0
  143. package/dist/telemetry/dom.d.ts.map +1 -1
  144. package/dist/telemetry/dom.js +9 -4
  145. package/dist/telemetry/dom.js.map +1 -1
  146. package/dist/telemetry/filters.d.ts +3 -0
  147. package/dist/telemetry/filters.d.ts.map +1 -1
  148. package/dist/telemetry/filters.js +25 -3
  149. package/dist/telemetry/filters.js.map +1 -1
  150. package/dist/telemetry/network.d.ts.map +1 -1
  151. package/dist/telemetry/network.js +35 -6
  152. package/dist/telemetry/network.js.map +1 -1
  153. package/dist/telemetry/roleInference.d.ts +50 -0
  154. package/dist/telemetry/roleInference.d.ts.map +1 -0
  155. package/dist/telemetry/roleInference.js +163 -0
  156. package/dist/telemetry/roleInference.js.map +1 -0
  157. package/dist/telemetry/utils.d.ts +0 -57
  158. package/dist/telemetry/utils.d.ts.map +1 -1
  159. package/dist/telemetry/utils.js +0 -71
  160. package/dist/telemetry/utils.js.map +1 -1
  161. package/dist/types/dom.d.ts +11 -0
  162. package/dist/types/dom.d.ts.map +1 -1
  163. package/dist/types.d.ts +2 -0
  164. package/dist/types.d.ts.map +1 -1
  165. package/dist/ui/formatters/a11y.d.ts +13 -3
  166. package/dist/ui/formatters/a11y.d.ts.map +1 -1
  167. package/dist/ui/formatters/a11y.js +18 -3
  168. package/dist/ui/formatters/a11y.js.map +1 -1
  169. package/dist/ui/formatters/preview.d.ts +4 -0
  170. package/dist/ui/formatters/preview.d.ts.map +1 -1
  171. package/dist/ui/formatters/preview.js +26 -43
  172. package/dist/ui/formatters/preview.js.map +1 -1
  173. package/dist/ui/formatters/sessionFormatters.d.ts.map +1 -1
  174. package/dist/ui/formatters/sessionFormatters.js +2 -0
  175. package/dist/ui/formatters/sessionFormatters.js.map +1 -1
  176. package/dist/ui/logging/index.d.ts +1 -1
  177. package/dist/ui/logging/index.d.ts.map +1 -1
  178. package/dist/ui/logging/index.js +1 -1
  179. package/dist/ui/logging/index.js.map +1 -1
  180. package/dist/ui/logging/logger.d.ts +21 -0
  181. package/dist/ui/logging/logger.d.ts.map +1 -1
  182. package/dist/ui/logging/logger.js +24 -6
  183. package/dist/ui/logging/logger.js.map +1 -1
  184. package/dist/ui/messages/commands.d.ts +0 -14
  185. package/dist/ui/messages/commands.d.ts.map +1 -1
  186. package/dist/ui/messages/commands.js +0 -18
  187. package/dist/ui/messages/commands.js.map +1 -1
  188. package/dist/ui/messages/errors.d.ts +0 -16
  189. package/dist/ui/messages/errors.d.ts.map +1 -1
  190. package/dist/ui/messages/errors.js +0 -18
  191. package/dist/ui/messages/errors.js.map +1 -1
  192. package/dist/ui/messages/hints.d.ts +0 -10
  193. package/dist/ui/messages/hints.d.ts.map +1 -1
  194. package/dist/ui/messages/hints.js +0 -12
  195. package/dist/ui/messages/hints.js.map +1 -1
  196. package/dist/utils/decisionTrees.d.ts +0 -17
  197. package/dist/utils/decisionTrees.d.ts.map +1 -1
  198. package/dist/utils/decisionTrees.js +5 -21
  199. package/dist/utils/decisionTrees.js.map +1 -1
  200. package/dist/utils/errorMapping.d.ts +60 -0
  201. package/dist/utils/errorMapping.d.ts.map +1 -0
  202. package/dist/utils/errorMapping.js +97 -0
  203. package/dist/utils/errorMapping.js.map +1 -0
  204. package/dist/utils/file.d.ts +27 -0
  205. package/dist/utils/file.d.ts.map +1 -0
  206. package/dist/utils/file.js +37 -0
  207. package/dist/utils/file.js.map +1 -0
  208. package/dist/utils/levenshtein.d.ts +0 -17
  209. package/dist/utils/levenshtein.d.ts.map +1 -1
  210. package/dist/utils/levenshtein.js +0 -31
  211. package/dist/utils/levenshtein.js.map +1 -1
  212. package/dist/utils/taskMappings.d.ts +0 -17
  213. package/dist/utils/taskMappings.d.ts.map +1 -1
  214. package/dist/utils/taskMappings.js +5 -21
  215. package/dist/utils/taskMappings.js.map +1 -1
  216. package/dist/utils/typeGuards.d.ts +62 -0
  217. package/dist/utils/typeGuards.d.ts.map +1 -0
  218. package/dist/utils/typeGuards.js +94 -0
  219. package/dist/utils/typeGuards.js.map +1 -0
  220. package/dist/utils/url.d.ts.map +1 -1
  221. package/dist/utils/url.js +15 -2
  222. package/dist/utils/url.js.map +1 -1
  223. package/package.json +1 -1
@@ -8,11 +8,13 @@
8
8
  *
9
9
  * Uses IPC/callCDP pattern for consistency with other DOM commands.
10
10
  */
11
+ import { DomElementResolver } from '../../commands/dom/DomElementResolver.js';
12
+ import { getDomContext } from '../../commands/dom/helpers.js';
11
13
  import { runCommand } from '../../commands/shared/CommandRunner.js';
12
14
  import { jsonOption } from '../../commands/shared/commonOptions.js';
13
15
  import { collectA11yTree, queryA11yTree, parseQueryPattern, resolveA11yNode, } from '../../telemetry/a11y.js';
14
16
  import { CommandError } from '../../ui/errors/index.js';
15
- import { formatA11yTree, formatA11yQueryResult, formatA11yNode } from '../../ui/formatters/a11y.js';
17
+ import { formatA11yTree, formatA11yQueryResult, formatA11yNodeWithContext, } from '../../ui/formatters/a11y.js';
16
18
  import { elementNotFoundError } from '../../ui/messages/errors.js';
17
19
  import { EXIT_CODES } from '../../utils/exitCodes.js';
18
20
  /**
@@ -72,38 +74,13 @@ async function handleA11yQuery(pattern, options) {
72
74
  return { success: true, data: result };
73
75
  }, options, formatA11yQueryResult);
74
76
  }
75
- /**
76
- * Retrieve cached node by index with validation.
77
- *
78
- * @param index - Zero-based index from query results
79
- * @returns Node from cache
80
- * @throws CommandError if cache missing, index out of range, or node not found
81
- */
82
- async function getCachedNodeByIndex(index) {
83
- const { getSessionQueryCache } = await import('../../session/queryCache.js');
84
- const cachedQuery = getSessionQueryCache();
85
- if (!cachedQuery) {
86
- throw new CommandError('No cached query results found', {
87
- suggestion: 'Run "bdg dom query <selector>" first to generate indexed results',
88
- }, EXIT_CODES.INVALID_ARGUMENTS);
89
- }
90
- if (index < 0 || index >= cachedQuery.nodes.length) {
91
- throw new CommandError(`Index ${index} out of range (found ${cachedQuery.nodes.length} elements)`, {
92
- suggestion: `Use an index between 0 and ${cachedQuery.nodes.length - 1}`,
93
- }, EXIT_CODES.INVALID_ARGUMENTS);
94
- }
95
- const targetNode = cachedQuery.nodes[index];
96
- if (!targetNode) {
97
- throw new CommandError(`Element at index ${index} not found`, {}, EXIT_CODES.RESOURCE_NOT_FOUND);
98
- }
99
- return targetNode;
100
- }
101
77
  /**
102
78
  * Handle bdg dom a11y describe <selectorOrIndex> command
103
79
  *
104
80
  * Gets accessibility properties for a DOM element by CSS selector or numeric index.
105
81
  * Supports index-based access from query results (e.g., "bdg dom a11y describe 0").
106
82
  * Useful for understanding how an element is exposed to assistive technologies.
83
+ * Includes DOM context (tag, classes, text preview) when a11y data is sparse.
107
84
  *
108
85
  * @param selectorOrIndex - CSS selector (e.g., "button.submit") or numeric index from query results
109
86
  * @param options - Command options
@@ -117,13 +94,16 @@ async function getCachedNodeByIndex(index) {
117
94
  * ```
118
95
  */
119
96
  async function handleA11yDescribe(selectorOrIndex, options) {
120
- const isNumericIndex = /^\d+$/.test(selectorOrIndex);
97
+ const resolver = DomElementResolver.getInstance();
98
+ const isNumericIndex = resolver.isNumericIndex(selectorOrIndex);
121
99
  await runCommand(async () => {
122
100
  let node;
101
+ let nodeId;
123
102
  if (isNumericIndex) {
124
103
  const index = parseInt(selectorOrIndex, 10);
125
- const targetNode = await getCachedNodeByIndex(index);
126
- node = await resolveA11yNode('', targetNode.nodeId);
104
+ const targetNode = await resolver.getNodeIdForIndex(index);
105
+ nodeId = targetNode.nodeId;
106
+ node = await resolveA11yNode('', nodeId);
127
107
  }
128
108
  else {
129
109
  node = await resolveA11yNode(selectorOrIndex);
@@ -131,8 +111,13 @@ async function handleA11yDescribe(selectorOrIndex, options) {
131
111
  if (!node) {
132
112
  throw new CommandError(elementNotFoundError(selectorOrIndex), {}, EXIT_CODES.RESOURCE_NOT_FOUND);
133
113
  }
134
- return { success: true, data: node };
135
- }, options, formatA11yNode);
114
+ let domContext = null;
115
+ const domNodeId = node.backendDOMNodeId ?? nodeId;
116
+ if (domNodeId) {
117
+ domContext = await getDomContext(domNodeId);
118
+ }
119
+ return { success: true, data: { node, domContext } };
120
+ }, options, formatA11yNodeWithContext);
136
121
  }
137
122
  /**
138
123
  * Register accessibility commands under 'bdg dom a11y'
@@ -142,7 +127,26 @@ async function handleA11yDescribe(selectorOrIndex, options) {
142
127
  export function registerA11yCommands(domCmd) {
143
128
  const a11y = domCmd
144
129
  .command('a11y')
145
- .description('Accessibility tree inspection and semantic queries');
130
+ .description('Accessibility tree inspection and semantic queries')
131
+ .argument('[search]', 'Quick search: index (describe), pattern with ":" (query), or name search')
132
+ .addOption(jsonOption)
133
+ .action(async (search, options) => {
134
+ if (!search) {
135
+ a11y.help();
136
+ return;
137
+ }
138
+ const isNumericIndex = /^\d+$/.test(search);
139
+ const isPatternQuery = search.includes(':') || search.includes('=');
140
+ if (isNumericIndex) {
141
+ await handleA11yDescribe(search, options);
142
+ }
143
+ else if (isPatternQuery) {
144
+ await handleA11yQuery(search, options);
145
+ }
146
+ else {
147
+ await handleA11yQuery(`name:*${search}*`, options);
148
+ }
149
+ });
146
150
  a11y
147
151
  .command('tree')
148
152
  .description('Dump full accessibility tree (filters ignored nodes)')
@@ -1 +1 @@
1
- {"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../../src/commands/dom/a11y.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../../src/commands/dom/a11y.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"evalHelpers.d.ts","sourceRoot":"","sources":["../../../src/commands/dom/evalHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuDlF;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAU9C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,eAAe,CAY7D;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB/F;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAyB5C"}
1
+ {"version":3,"file":"evalHelpers.d.ts","sourceRoot":"","sources":["../../../src/commands/dom/evalHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuDlF;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAU9C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,eAAe,CAY7D;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB/F;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CA6B5C"}
@@ -111,7 +111,7 @@ export async function executeScript(cdp, script) {
111
111
  }
112
112
  if (response.exceptionDetails) {
113
113
  const errorMsg = response.exceptionDetails.exception?.description ?? 'Unknown error executing script';
114
- throw new Error(errorMsg);
114
+ throw new CommandError(errorMsg, { note: 'Script execution failed in browser context' }, EXIT_CODES.SOFTWARE_ERROR);
115
115
  }
116
116
  return response;
117
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"evalHelpers.js","sourceRoot":"","sources":["../../../src/commands/dom/evalHelpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"evalHelpers.js","sourceRoot":"","sources":["../../../src/commands/dom/evalHelpers.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ import { type FillOptions, type FillResult, type ClickResult } from './reactEven
9
9
  * @param cdp - CDP connection
10
10
  * @param selector - CSS selector for the element
11
11
  * @param value - Value to fill
12
- * @param options - Fill options
12
+ * @param options - Fill options including optional index for multiple matches
13
13
  * @returns Promise resolving to fill result
14
14
  *
15
15
  * @throws CommandError When element operations fail
@@ -28,7 +28,7 @@ export declare function fillElement(cdp: CDPConnection, selector: string, value:
28
28
  *
29
29
  * @param cdp - CDP connection
30
30
  * @param selector - CSS selector for the element
31
- * @param options - Click options
31
+ * @param options - Click options including optional index for multiple matches
32
32
  * @returns Promise resolving to click result
33
33
  *
34
34
  * @throws CommandError When element operations fail
@@ -44,4 +44,70 @@ export declare function fillElement(cdp: CDPConnection, selector: string, value:
44
44
  export declare function clickElement(cdp: CDPConnection, selector: string, options?: {
45
45
  index?: number;
46
46
  }): Promise<ClickResult>;
47
+ /**
48
+ * Wait for page to stabilize after an action (click, fill, etc.).
49
+ *
50
+ * This is a lightweight stability check designed for post-action waiting:
51
+ * - Waits for network to be idle for 150ms
52
+ * - Times out after 2s to avoid hanging
53
+ * - Does not block on slow background requests
54
+ *
55
+ * @param cdp - CDP connection
56
+ * @returns Promise that resolves when stable or timeout reached
57
+ *
58
+ * @remarks
59
+ * This is intentionally less strict than page readiness on initial load.
60
+ * It's designed to catch immediate reactions to user actions (AJAX, re-renders)
61
+ * without waiting for unrelated background activity.
62
+ */
63
+ export declare function waitForActionStability(cdp: CDPConnection): Promise<void>;
64
+ /**
65
+ * Options for pressing a key on an element.
66
+ */
67
+ export interface PressKeyOptions {
68
+ /** Element index if selector matches multiple (1-based) */
69
+ index?: number;
70
+ /** Number of times to press the key (default: 1) */
71
+ times?: number;
72
+ /** Comma-separated modifier keys (shift, ctrl, alt, meta) */
73
+ modifiers?: string;
74
+ }
75
+ /**
76
+ * Result of pressing a key.
77
+ */
78
+ export interface PressKeyResult {
79
+ success: boolean;
80
+ error?: string;
81
+ selector?: string;
82
+ key?: string;
83
+ times?: number;
84
+ modifiers?: number;
85
+ elementType?: string | undefined;
86
+ }
87
+ /**
88
+ * Press a key on an element.
89
+ *
90
+ * Focuses the element first, then dispatches keyDown and keyUp events via CDP.
91
+ *
92
+ * @param cdp - CDP connection
93
+ * @param selector - CSS selector for the element
94
+ * @param keyName - Key name (e.g., "Enter", "Tab", "a")
95
+ * @param options - Press key options
96
+ * @returns Promise resolving to press key result
97
+ *
98
+ * @throws CommandError When element or key operations fail
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * // Press Enter on a todo input
103
+ * const result = await pressKeyElement(cdp, '.new-todo', 'Enter');
104
+ *
105
+ * // Press Tab 3 times with Shift held
106
+ * const result = await pressKeyElement(cdp, 'input', 'Tab', {
107
+ * times: 3,
108
+ * modifiers: 'shift'
109
+ * });
110
+ * ```
111
+ */
112
+ export declare function pressKeyElement(cdp: CDPConnection, selector: string, keyName: string, options?: PressKeyOptions): Promise<PressKeyResult>;
47
113
  //# sourceMappingURL=formFillHelpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"formFillHelpers.d.ts","sourceRoot":"","sources":["../../../src/commands/dom/formFillHelpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,EAEjB,MAAM,wBAAwB,CAAC;AAqChC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA6DrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,WAAW,CAAC,CAyDtB"}
1
+ {"version":3,"file":"formFillHelpers.d.ts","sourceRoot":"","sources":["../../../src/commands/dom/formFillHelpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AA8ChC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAiDrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,WAAW,CAAC,CA6CtB;AA8BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C9E;AAWD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAuEzB"}
@@ -2,8 +2,17 @@
2
2
  * Form interaction helpers for filling inputs, clicking buttons, etc.
3
3
  */
4
4
  import { CommandError } from '../../ui/errors/index.js';
5
+ import { createLogger } from '../../ui/logging/index.js';
5
6
  import { EXIT_CODES } from '../../utils/exitCodes.js';
6
- import { REACT_FILL_SCRIPT, CLICK_ELEMENT_SCRIPT, GET_ELEMENT_BY_INDEX_SCRIPT, } from './reactEventHelpers.js';
7
+ import { getKeyDefinition, parseModifiers } from './keyMapping.js';
8
+ import { REACT_FILL_SCRIPT, CLICK_ELEMENT_SCRIPT, isFillResult, isClickResult, } from './reactEventHelpers.js';
9
+ const log = createLogger('dom');
10
+ /** Network idle threshold for post-action stability (ms) */
11
+ const ACTION_NETWORK_IDLE_MS = 150;
12
+ /** Maximum time to wait for post-action stability (ms) */
13
+ const ACTION_STABILITY_TIMEOUT_MS = 2000;
14
+ /** Check interval for stability polling (ms) */
15
+ const STABILITY_CHECK_INTERVAL_MS = 50;
7
16
  /**
8
17
  * Format exception details into a user-friendly error message with troubleshooting hints.
9
18
  *
@@ -36,7 +45,7 @@ function formatScriptExecutionError(exceptionDetails, selector, operationType =
36
45
  * @param cdp - CDP connection
37
46
  * @param selector - CSS selector for the element
38
47
  * @param value - Value to fill
39
- * @param options - Fill options
48
+ * @param options - Fill options including optional index for multiple matches
40
49
  * @returns Promise resolving to fill result
41
50
  *
42
51
  * @throws CommandError When element operations fail
@@ -50,33 +59,26 @@ function formatScriptExecutionError(exceptionDetails, selector, operationType =
50
59
  * ```
51
60
  */
52
61
  export async function fillElement(cdp, selector, value, options = {}) {
53
- let targetSelector = selector;
54
- if (options.index !== undefined) {
55
- const indexResult = await getElementByIndex(cdp, selector, options.index);
56
- if (!indexResult.success) {
57
- return indexResult;
58
- }
59
- if (!indexResult.uniqueSelector) {
60
- throw new CommandError('Failed to resolve unique selector for element index', { note: 'Element index resolution returned no unique selector' }, EXIT_CODES.SOFTWARE_ERROR);
61
- }
62
- targetSelector = indexResult.uniqueSelector;
63
- }
64
- const expression = `(${REACT_FILL_SCRIPT})('${escapeSelectorForJS(targetSelector)}', '${escapeValueForJS(value)}', ${JSON.stringify({ blur: options.blur ?? true })})`;
62
+ const scriptOptions = {
63
+ blur: options.blur ?? true,
64
+ index: options.index,
65
+ };
66
+ const expression = `(${REACT_FILL_SCRIPT})('${escapeSelectorForJS(selector)}', '${escapeValueForJS(value)}', ${JSON.stringify(scriptOptions)})`;
65
67
  try {
66
68
  const response = await cdp.send('Runtime.evaluate', {
67
69
  expression,
68
70
  returnByValue: true,
69
- userGesture: true, // Treat as user-initiated action
71
+ userGesture: true,
70
72
  });
71
73
  const cdpResponse = response;
72
74
  if (cdpResponse.exceptionDetails) {
73
75
  const errorMessage = formatScriptExecutionError(cdpResponse.exceptionDetails, selector, 'fill');
74
76
  throw new CommandError(errorMessage, {}, EXIT_CODES.SOFTWARE_ERROR);
75
77
  }
76
- if (cdpResponse.result?.value) {
78
+ if (cdpResponse.result?.value && isFillResult(cdpResponse.result.value)) {
77
79
  return cdpResponse.result.value;
78
80
  }
79
- throw new CommandError('Unexpected response format', { note: 'CDP response missing result.value' }, EXIT_CODES.SOFTWARE_ERROR);
81
+ throw new CommandError('Unexpected response format', { note: 'CDP response missing result.value or invalid FillResult structure' }, EXIT_CODES.SOFTWARE_ERROR);
80
82
  }
81
83
  catch (error) {
82
84
  if (error instanceof CommandError) {
@@ -91,7 +93,7 @@ export async function fillElement(cdp, selector, value, options = {}) {
91
93
  *
92
94
  * @param cdp - CDP connection
93
95
  * @param selector - CSS selector for the element
94
- * @param options - Click options
96
+ * @param options - Click options including optional index for multiple matches
95
97
  * @returns Promise resolving to click result
96
98
  *
97
99
  * @throws CommandError When element operations fail
@@ -105,18 +107,8 @@ export async function fillElement(cdp, selector, value, options = {}) {
105
107
  * ```
106
108
  */
107
109
  export async function clickElement(cdp, selector, options = {}) {
108
- let targetSelector = selector;
109
- if (options.index !== undefined) {
110
- const indexResult = await getElementByIndex(cdp, selector, options.index);
111
- if (!indexResult.success) {
112
- return indexResult;
113
- }
114
- if (!indexResult.uniqueSelector) {
115
- throw new CommandError('Failed to resolve unique selector for element index', { note: 'Element index resolution returned no unique selector' }, EXIT_CODES.SOFTWARE_ERROR);
116
- }
117
- targetSelector = indexResult.uniqueSelector;
118
- }
119
- const expression = `(${CLICK_ELEMENT_SCRIPT})('${escapeSelectorForJS(targetSelector)}')`;
110
+ const indexArg = options.index ?? 'null';
111
+ const expression = `(${CLICK_ELEMENT_SCRIPT})('${escapeSelectorForJS(selector)}', ${indexArg})`;
120
112
  try {
121
113
  const response = await cdp.send('Runtime.evaluate', {
122
114
  expression,
@@ -125,13 +117,13 @@ export async function clickElement(cdp, selector, options = {}) {
125
117
  });
126
118
  const cdpResponse = response;
127
119
  if (cdpResponse.exceptionDetails) {
128
- const errorMessage = formatScriptExecutionError(cdpResponse.exceptionDetails, selector);
120
+ const errorMessage = formatScriptExecutionError(cdpResponse.exceptionDetails, selector, 'click');
129
121
  throw new CommandError(errorMessage, {}, EXIT_CODES.SOFTWARE_ERROR);
130
122
  }
131
- if (cdpResponse.result?.value) {
123
+ if (cdpResponse.result?.value && isClickResult(cdpResponse.result.value)) {
132
124
  return cdpResponse.result.value;
133
125
  }
134
- throw new CommandError('Unexpected response format', { note: 'CDP response missing result.value' }, EXIT_CODES.SOFTWARE_ERROR);
126
+ throw new CommandError('Unexpected response format', { note: 'CDP response missing result.value or invalid ClickResult structure' }, EXIT_CODES.SOFTWARE_ERROR);
135
127
  }
136
128
  catch (error) {
137
129
  if (error instanceof CommandError) {
@@ -142,63 +134,217 @@ export async function clickElement(cdp, selector, options = {}) {
142
134
  }
143
135
  }
144
136
  /**
145
- * Get element by index when selector matches multiple elements.
137
+ * Escape CSS selector for safe inclusion in JavaScript single-quoted string.
138
+ * Uses JSON.stringify for special characters, then escapes single quotes
139
+ * since the expression wrapper uses single quotes.
146
140
  *
147
- * @param cdp - CDP connection
148
- * @param selector - CSS selector
149
- * @param index - Element index (1-based)
150
- * @returns Promise resolving to element info
141
+ * @param selector - CSS selector to escape
142
+ * @returns Escaped selector safe for single-quoted JS string
151
143
  *
152
- * @throws CommandError When element operations fail
144
+ * @internal
145
+ */
146
+ function escapeSelectorForJS(selector) {
147
+ return JSON.stringify(selector).slice(1, -1).replace(/'/g, "\\'");
148
+ }
149
+ /**
150
+ * Escape value for safe inclusion in JavaScript single-quoted string.
151
+ * Uses JSON.stringify for special characters, then escapes single quotes
152
+ * since the expression wrapper uses single quotes.
153
+ *
154
+ * @param value - Value to escape
155
+ * @returns Escaped value safe for single-quoted JS string
153
156
  *
154
157
  * @internal
155
158
  */
156
- async function getElementByIndex(cdp, selector, index) {
157
- const expression = `(${GET_ELEMENT_BY_INDEX_SCRIPT})('${escapeSelectorForJS(selector)}', ${index})`;
159
+ function escapeValueForJS(value) {
160
+ return JSON.stringify(value).slice(1, -1).replace(/'/g, "\\'");
161
+ }
162
+ /**
163
+ * Wait for page to stabilize after an action (click, fill, etc.).
164
+ *
165
+ * This is a lightweight stability check designed for post-action waiting:
166
+ * - Waits for network to be idle for 150ms
167
+ * - Times out after 2s to avoid hanging
168
+ * - Does not block on slow background requests
169
+ *
170
+ * @param cdp - CDP connection
171
+ * @returns Promise that resolves when stable or timeout reached
172
+ *
173
+ * @remarks
174
+ * This is intentionally less strict than page readiness on initial load.
175
+ * It's designed to catch immediate reactions to user actions (AJAX, re-renders)
176
+ * without waiting for unrelated background activity.
177
+ */
178
+ export async function waitForActionStability(cdp) {
179
+ const deadline = Date.now() + ACTION_STABILITY_TIMEOUT_MS;
180
+ let activeRequests = 0;
181
+ let lastActivity = Date.now();
182
+ const onRequestStarted = () => {
183
+ activeRequests++;
184
+ lastActivity = Date.now();
185
+ };
186
+ const onRequestFinished = () => {
187
+ activeRequests--;
188
+ if (activeRequests === 0) {
189
+ lastActivity = Date.now();
190
+ }
191
+ };
192
+ await cdp.send('Network.enable');
193
+ const cleanupRequest = cdp.on('Network.requestWillBeSent', onRequestStarted);
194
+ const cleanupFinished = cdp.on('Network.loadingFinished', onRequestFinished);
195
+ const cleanupFailed = cdp.on('Network.loadingFailed', onRequestFinished);
158
196
  try {
159
- const response = await cdp.send('Runtime.evaluate', {
160
- expression,
197
+ while (Date.now() < deadline) {
198
+ if (activeRequests === 0) {
199
+ const idleTime = Date.now() - lastActivity;
200
+ if (idleTime >= ACTION_NETWORK_IDLE_MS) {
201
+ log.debug(`Network stable after ${idleTime}ms idle`);
202
+ return;
203
+ }
204
+ }
205
+ await delay(STABILITY_CHECK_INTERVAL_MS);
206
+ }
207
+ log.debug('Stability timeout reached, proceeding');
208
+ }
209
+ finally {
210
+ cleanupRequest();
211
+ cleanupFinished();
212
+ cleanupFailed();
213
+ }
214
+ }
215
+ /**
216
+ * Delay utility.
217
+ *
218
+ * @param ms - Milliseconds to delay
219
+ */
220
+ function delay(ms) {
221
+ return new Promise((resolve) => setTimeout(resolve, ms));
222
+ }
223
+ /**
224
+ * Script to focus an element by selector and optional index.
225
+ *
226
+ * @returns Object with success status and element info
227
+ */
228
+ const FOCUS_ELEMENT_SCRIPT = `
229
+ (function(selector, index) {
230
+ const allMatches = document.querySelectorAll(selector);
231
+ if (allMatches.length === 0) {
232
+ return { success: false, error: 'No elements found matching selector: ' + selector };
233
+ }
234
+
235
+ let el;
236
+ if (typeof index === 'number' && index > 0) {
237
+ if (index > allMatches.length) {
238
+ return {
239
+ success: false,
240
+ error: 'Index ' + index + ' out of range (found ' + allMatches.length + ' elements)'
241
+ };
242
+ }
243
+ el = allMatches[index - 1];
244
+ } else {
245
+ el = allMatches[0];
246
+ }
247
+
248
+ el.focus();
249
+
250
+ return {
251
+ success: true,
252
+ selector: selector,
253
+ elementType: el.tagName.toLowerCase(),
254
+ focused: document.activeElement === el
255
+ };
256
+ })`;
257
+ /**
258
+ * Press a key on an element.
259
+ *
260
+ * Focuses the element first, then dispatches keyDown and keyUp events via CDP.
261
+ *
262
+ * @param cdp - CDP connection
263
+ * @param selector - CSS selector for the element
264
+ * @param keyName - Key name (e.g., "Enter", "Tab", "a")
265
+ * @param options - Press key options
266
+ * @returns Promise resolving to press key result
267
+ *
268
+ * @throws CommandError When element or key operations fail
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * // Press Enter on a todo input
273
+ * const result = await pressKeyElement(cdp, '.new-todo', 'Enter');
274
+ *
275
+ * // Press Tab 3 times with Shift held
276
+ * const result = await pressKeyElement(cdp, 'input', 'Tab', {
277
+ * times: 3,
278
+ * modifiers: 'shift'
279
+ * });
280
+ * ```
281
+ */
282
+ export async function pressKeyElement(cdp, selector, keyName, options = {}) {
283
+ const keyDef = getKeyDefinition(keyName);
284
+ if (!keyDef) {
285
+ return {
286
+ success: false,
287
+ error: `Unknown key: "${keyName}". Supported keys: Enter, Tab, Escape, Space, Backspace, Delete, ArrowUp/Down/Left/Right, Home, End, PageUp, PageDown, F1-F12, a-z, 0-9`,
288
+ };
289
+ }
290
+ const times = options.times ?? 1;
291
+ const modifierFlags = parseModifiers(options.modifiers);
292
+ const indexArg = options.index ?? 'null';
293
+ const focusExpression = `(${FOCUS_ELEMENT_SCRIPT})('${escapeSelectorForJS(selector)}', ${indexArg})`;
294
+ try {
295
+ const focusResponse = await cdp.send('Runtime.evaluate', {
296
+ expression: focusExpression,
161
297
  returnByValue: true,
162
298
  });
163
- const cdpResponse = response;
164
- if (cdpResponse.exceptionDetails) {
165
- throw new CommandError('Script execution failed', { note: cdpResponse.exceptionDetails.text ?? 'Unknown error' }, EXIT_CODES.SOFTWARE_ERROR);
299
+ const focusCdpResponse = focusResponse;
300
+ if (focusCdpResponse.exceptionDetails) {
301
+ throw new CommandError(`Failed to focus element: ${focusCdpResponse.exceptionDetails.text}`, { note: `Selector: ${selector}` }, EXIT_CODES.SOFTWARE_ERROR);
166
302
  }
167
- if (cdpResponse.result?.value) {
168
- return cdpResponse.result.value;
303
+ const focusResult = focusCdpResponse.result?.value;
304
+ if (!focusResult?.success) {
305
+ return {
306
+ success: false,
307
+ error: focusResult?.error ?? 'Failed to focus element',
308
+ selector,
309
+ };
169
310
  }
170
- throw new CommandError('Unexpected response format', { note: 'CDP response missing result.value' }, EXIT_CODES.SOFTWARE_ERROR);
311
+ for (let i = 0; i < times; i++) {
312
+ await dispatchKeyEvent(cdp, 'keyDown', keyDef, modifierFlags);
313
+ await dispatchKeyEvent(cdp, 'keyUp', keyDef, modifierFlags);
314
+ }
315
+ return {
316
+ success: true,
317
+ selector,
318
+ key: keyName,
319
+ times,
320
+ modifiers: modifierFlags,
321
+ elementType: focusResult.elementType,
322
+ };
171
323
  }
172
324
  catch (error) {
173
325
  if (error instanceof CommandError) {
174
326
  throw error;
175
327
  }
176
328
  const errorMessage = error instanceof Error ? error.message : String(error);
177
- throw new CommandError('Failed to get element by index', { note: errorMessage }, EXIT_CODES.SOFTWARE_ERROR);
329
+ throw new CommandError('Failed to press key', { note: errorMessage }, EXIT_CODES.SOFTWARE_ERROR);
178
330
  }
179
331
  }
180
332
  /**
181
- * Escape CSS selector for safe inclusion in JavaScript string.
182
- * Uses JSON.stringify to handle all special characters safely.
333
+ * Dispatch a single key event via CDP Input.dispatchKeyEvent.
183
334
  *
184
- * @param selector - CSS selector to escape
185
- * @returns Escaped selector (without surrounding quotes)
186
- *
187
- * @internal
188
- */
189
- function escapeSelectorForJS(selector) {
190
- return JSON.stringify(selector).slice(1, -1);
191
- }
192
- /**
193
- * Escape value for safe inclusion in JavaScript string.
194
- * Uses JSON.stringify to handle all special characters safely.
195
- *
196
- * @param value - Value to escape
197
- * @returns Escaped value (without surrounding quotes)
198
- *
199
- * @internal
335
+ * @param cdp - CDP connection
336
+ * @param type - Event type (keyDown or keyUp)
337
+ * @param keyDef - Key definition with code, key, and keyCode
338
+ * @param modifiers - Modifier bit flags
200
339
  */
201
- function escapeValueForJS(value) {
202
- return JSON.stringify(value).slice(1, -1);
340
+ async function dispatchKeyEvent(cdp, type, keyDef, modifiers) {
341
+ await cdp.send('Input.dispatchKeyEvent', {
342
+ type,
343
+ code: keyDef.code,
344
+ key: keyDef.key,
345
+ windowsVirtualKeyCode: keyDef.keyCode,
346
+ nativeVirtualKeyCode: keyDef.keyCode,
347
+ modifiers,
348
+ });
203
349
  }
204
350
  //# sourceMappingURL=formFillHelpers.js.map