@enekesabel/playwright-lite 0.1.0 → 0.2.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 (3) hide show
  1. package/README.md +85 -85
  2. package/dist/index.mjs +304 -137
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -66,26 +66,26 @@ Targets Playwright **1.62.1**. Statuses describe API compatibility within the ru
66
66
  | [`ariaSnapshot`](https://playwright.dev/docs/api/class-page#page-aria-snapshot) | ✅ | |
67
67
  | [`bringToFront`](https://playwright.dev/docs/api/class-page#page-bring-to-front) | ❌ | |
68
68
  | [`cancelPickLocator`](https://playwright.dev/docs/api/class-page#page-cancel-pick-locator) | ❌ | |
69
- | [`check`](https://playwright.dev/docs/api/class-page#page-check) | ⚠️ | The `signal` option is unsupported. |
69
+ | [`check`](https://playwright.dev/docs/api/class-page#page-check) | ✅ | |
70
70
  | [`clearConsoleMessages`](https://playwright.dev/docs/api/class-page#page-clear-console-messages) | ❌ | |
71
71
  | [`clearPageErrors`](https://playwright.dev/docs/api/class-page#page-clear-page-errors) | ❌ | |
72
- | [`click`](https://playwright.dev/docs/api/class-page#page-click) | ⚠️ | The `signal` option is unsupported. The action does not wait for navigation. |
72
+ | [`click`](https://playwright.dev/docs/api/class-page#page-click) | ⚠️ | The action does not wait for navigation. |
73
73
  | [`clock`](https://playwright.dev/docs/api/class-page#page-clock) | ❌ | |
74
74
  | [`close`](https://playwright.dev/docs/api/class-page#page-close) | ❌ | |
75
75
  | [`consoleMessages`](https://playwright.dev/docs/api/class-page#page-console-messages) | ❌ | |
76
76
  | [`content`](https://playwright.dev/docs/api/class-page#page-content) | ✅ | |
77
77
  | [`context`](https://playwright.dev/docs/api/class-page#page-context) | ❌ | |
78
78
  | [`coverage`](https://playwright.dev/docs/api/class-page#page-coverage) | ❌ | |
79
- | [`dblclick`](https://playwright.dev/docs/api/class-page#page-dblclick) | ⚠️ | The `signal` option is unsupported. |
80
- | [`dispatchEvent`](https://playwright.dev/docs/api/class-page#page-dispatch-event) | ⚠️ | The `signal` option is unsupported; `JSHandle`/`ElementHandle` values in `eventInit` are not unwrapped. |
79
+ | [`dblclick`](https://playwright.dev/docs/api/class-page#page-dblclick) | ✅ | |
80
+ | [`dispatchEvent`](https://playwright.dev/docs/api/class-page#page-dispatch-event) | ⚠️ | `JSHandle`/`ElementHandle` values in `eventInit` are not unwrapped. |
81
81
  | [`dragAndDrop`](https://playwright.dev/docs/api/class-page#page-drag-and-drop) | ❌ | |
82
82
  | [`emulateMedia`](https://playwright.dev/docs/api/class-page#page-emulate-media) | ❌ | |
83
83
  | [`evaluate`](https://playwright.dev/docs/api/class-page#page-evaluate) | ⚠️ | Rejects `exposeFunctions: true`. |
84
84
  | [`evaluateHandle`](https://playwright.dev/docs/api/class-page#page-evaluate-handle) | ❌ | |
85
85
  | [`exposeBinding`](https://playwright.dev/docs/api/class-page#page-expose-binding) | ❌ | |
86
86
  | [`exposeFunction`](https://playwright.dev/docs/api/class-page#page-expose-function) | ❌ | |
87
- | [`fill`](https://playwright.dev/docs/api/class-page#page-fill) | ⚠️ | Multiple matches throw instead of selecting the first match. Unsupported options: `force`, `signal`, `strict`. |
88
- | [`focus`](https://playwright.dev/docs/api/class-page#page-focus) | ⚠️ | Multiple matches throw instead of selecting the first match. Unsupported options: `signal`, `strict`. |
87
+ | [`fill`](https://playwright.dev/docs/api/class-page#page-fill) | ⚠️ | The `force` option is unsupported. |
88
+ | [`focus`](https://playwright.dev/docs/api/class-page#page-focus) | ✅ | |
89
89
  | [`frame`](https://playwright.dev/docs/api/class-page#page-frame) | 🚫 | Iframe realms are outside the single-document boundary. |
90
90
  | [`frameLocator`](https://playwright.dev/docs/api/class-page#page-frame-locator) | 🚫 | Iframe realms are outside the single-document boundary. |
91
91
  | [`frames`](https://playwright.dev/docs/api/class-page#page-frames) | 🚫 | Iframe realms are outside the single-document boundary. |
@@ -101,7 +101,7 @@ Targets Playwright **1.62.1**. Statuses describe API compatibility within the ru
101
101
  | [`goForward`](https://playwright.dev/docs/api/class-page#page-go-forward) | ❌ | |
102
102
  | [`goto`](https://playwright.dev/docs/api/class-page#page-goto) | ⚠️ | Does not return a `Response`; resolves to `null` only for same-document hash navigation. Relative URLs use `document.baseURI`, not a configured Playwright `baseURL`. Rejects `referer`, `signal`, and `waitUntil: "networkidle"`. |
103
103
  | [`hideHighlight`](https://playwright.dev/docs/api/class-page#page-hide-highlight) | ✅ | |
104
- | [`hover`](https://playwright.dev/docs/api/class-page#page-hover) | ⚠️ | The `signal` option is unsupported. |
104
+ | [`hover`](https://playwright.dev/docs/api/class-page#page-hover) | ✅ | |
105
105
  | [`innerHTML`](https://playwright.dev/docs/api/class-page#page-inner-html) | ✅ | |
106
106
  | [`innerText`](https://playwright.dev/docs/api/class-page#page-inner-text) | ✅ | |
107
107
  | [`inputValue`](https://playwright.dev/docs/api/class-page#page-input-value) | ✅ | |
@@ -126,7 +126,7 @@ Targets Playwright **1.62.1**. Statuses describe API compatibility within the ru
126
126
  | [`pdf`](https://playwright.dev/docs/api/class-page#page-pdf) | ❌ | |
127
127
  | [`pickLocator`](https://playwright.dev/docs/api/class-page#page-pick-locator) | ❌ | |
128
128
  | [`prependListener`](https://playwright.dev/docs/events) | ❌ | |
129
- | [`press`](https://playwright.dev/docs/api/class-page#page-press) | ⚠️ | Multiple matches throw instead of selecting the first match. Unsupported options: `delay`, `signal`, `strict`. |
129
+ | [`press`](https://playwright.dev/docs/api/class-page#page-press) | ✅ | |
130
130
  | [`reload`](https://playwright.dev/docs/api/class-page#page-reload) | ❌ | |
131
131
  | [`removeAllListeners`](https://playwright.dev/docs/api/class-page#page-remove-all-listeners) | ❌ | |
132
132
  | [`removeListener`](https://playwright.dev/docs/events) | ❌ | |
@@ -139,21 +139,21 @@ Targets Playwright **1.62.1**. Statuses describe API compatibility within the ru
139
139
  | [`routeWebSocket`](https://playwright.dev/docs/api/class-page#page-route-web-socket) | ❌ | |
140
140
  | [`screencast`](https://playwright.dev/docs/api/class-page#page-screencast) | ❌ | |
141
141
  | [`screenshot`](https://playwright.dev/docs/api/class-page#page-screenshot) | ❌ | |
142
- | [`selectOption`](https://playwright.dev/docs/api/class-page#page-select-option) | ⚠️ | Multiple matches throw instead of selecting the first match. `ElementHandle` option values are unsupported. Unsupported options: `force`, `signal`, `strict`. |
142
+ | [`selectOption`](https://playwright.dev/docs/api/class-page#page-select-option) | ⚠️ | `ElementHandle` option values are unsupported. The `force` option is unsupported. |
143
143
  | [`sessionStorage`](https://playwright.dev/docs/api/class-page#page-session-storage) | ✅ | |
144
- | [`setChecked`](https://playwright.dev/docs/api/class-page#page-set-checked) | ⚠️ | The `signal` option is unsupported. |
144
+ | [`setChecked`](https://playwright.dev/docs/api/class-page#page-set-checked) | ✅ | |
145
145
  | [`setContent`](https://playwright.dev/docs/api/class-page#page-set-content) | 🚫 | Document replacement is excluded. |
146
146
  | [`setDefaultNavigationTimeout`](https://playwright.dev/docs/api/class-page#page-set-default-navigation-timeout) | ✅ | |
147
147
  | [`setDefaultTimeout`](https://playwright.dev/docs/api/class-page#page-set-default-timeout) | ✅ | |
148
148
  | [`setExtraHTTPHeaders`](https://playwright.dev/docs/api/class-page#page-set-extra-http-headers) | ❌ | |
149
- | [`setInputFiles`](https://playwright.dev/docs/api/class-page#page-set-input-files) | ⚠️ | Accepts only in-memory `{ name, mimeType, buffer }` objects; file paths and directory uploads are unsupported. Empty `mimeType` throws instead of inferring a MIME type. The `signal` option is unsupported. |
149
+ | [`setInputFiles`](https://playwright.dev/docs/api/class-page#page-set-input-files) | ⚠️ | Accepts only in-memory `{ name, mimeType, buffer }` objects; file paths and directory uploads are unsupported. Empty `mimeType` throws instead of inferring a MIME type. |
150
150
  | [`setViewportSize`](https://playwright.dev/docs/api/class-page#page-set-viewport-size) | 🚫 | Browser viewport resizing is excluded. |
151
151
  | [`tap`](https://playwright.dev/docs/api/class-page#page-tap) | ❌ | |
152
152
  | [`textContent`](https://playwright.dev/docs/api/class-page#page-text-content) | ✅ | |
153
153
  | [`title`](https://playwright.dev/docs/api/class-page#page-title) | ✅ | |
154
154
  | [`touchscreen`](https://playwright.dev/docs/api/class-page#page-touchscreen) | ❌ | |
155
- | [`type`](https://playwright.dev/docs/api/class-page#page-type) | ⚠️ | The `signal` option is unsupported. |
156
- | [`uncheck`](https://playwright.dev/docs/api/class-page#page-uncheck) | ⚠️ | The `signal` option is unsupported. |
155
+ | [`type`](https://playwright.dev/docs/api/class-page#page-type) | ✅ | |
156
+ | [`uncheck`](https://playwright.dev/docs/api/class-page#page-uncheck) | ✅ | |
157
157
  | [`unroute`](https://playwright.dev/docs/api/class-page#page-unroute) | ❌ | |
158
158
  | [`unrouteAll`](https://playwright.dev/docs/api/class-page#page-unroute-all) | ❌ | |
159
159
  | [`url`](https://playwright.dev/docs/api/class-page#page-url) | ✅ | |
@@ -165,84 +165,84 @@ Targets Playwright **1.62.1**. Statuses describe API compatibility within the ru
165
165
  | [`waitForNavigation`](https://playwright.dev/docs/api/class-page#page-wait-for-navigation) | ❌ | |
166
166
  | [`waitForRequest`](https://playwright.dev/docs/api/class-page#page-wait-for-request) | ❌ | |
167
167
  | [`waitForResponse`](https://playwright.dev/docs/api/class-page#page-wait-for-response) | ❌ | |
168
- | [`waitForSelector`](https://playwright.dev/docs/api/class-page#page-wait-for-selector) | ⚠️ | The `signal` option is unsupported. Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
168
+ | [`waitForSelector`](https://playwright.dev/docs/api/class-page#page-wait-for-selector) | ⚠️ | Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
169
169
  | [`waitForTimeout`](https://playwright.dev/docs/api/class-page#page-wait-for-timeout) | ✅ | |
170
170
  | [`waitForURL`](https://playwright.dev/docs/api/class-page#page-wait-for-url) | ❌ | |
171
171
  | [`workers`](https://playwright.dev/docs/api/class-page#page-workers) | ❌ | |
172
172
 
173
173
  ### Locator
174
174
 
175
- | API | Status | Notes |
176
- | ------------------------------------------------------------------------------------------------------------ | :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
177
- | [`all`](https://playwright.dev/docs/api/class-locator#locator-all) | ✅ | |
178
- | [`allInnerTexts`](https://playwright.dev/docs/api/class-locator#locator-all-inner-texts) | ✅ | |
179
- | [`allTextContents`](https://playwright.dev/docs/api/class-locator#locator-all-text-contents) | ✅ | |
180
- | [`and`](https://playwright.dev/docs/api/class-locator#locator-and) | ✅ | |
181
- | [`ariaSnapshot`](https://playwright.dev/docs/api/class-locator#locator-aria-snapshot) | ✅ | |
182
- | [`blur`](https://playwright.dev/docs/api/class-locator#locator-blur) | ✅ | |
183
- | [`boundingBox`](https://playwright.dev/docs/api/class-locator#locator-bounding-box) | ✅ | |
184
- | [`check`](https://playwright.dev/docs/api/class-locator#locator-check) | ⚠️ | The `signal` option is unsupported. |
185
- | [`clear`](https://playwright.dev/docs/api/class-locator#locator-clear) | ⚠️ | Unsupported options: `force`, `signal`. |
186
- | [`click`](https://playwright.dev/docs/api/class-locator#locator-click) | ⚠️ | Unsupported options: `signal`, `steps`. The action does not wait for navigation. |
187
- | [`contentFrame`](https://playwright.dev/docs/api/class-locator#locator-content-frame) | 🚫 | Iframe realms are outside the single-document boundary. |
188
- | [`count`](https://playwright.dev/docs/api/class-locator#locator-count) | ✅ | |
189
- | [`dblclick`](https://playwright.dev/docs/api/class-locator#locator-dblclick) | ⚠️ | Unsupported options: `signal`, `steps`. |
190
- | [`describe`](https://playwright.dev/docs/api/class-locator#locator-describe) | ✅ | |
191
- | [`description`](https://playwright.dev/docs/api/class-locator#locator-description) | ⚠️ | `describe('').description()` returns `''` instead of `null`; `describe('x').filter({}).description()` returns `null` instead of `'x'`. |
192
- | [`dispatchEvent`](https://playwright.dev/docs/api/class-locator#locator-dispatch-event) | ⚠️ | The `signal` option is unsupported; `JSHandle`/`ElementHandle` values in `eventInit` are not unwrapped. |
193
- | [`dragTo`](https://playwright.dev/docs/api/class-locator#locator-drag-to) | ❌ | |
194
- | [`drop`](https://playwright.dev/docs/api/class-locator#locator-drop) | ❌ | |
195
- | [`elementHandle`](https://playwright.dev/docs/api/class-locator#locator-element-handle) | ⚠️ | Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
196
- | [`elementHandles`](https://playwright.dev/docs/api/class-locator#locator-element-handles) | ⚠️ | Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
197
- | [`evaluate`](https://playwright.dev/docs/api/class-locator#locator-evaluate) | ⚠️ | Rejects `exposeFunctions: true`. |
198
- | [`evaluateAll`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all) | ✅ | |
199
- | [`evaluateHandle`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) | ❌ | |
200
- | [`fill`](https://playwright.dev/docs/api/class-locator#locator-fill) | ⚠️ | Unsupported options: `force`, `signal`. |
201
- | [`filter`](https://playwright.dev/docs/api/class-locator#locator-filter) | ✅ | |
202
- | [`first`](https://playwright.dev/docs/api/class-locator#locator-first) | ✅ | |
203
- | [`focus`](https://playwright.dev/docs/api/class-locator#locator-focus) | ✅ | |
204
- | [`frameLocator`](https://playwright.dev/docs/api/class-locator#locator-frame-locator) | 🚫 | Iframe realms are outside the single-document boundary. |
205
- | [`getAttribute`](https://playwright.dev/docs/api/class-locator#locator-get-attribute) | ✅ | |
206
- | [`getByAltText`](https://playwright.dev/docs/api/class-locator#locator-get-by-alt-text) | ✅ | |
207
- | [`getByLabel`](https://playwright.dev/docs/api/class-locator#locator-get-by-label) | ✅ | |
208
- | [`getByPlaceholder`](https://playwright.dev/docs/api/class-locator#locator-get-by-placeholder) | ✅ | |
209
- | [`getByRole`](https://playwright.dev/docs/api/class-locator#locator-get-by-role) | ✅ | |
210
- | [`getByTestId`](https://playwright.dev/docs/api/class-locator#locator-get-by-test-id) | ✅ | |
211
- | [`getByText`](https://playwright.dev/docs/api/class-locator#locator-get-by-text) | ✅ | |
212
- | [`getByTitle`](https://playwright.dev/docs/api/class-locator#locator-get-by-title) | ✅ | |
213
- | [`hideHighlight`](https://playwright.dev/docs/api/class-locator#locator-hide-highlight) | ✅ | |
214
- | [`highlight`](https://playwright.dev/docs/api/class-locator#locator-highlight) | ✅ | |
215
- | [`hover`](https://playwright.dev/docs/api/class-locator#locator-hover) | ⚠️ | The `signal` option is unsupported. |
216
- | [`innerHTML`](https://playwright.dev/docs/api/class-locator#locator-inner-html) | ✅ | |
217
- | [`innerText`](https://playwright.dev/docs/api/class-locator#locator-inner-text) | ✅ | |
218
- | [`inputValue`](https://playwright.dev/docs/api/class-locator#locator-input-value) | ✅ | |
219
- | [`isChecked`](https://playwright.dev/docs/api/class-locator#locator-is-checked) | ✅ | |
220
- | [`isDisabled`](https://playwright.dev/docs/api/class-locator#locator-is-disabled) | ✅ | |
221
- | [`isEditable`](https://playwright.dev/docs/api/class-locator#locator-is-editable) | ✅ | |
222
- | [`isEnabled`](https://playwright.dev/docs/api/class-locator#locator-is-enabled) | ✅ | |
223
- | [`isHidden`](https://playwright.dev/docs/api/class-locator#locator-is-hidden) | ✅ | |
224
- | [`isVisible`](https://playwright.dev/docs/api/class-locator#locator-is-visible) | ✅ | |
225
- | [`last`](https://playwright.dev/docs/api/class-locator#locator-last) | ✅ | |
226
- | [`locator`](https://playwright.dev/docs/api/class-locator#locator-locator) | ✅ | |
227
- | [`normalize`](https://playwright.dev/docs/api/class-locator#locator-normalize) | ❌ | |
228
- | [`nth`](https://playwright.dev/docs/api/class-locator#locator-nth) | ✅ | |
229
- | [`or`](https://playwright.dev/docs/api/class-locator#locator-or) | ✅ | |
230
- | [`page`](https://playwright.dev/docs/api/class-locator#locator-page) | ✅ | |
231
- | [`press`](https://playwright.dev/docs/api/class-locator#locator-press) | ⚠️ | Unsupported options: `delay`, `signal`. |
232
- | [`pressSequentially`](https://playwright.dev/docs/api/class-locator#locator-press-sequentially) | ⚠️ | The `signal` option is unsupported. |
233
- | [`screenshot`](https://playwright.dev/docs/api/class-locator#locator-screenshot) | ❌ | |
234
- | [`scrollIntoViewIfNeeded`](https://playwright.dev/docs/api/class-locator#locator-scroll-into-view-if-needed) | ⚠️ | The `signal` option is unsupported. |
235
- | [`selectOption`](https://playwright.dev/docs/api/class-locator#locator-select-option) | ⚠️ | `ElementHandle` option values are unsupported. Unsupported options: `force`, `signal`. |
236
- | [`selectText`](https://playwright.dev/docs/api/class-locator#locator-select-text) | ⚠️ | Unsupported options: `force`, `signal`. |
237
- | [`setChecked`](https://playwright.dev/docs/api/class-locator#locator-set-checked) | ⚠️ | The `signal` option is unsupported. |
238
- | [`setInputFiles`](https://playwright.dev/docs/api/class-locator#locator-set-input-files) | ⚠️ | Accepts only in-memory `{ name, mimeType, buffer }` objects; file paths and directory uploads are unsupported. Empty `mimeType` throws instead of inferring a MIME type. The `signal` option is unsupported. |
239
- | [`tap`](https://playwright.dev/docs/api/class-locator#locator-tap) | ❌ | |
240
- | [`textContent`](https://playwright.dev/docs/api/class-locator#locator-text-content) | ✅ | |
241
- | [`toString`](https://playwright.dev/docs/api/class-locator#locator-to-string) | ⚠️ | String representations can omit options: `filter({ hasText: 'x' })` prints `filter(...)`, and `page.getByRole('button', { disabled: true })` omits `disabled`. |
242
- | [`type`](https://playwright.dev/docs/api/class-locator#locator-type) | ⚠️ | The `signal` option is unsupported. |
243
- | [`uncheck`](https://playwright.dev/docs/api/class-locator#locator-uncheck) | ⚠️ | The `signal` option is unsupported. |
244
- | [`waitFor`](https://playwright.dev/docs/api/class-locator#locator-wait-for) | ⚠️ | The `signal` option is unsupported. |
245
- | [`waitForFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function) | ❌ | |
175
+ | API | Status | Notes |
176
+ | ------------------------------------------------------------------------------------------------------------ | :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
177
+ | [`all`](https://playwright.dev/docs/api/class-locator#locator-all) | ✅ | |
178
+ | [`allInnerTexts`](https://playwright.dev/docs/api/class-locator#locator-all-inner-texts) | ✅ | |
179
+ | [`allTextContents`](https://playwright.dev/docs/api/class-locator#locator-all-text-contents) | ✅ | |
180
+ | [`and`](https://playwright.dev/docs/api/class-locator#locator-and) | ✅ | |
181
+ | [`ariaSnapshot`](https://playwright.dev/docs/api/class-locator#locator-aria-snapshot) | ✅ | |
182
+ | [`blur`](https://playwright.dev/docs/api/class-locator#locator-blur) | ✅ | |
183
+ | [`boundingBox`](https://playwright.dev/docs/api/class-locator#locator-bounding-box) | ✅ | |
184
+ | [`check`](https://playwright.dev/docs/api/class-locator#locator-check) | ✅ | |
185
+ | [`clear`](https://playwright.dev/docs/api/class-locator#locator-clear) | ⚠️ | The `force` option is unsupported. |
186
+ | [`click`](https://playwright.dev/docs/api/class-locator#locator-click) | ⚠️ | The `steps` option is unsupported. The action does not wait for navigation. |
187
+ | [`contentFrame`](https://playwright.dev/docs/api/class-locator#locator-content-frame) | 🚫 | Iframe realms are outside the single-document boundary. |
188
+ | [`count`](https://playwright.dev/docs/api/class-locator#locator-count) | ✅ | |
189
+ | [`dblclick`](https://playwright.dev/docs/api/class-locator#locator-dblclick) | ⚠️ | The `steps` option is unsupported. |
190
+ | [`describe`](https://playwright.dev/docs/api/class-locator#locator-describe) | ✅ | |
191
+ | [`description`](https://playwright.dev/docs/api/class-locator#locator-description) | ⚠️ | `describe('').description()` returns `''` instead of `null`; `describe('x').filter({}).description()` returns `null` instead of `'x'`. |
192
+ | [`dispatchEvent`](https://playwright.dev/docs/api/class-locator#locator-dispatch-event) | ⚠️ | `JSHandle`/`ElementHandle` values in `eventInit` are not unwrapped. |
193
+ | [`dragTo`](https://playwright.dev/docs/api/class-locator#locator-drag-to) | ❌ | |
194
+ | [`drop`](https://playwright.dev/docs/api/class-locator#locator-drop) | ❌ | |
195
+ | [`elementHandle`](https://playwright.dev/docs/api/class-locator#locator-element-handle) | ⚠️ | Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
196
+ | [`elementHandles`](https://playwright.dev/docs/api/class-locator#locator-element-handles) | ⚠️ | Returned `ElementHandle` methods and options differ; see [ElementHandle compatibility](#elementhandle-compatibility). |
197
+ | [`evaluate`](https://playwright.dev/docs/api/class-locator#locator-evaluate) | ⚠️ | Rejects `exposeFunctions: true`. |
198
+ | [`evaluateAll`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all) | ✅ | |
199
+ | [`evaluateHandle`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) | ❌ | |
200
+ | [`fill`](https://playwright.dev/docs/api/class-locator#locator-fill) | ⚠️ | The `force` option is unsupported. |
201
+ | [`filter`](https://playwright.dev/docs/api/class-locator#locator-filter) | ✅ | |
202
+ | [`first`](https://playwright.dev/docs/api/class-locator#locator-first) | ✅ | |
203
+ | [`focus`](https://playwright.dev/docs/api/class-locator#locator-focus) | ✅ | |
204
+ | [`frameLocator`](https://playwright.dev/docs/api/class-locator#locator-frame-locator) | 🚫 | Iframe realms are outside the single-document boundary. |
205
+ | [`getAttribute`](https://playwright.dev/docs/api/class-locator#locator-get-attribute) | ✅ | |
206
+ | [`getByAltText`](https://playwright.dev/docs/api/class-locator#locator-get-by-alt-text) | ✅ | |
207
+ | [`getByLabel`](https://playwright.dev/docs/api/class-locator#locator-get-by-label) | ✅ | |
208
+ | [`getByPlaceholder`](https://playwright.dev/docs/api/class-locator#locator-get-by-placeholder) | ✅ | |
209
+ | [`getByRole`](https://playwright.dev/docs/api/class-locator#locator-get-by-role) | ✅ | |
210
+ | [`getByTestId`](https://playwright.dev/docs/api/class-locator#locator-get-by-test-id) | ✅ | |
211
+ | [`getByText`](https://playwright.dev/docs/api/class-locator#locator-get-by-text) | ✅ | |
212
+ | [`getByTitle`](https://playwright.dev/docs/api/class-locator#locator-get-by-title) | ✅ | |
213
+ | [`hideHighlight`](https://playwright.dev/docs/api/class-locator#locator-hide-highlight) | ✅ | |
214
+ | [`highlight`](https://playwright.dev/docs/api/class-locator#locator-highlight) | ✅ | |
215
+ | [`hover`](https://playwright.dev/docs/api/class-locator#locator-hover) | ✅ | |
216
+ | [`innerHTML`](https://playwright.dev/docs/api/class-locator#locator-inner-html) | ✅ | |
217
+ | [`innerText`](https://playwright.dev/docs/api/class-locator#locator-inner-text) | ✅ | |
218
+ | [`inputValue`](https://playwright.dev/docs/api/class-locator#locator-input-value) | ✅ | |
219
+ | [`isChecked`](https://playwright.dev/docs/api/class-locator#locator-is-checked) | ✅ | |
220
+ | [`isDisabled`](https://playwright.dev/docs/api/class-locator#locator-is-disabled) | ✅ | |
221
+ | [`isEditable`](https://playwright.dev/docs/api/class-locator#locator-is-editable) | ✅ | |
222
+ | [`isEnabled`](https://playwright.dev/docs/api/class-locator#locator-is-enabled) | ✅ | |
223
+ | [`isHidden`](https://playwright.dev/docs/api/class-locator#locator-is-hidden) | ✅ | |
224
+ | [`isVisible`](https://playwright.dev/docs/api/class-locator#locator-is-visible) | ✅ | |
225
+ | [`last`](https://playwright.dev/docs/api/class-locator#locator-last) | ✅ | |
226
+ | [`locator`](https://playwright.dev/docs/api/class-locator#locator-locator) | ✅ | |
227
+ | [`normalize`](https://playwright.dev/docs/api/class-locator#locator-normalize) | ❌ | |
228
+ | [`nth`](https://playwright.dev/docs/api/class-locator#locator-nth) | ✅ | |
229
+ | [`or`](https://playwright.dev/docs/api/class-locator#locator-or) | ✅ | |
230
+ | [`page`](https://playwright.dev/docs/api/class-locator#locator-page) | ✅ | |
231
+ | [`press`](https://playwright.dev/docs/api/class-locator#locator-press) | ✅ | |
232
+ | [`pressSequentially`](https://playwright.dev/docs/api/class-locator#locator-press-sequentially) | ✅ | |
233
+ | [`screenshot`](https://playwright.dev/docs/api/class-locator#locator-screenshot) | ❌ | |
234
+ | [`scrollIntoViewIfNeeded`](https://playwright.dev/docs/api/class-locator#locator-scroll-into-view-if-needed) | ✅ | |
235
+ | [`selectOption`](https://playwright.dev/docs/api/class-locator#locator-select-option) | ⚠️ | `ElementHandle` option values are unsupported. The `force` option is unsupported. |
236
+ | [`selectText`](https://playwright.dev/docs/api/class-locator#locator-select-text) | ⚠️ | The `force` option is unsupported. |
237
+ | [`setChecked`](https://playwright.dev/docs/api/class-locator#locator-set-checked) | ✅ | |
238
+ | [`setInputFiles`](https://playwright.dev/docs/api/class-locator#locator-set-input-files) | ⚠️ | Accepts only in-memory `{ name, mimeType, buffer }` objects; file paths and directory uploads are unsupported. Empty `mimeType` throws instead of inferring a MIME type. |
239
+ | [`tap`](https://playwright.dev/docs/api/class-locator#locator-tap) | ❌ | |
240
+ | [`textContent`](https://playwright.dev/docs/api/class-locator#locator-text-content) | ✅ | |
241
+ | [`toString`](https://playwright.dev/docs/api/class-locator#locator-to-string) | ⚠️ | String representations can omit options: `filter({ hasText: 'x' })` prints `filter(...)`, and `page.getByRole('button', { disabled: true })` omits `disabled`. |
242
+ | [`type`](https://playwright.dev/docs/api/class-locator#locator-type) | ✅ | |
243
+ | [`uncheck`](https://playwright.dev/docs/api/class-locator#locator-uncheck) | ✅ | |
244
+ | [`waitFor`](https://playwright.dev/docs/api/class-locator#locator-wait-for) | ✅ | |
245
+ | [`waitForFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function) | ❌ | |
246
246
 
247
247
  ### ElementHandle compatibility
248
248
 
package/dist/index.mjs CHANGED
@@ -14754,6 +14754,27 @@ function validateString(value, name) {
14754
14754
  if (typeof value === "string") return value;
14755
14755
  throw new Error(`${name}: expected string, got ${typeof value}`);
14756
14756
  }
14757
+ /**
14758
+ * `delay` is `float?` in the pinned protocol for press, type and the pointer
14759
+ * actions. Like the pointer options, a non-finite value is rejected instead of
14760
+ * reaching the input path as NaN, and a boxed `Number` is unwrapped for the
14761
+ * caller to forward instead of leaking an object into the input path.
14762
+ */
14763
+ function validateDelay(value) {
14764
+ if (value === void 0) return void 0;
14765
+ const delay = value instanceof Number ? value.valueOf() : value;
14766
+ if (typeof delay !== "number" || !Number.isFinite(delay)) throw new TypeError("delay: expected number");
14767
+ return delay;
14768
+ }
14769
+ /**
14770
+ * `signal` is a client-side option in the pinned API: it never reaches the
14771
+ * protocol, so the adapter checks the value itself. `name` is the API member
14772
+ * or option group the message speaks for, such as `click` or `Query`.
14773
+ */
14774
+ function validateSignal(name, value) {
14775
+ if (value === void 0 || value instanceof AbortSignal) return;
14776
+ throw new TypeError(`${name} signal must be an AbortSignal`);
14777
+ }
14757
14778
  function validateNoWaitAfter(method, value) {
14758
14779
  if (method !== "click" && method !== "press") return;
14759
14780
  if (value === void 0 || typeof value === "boolean" || value instanceof Boolean) return;
@@ -15571,16 +15592,16 @@ var LocatorImpl = class LocatorImpl {
15571
15592
  return this.ownerPage.resolveAll(this.selector).map((element) => this.ownerPage.elementHandleFor(element));
15572
15593
  }
15573
15594
  async getAttribute(name, options) {
15574
- return this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options);
15595
+ return withAbortPrefix("locator.getAttribute", () => this.ownerPage.locatorGetAttribute(this.selector, this.label, name, options));
15575
15596
  }
15576
15597
  async textContent(options) {
15577
- return this.ownerPage.locatorTextContent(this.selector, this.label, options);
15598
+ return withAbortPrefix("locator.textContent", () => this.ownerPage.locatorTextContent(this.selector, this.label, options));
15578
15599
  }
15579
15600
  async innerText(options) {
15580
- return this.ownerPage.locatorInnerText(this.selector, this.label, options);
15601
+ return withAbortPrefix("locator.innerText", () => this.ownerPage.locatorInnerText(this.selector, this.label, options));
15581
15602
  }
15582
15603
  async innerHTML(options) {
15583
- return this.ownerPage.locatorInnerHTML(this.selector, this.label, options);
15604
+ return withAbortPrefix("locator.innerHTML", () => this.ownerPage.locatorInnerHTML(this.selector, this.label, options));
15584
15605
  }
15585
15606
  async allInnerTexts() {
15586
15607
  return this.ownerPage.locatorAllInnerTexts(this.selector);
@@ -15589,19 +15610,19 @@ var LocatorImpl = class LocatorImpl {
15589
15610
  return this.ownerPage.locatorAllTextContents(this.selector);
15590
15611
  }
15591
15612
  async inputValue(options) {
15592
- return this.ownerPage.locatorInputValue(this.selector, this.label, options);
15613
+ return withAbortPrefix("locator.inputValue", () => this.ownerPage.locatorInputValue(this.selector, this.label, options));
15593
15614
  }
15594
15615
  async isEnabled(options) {
15595
- return this.ownerPage.locatorIsEnabled(this.selector, this.label, options);
15616
+ return withAbortPrefix("locator.isEnabled", () => this.ownerPage.locatorIsEnabled(this.selector, this.label, options));
15596
15617
  }
15597
15618
  async isDisabled(options) {
15598
- return this.ownerPage.locatorIsDisabled(this.selector, this.label, options);
15619
+ return withAbortPrefix("locator.isDisabled", () => this.ownerPage.locatorIsDisabled(this.selector, this.label, options));
15599
15620
  }
15600
15621
  async isChecked(options) {
15601
- return this.ownerPage.locatorIsChecked(this.selector, this.label, options);
15622
+ return withAbortPrefix("locator.isChecked", () => this.ownerPage.locatorIsChecked(this.selector, this.label, options));
15602
15623
  }
15603
15624
  async isEditable(options) {
15604
- return this.ownerPage.locatorIsEditable(this.selector, this.label, options);
15625
+ return withAbortPrefix("locator.isEditable", () => this.ownerPage.locatorIsEditable(this.selector, this.label, options));
15605
15626
  }
15606
15627
  async isVisible(options) {
15607
15628
  return this.ownerPage.locatorIsVisible(this.selector, this.label, options);
@@ -15610,7 +15631,7 @@ var LocatorImpl = class LocatorImpl {
15610
15631
  return !this.ownerPage.locatorIsVisible(this.selector, this.label, options);
15611
15632
  }
15612
15633
  async boundingBox(options) {
15613
- return this.ownerPage.locatorBoundingBox(this.selector, this.label, options);
15634
+ return withAbortPrefix("locator.boundingBox", () => this.ownerPage.locatorBoundingBox(this.selector, this.label, options));
15614
15635
  }
15615
15636
  /**
15616
15637
  * Captures the accessibility snapshot rooted at this locator's sole element.
@@ -15620,7 +15641,7 @@ var LocatorImpl = class LocatorImpl {
15620
15641
  * not add frame traversal or browser-process behavior.
15621
15642
  */
15622
15643
  async ariaSnapshot(options = {}) {
15623
- return this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options);
15644
+ return withAbortPrefix("locator.ariaSnapshot", () => this.ownerPage.locatorAriaSnapshot(this.selector, this.label, options));
15624
15645
  }
15625
15646
  /**
15626
15647
  * The public Playwright matcher implementation calls this private-shaped
@@ -15641,7 +15662,7 @@ var LocatorImpl = class LocatorImpl {
15641
15662
  }
15642
15663
  async evaluate(pageFunction, arg, options) {
15643
15664
  assertMaxArguments(arguments.length, 3);
15644
- return this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options);
15665
+ return withAbortPrefix("locator.evaluate", () => this.ownerPage.locatorEvaluate(this.selector, this.label, pageFunction, arg, options));
15645
15666
  }
15646
15667
  async evaluateAll(pageFunction, arg) {
15647
15668
  assertMaxArguments(arguments.length, 2);
@@ -15654,26 +15675,45 @@ var LocatorImpl = class LocatorImpl {
15654
15675
  });
15655
15676
  }
15656
15677
  async fill(value, options) {
15657
- rejectUnsupportedOptions("fill", options, ["noWaitAfter", "timeout"]);
15658
- await this.ownerPage.fillSelector(this.selector, value, this.label, options?.timeout);
15678
+ rejectUnsupportedOptions("fill", options, [
15679
+ "noWaitAfter",
15680
+ "signal",
15681
+ "timeout"
15682
+ ]);
15683
+ await withAbortPrefix("locator.fill", () => this.ownerPage.fillSelector(this.selector, value, this.label, options?.timeout, void 0, true, options?.signal));
15659
15684
  }
15660
15685
  async setInputFiles(files, options) {
15661
- rejectUnsupportedOptions("setInputFiles", options, ["noWaitAfter", "timeout"]);
15662
- await this.ownerPage.setInputFilesSelector(this.selector, files, options, true);
15686
+ rejectUnsupportedOptions("setInputFiles", options, [
15687
+ "noWaitAfter",
15688
+ "signal",
15689
+ "timeout"
15690
+ ]);
15691
+ await withAbortPrefix("locator.setInputFiles", () => this.ownerPage.setInputFilesSelector(this.selector, files, options, true));
15663
15692
  }
15664
15693
  async press(key, options) {
15665
- rejectUnsupportedOptions("press", options, ["noWaitAfter", "timeout"]);
15666
- await this.ownerPage.pressSelector(this.selector, key, this.label, options?.timeout);
15694
+ const delay = rejectUnsupportedOptions("press", options, [
15695
+ "delay",
15696
+ "noWaitAfter",
15697
+ "signal",
15698
+ "timeout"
15699
+ ]);
15700
+ await withAbortPrefix("locator.press", () => this.ownerPage.pressSelector(this.selector, key, this.label, options?.timeout, void 0, true, options?.signal, delay));
15667
15701
  }
15668
15702
  async focus(options) {
15669
- await this.ownerPage.focusSelector(this.selector, this.label, options);
15703
+ rejectUnsupportedOptions("focus", options, ["signal", "timeout"]);
15704
+ await withAbortPrefix("locator.focus", () => this.ownerPage.focusSelector(this.selector, this.label, options));
15670
15705
  }
15671
15706
  async blur(options) {
15672
- await this.ownerPage.blurSelector(this.selector, this.label, options);
15707
+ rejectUnsupportedOptions("blur", options, ["signal", "timeout"]);
15708
+ await withAbortPrefix("locator.blur", () => this.ownerPage.blurSelector(this.selector, this.label, options));
15673
15709
  }
15674
15710
  async clear(options) {
15675
- rejectUnsupportedOptions("clear", options, ["noWaitAfter", "timeout"]);
15676
- await this.ownerPage.fillSelector(this.selector, "", this.label, options?.timeout);
15711
+ rejectUnsupportedOptions("clear", options, [
15712
+ "noWaitAfter",
15713
+ "signal",
15714
+ "timeout"
15715
+ ]);
15716
+ await withAbortPrefix("locator.clear", () => this.ownerPage.fillSelector(this.selector, "", this.label, options?.timeout, void 0, true, options?.signal));
15677
15717
  }
15678
15718
  async hover(options) {
15679
15719
  await this.ownerPage.hoverSelector(this.selector, this.label, options?.timeout, void 0, {
@@ -15706,39 +15746,52 @@ var LocatorImpl = class LocatorImpl {
15706
15746
  });
15707
15747
  }
15708
15748
  async dispatchEvent(type, eventInit = {}, options) {
15709
- rejectUnsupportedOptions("dispatchEvent", options, ["timeout"]);
15710
- await this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout);
15749
+ rejectUnsupportedOptions("dispatchEvent", options, ["signal", "timeout"]);
15750
+ await withAbortPrefix("locator.dispatchEvent", () => this.ownerPage.dispatchEventSelector(this.selector, type, eventInit, this.label, options?.timeout, void 0, true, options?.signal));
15711
15751
  }
15712
15752
  async selectOption(values, options) {
15713
- rejectUnsupportedOptions("selectOption", options, ["noWaitAfter", "timeout"]);
15714
- return this.ownerPage.selectOptionSelector(this.selector, values, this.label, options?.timeout);
15753
+ rejectUnsupportedOptions("selectOption", options, [
15754
+ "noWaitAfter",
15755
+ "signal",
15756
+ "timeout"
15757
+ ]);
15758
+ return withAbortPrefix("locator.selectOption", () => this.ownerPage.selectOptionSelector(this.selector, values, this.label, options?.timeout, void 0, true, options?.signal));
15715
15759
  }
15716
15760
  async selectText(options) {
15717
- rejectUnsupportedOptions("selectText", options, ["timeout"]);
15718
- await this.ownerPage.selectText(this.selector, this.label, options?.timeout);
15761
+ rejectUnsupportedOptions("selectText", options, ["signal", "timeout"]);
15762
+ await withAbortPrefix("locator.selectText", () => this.ownerPage.selectText(this.selector, this.label, options?.timeout, void 0, options?.signal));
15719
15763
  }
15720
15764
  async scrollIntoViewIfNeeded(options) {
15721
- rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["timeout"]);
15722
- await this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout);
15765
+ rejectUnsupportedOptions("scrollIntoViewIfNeeded", options, ["signal", "timeout"]);
15766
+ await withAbortPrefix("locator.scrollIntoViewIfNeeded", () => this.ownerPage.scrollLocatorIntoView(this.selector, this.label, options?.timeout, void 0, options?.signal));
15723
15767
  }
15724
15768
  async type(text, options = {}) {
15769
+ await withAbortPrefix("locator.type", () => this.typeText(text, options));
15770
+ }
15771
+ async pressSequentially(text, options = {}) {
15772
+ await withAbortPrefix("locator.pressSequentially", () => this.typeText(text, options));
15773
+ }
15774
+ async typeText(text, options) {
15725
15775
  rejectUnsupportedOptions("type", options, [
15726
15776
  "delay",
15727
15777
  "noWaitAfter",
15778
+ "signal",
15728
15779
  "timeout"
15729
15780
  ]);
15730
- await this.ownerPage.type(this.selector, text, options, this.label);
15731
- }
15732
- async pressSequentially(text, options = {}) {
15733
- await this.type(text, options);
15781
+ await this.ownerPage.typeSelector(this.selector, text, options, this.label, true);
15734
15782
  }
15735
15783
  async waitFor(options = {}) {
15736
15784
  const state = options.state ?? "visible";
15737
- rejectUnsupportedOptions("waitFor", options, ["state", "timeout"]);
15738
- await this.ownerPage.waitForState(this.selector, {
15785
+ rejectUnsupportedOptions("waitFor", options, [
15786
+ "signal",
15787
+ "state",
15788
+ "timeout"
15789
+ ]);
15790
+ await withAbortPrefix("locator.waitFor", () => this.ownerPage.waitForState(this.selector, {
15791
+ signal: options.signal,
15739
15792
  state,
15740
15793
  timeout: options.timeout
15741
- }, this.label);
15794
+ }, this.label));
15742
15795
  }
15743
15796
  };
15744
15797
  /**
@@ -15752,11 +15805,14 @@ function requireBrand(value, context) {
15752
15805
  if (typeof payload !== "object" || payload === null || typeof payload.getSelector !== "function" || typeof payload.resolveElements !== "function") throw new TypeError(`${context}: expected an PlaywrightLite Locator, got incompatible branded object`);
15753
15806
  return payload;
15754
15807
  }
15808
+ /** Returns the normalized `delay`, unwrapped like the pointer options. */
15755
15809
  function rejectUnsupportedOptions(method, options, supported = []) {
15756
- if (!options) return;
15810
+ if (!options) return void 0;
15757
15811
  const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && !supported.includes(key));
15758
15812
  if (unsupported.length > 0) throw new Error(`${method}(): unsupported Playwright option(s): ${unsupported.join(", ")}.`);
15813
+ validateSignal(method, options.signal);
15759
15814
  if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
15815
+ return supported.includes("delay") ? validateDelay(options.delay) : void 0;
15760
15816
  }
15761
15817
  function cssObjectToString(style) {
15762
15818
  return Object.entries(style).map(([key, value]) => {
@@ -15880,22 +15936,22 @@ var PageImpl = class PageImpl {
15880
15936
  this.injected.hideHighlight();
15881
15937
  }
15882
15938
  async getAttribute(selector, name, options) {
15883
- return this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name));
15939
+ return withAbortPrefix("page.getAttribute", () => this.query(selector, `page.getAttribute(${JSON.stringify(selector)}, ${JSON.stringify(name)})`, options, false, (element) => element.getAttribute(name)));
15884
15940
  }
15885
15941
  async textContent(selector, options) {
15886
- return this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent);
15942
+ return withAbortPrefix("page.textContent", () => this.query(selector, `page.textContent(${JSON.stringify(selector)})`, options, false, (element) => element.textContent));
15887
15943
  }
15888
15944
  async inputValue(selector, options) {
15889
- return this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element));
15945
+ return withAbortPrefix("page.inputValue", () => this.query(selector, `page.inputValue(${JSON.stringify(selector)})`, options, false, (element) => this.inputValueForElement(element)));
15890
15946
  }
15891
15947
  async isEnabled(selector, options) {
15892
- return this.queryState(selector, "enabled", options, false);
15948
+ return withAbortPrefix("page.isEnabled", () => this.queryState(selector, "enabled", options, false));
15893
15949
  }
15894
15950
  async isDisabled(selector, options) {
15895
- return this.queryState(selector, "disabled", options, false);
15951
+ return withAbortPrefix("page.isDisabled", () => this.queryState(selector, "disabled", options, false));
15896
15952
  }
15897
15953
  async isChecked(selector, options) {
15898
- return this.queryState(selector, "checked", options, false);
15954
+ return withAbortPrefix("page.isChecked", () => this.queryState(selector, "checked", options, false));
15899
15955
  }
15900
15956
  async $(selector, options = {}) {
15901
15957
  assertDollarOptions(options);
@@ -15905,7 +15961,7 @@ var PageImpl = class PageImpl {
15905
15961
  return this.resolveAll(selector).map((element) => this.elementHandleFor(element));
15906
15962
  }
15907
15963
  async waitForSelector(selector, options = {}) {
15908
- return await this.waitForSelectorInRoot(this.document, selector, options);
15964
+ return await withAbortPrefix("page.waitForSelector", () => this.waitForSelectorInRoot(this.document, selector, options));
15909
15965
  }
15910
15966
  async waitForSelectorWithinElement(root, selector, options = {}) {
15911
15967
  return await this.waitForSelectorInRoot(root, selector, options, false);
@@ -15976,6 +16032,7 @@ var PageImpl = class PageImpl {
15976
16032
  */
15977
16033
  async performPointerAction(selector, label, action, options, deadline, checked, apiMethod = action) {
15978
16034
  try {
16035
+ this.attachActionSignal(deadline, options.signal);
15979
16036
  while (true) {
15980
16037
  this.assertActionDeadline(deadline, action);
15981
16038
  try {
@@ -16035,12 +16092,13 @@ var PageImpl = class PageImpl {
16035
16092
  if (!checked && "isRadio" in state && state.isRadio) throw new Error("Cannot uncheck radio button. Radio buttons can only be unchecked by selecting another radio button in the same group.");
16036
16093
  return state.matches === checked;
16037
16094
  }
16038
- async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout)) {
16095
+ async fillSelector(selector, value, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16096
+ this.attachActionSignal(deadline, signal);
16039
16097
  const { element } = await this.retryActionability(selector, label, "fill", [
16040
16098
  "visible",
16041
16099
  "enabled",
16042
16100
  "editable"
16043
- ], false, deadline);
16101
+ ], false, deadline, void 0, void 0, strict);
16044
16102
  this.assertActionDeadline(deadline, "fill");
16045
16103
  const result = this.actionableInjected.fill(element, value);
16046
16104
  if (result === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
@@ -16050,14 +16108,18 @@ var PageImpl = class PageImpl {
16050
16108
  if (!inputTarget) throw new Error(`Element is not connected for locator ${label}`);
16051
16109
  this.insertFilledText(inputTarget, value, deadline, "fill");
16052
16110
  }
16053
- async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout)) {
16054
- const element = await this.query(selector, label, { timeout }, true, (candidate) => candidate, deadline);
16111
+ async pressSelector(selector, key, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal, delay) {
16112
+ this.attachActionSignal(deadline, signal);
16113
+ const element = await this.query(selector, label, {
16114
+ signal,
16115
+ timeout
16116
+ }, strict, (candidate) => candidate, deadline);
16055
16117
  this.assertActionDeadline(deadline, "press");
16056
16118
  this.focusElement(element);
16057
- await this.keyboard.press(key, {}, deadline);
16119
+ await this.keyboard.press(key, { delay }, deadline);
16058
16120
  }
16059
- async focusSelector(selector, label, options) {
16060
- await this.query(selector, label, options, true, (element) => {
16121
+ async focusSelector(selector, label, options, strict = true) {
16122
+ await this.query(selector, label, options, strict, (element) => {
16061
16123
  if (this.actionableInjected.focusNode(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
16062
16124
  });
16063
16125
  }
@@ -16075,27 +16137,35 @@ var PageImpl = class PageImpl {
16075
16137
  if (typeof checked !== "boolean") throw new TypeError("checked must be a boolean");
16076
16138
  await this.performPointerAction(selector, label, "click", options, deadline, checked, apiMethod);
16077
16139
  }
16078
- async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout)) {
16140
+ async selectOptionSelector(selector, values, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16141
+ this.attachActionSignal(deadline, signal);
16079
16142
  const options = (values === null ? [] : Array.isArray(values) ? values : [values]).map((value) => typeof value === "string" ? { valueOrLabel: value } : value);
16080
16143
  let lastError;
16081
16144
  while (true) {
16082
16145
  if (Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded.${lastError ? ` ${lastError.message}` : ""}`, { cause: lastError });
16083
- const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline);
16146
+ const { element } = await this.retryActionability(selector, label, "select option", ["visible", "enabled"], false, deadline, void 0, void 0, strict);
16084
16147
  this.assertActionDeadline(deadline, "select option");
16085
16148
  const result = this.actionableInjected.selectOptions(element, options);
16086
16149
  if (Array.isArray(result)) return result;
16087
16150
  lastError = result === "error:optionnotenabled" ? /* @__PURE__ */ new Error("Element is not enabled") : result === "error:notconnected" ? /* @__PURE__ */ new Error(`Element is not connected for locator ${label}`) : /* @__PURE__ */ new Error("Options not found");
16088
16151
  const remaining = deadline.expiresAt - Date.now();
16089
16152
  if (remaining <= 0) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
16090
- await this.wait(Math.min(ACTION_RETRY_DELAY, remaining));
16153
+ try {
16154
+ await this.waitWithinActionDeadline(Math.min(ACTION_RETRY_DELAY, remaining), deadline, "select option");
16155
+ } catch (error) {
16156
+ if (error instanceof AdapterTimeoutError) throw new AdapterTimeoutError(`select option: Timeout ${deadline.timeout}ms exceeded. ${lastError.message}`, { cause: lastError });
16157
+ throw error;
16158
+ }
16091
16159
  }
16092
16160
  }
16093
- async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
16161
+ async selectText(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
16162
+ this.attachActionSignal(deadline, signal);
16094
16163
  const { element } = await this.retryActionability(selector, label, "select text", ["visible"], false, deadline);
16095
16164
  this.assertActionDeadline(deadline, "select text");
16096
16165
  if (this.actionableInjected.selectText(element) === "error:notconnected") throw new Error(`Element is not connected for locator ${label}`);
16097
16166
  }
16098
- async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout)) {
16167
+ async scrollLocatorIntoView(selector, label, timeout, deadline = this.createActionDeadline(timeout), signal) {
16168
+ this.attachActionSignal(deadline, signal);
16099
16169
  const { element } = await this.retryActionability(selector, label, "scroll into view", ["stable"], false, deadline);
16100
16170
  this.assertActionDeadline(deadline, "scroll into view");
16101
16171
  this.scrollIntoViewIfNeeded(element);
@@ -16105,6 +16175,7 @@ var PageImpl = class PageImpl {
16105
16175
  try {
16106
16176
  await this.waitForSelectorInRoot(this.document, selector, {
16107
16177
  state: options.state,
16178
+ signal: options.signal,
16108
16179
  strict: true,
16109
16180
  timeout: options.timeout
16110
16181
  });
@@ -16118,7 +16189,11 @@ var PageImpl = class PageImpl {
16118
16189
  if (options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError("setInputFiles strict must be a boolean");
16119
16190
  const payloads = inputFilePayloads(files);
16120
16191
  const deadline = this.createActionDeadline(options.timeout);
16121
- await this.query(selector, selector, { timeout: options.timeout }, strict || options.strict === true, (element) => {
16192
+ this.attachActionSignal(deadline, options.signal);
16193
+ await this.query(selector, selector, {
16194
+ signal: options.signal,
16195
+ timeout: options.timeout
16196
+ }, strict || options.strict === true, (element) => {
16122
16197
  this.assertActionDeadline(deadline, "setInputFiles");
16123
16198
  const input = this.injected.retarget(element, "follow-label");
16124
16199
  if (!input || !input.isConnected) throw new Error("Element is not connected");
@@ -16161,28 +16236,30 @@ var PageImpl = class PageImpl {
16161
16236
  this.defaultNavigationTimeout = validateTimeout(timeout, "Default navigation timeout");
16162
16237
  }
16163
16238
  async innerText(selector, options) {
16164
- return this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
16239
+ return withAbortPrefix("page.innerText", () => this.query(selector, `page.innerText(${JSON.stringify(selector)})`, options, false, (element) => {
16165
16240
  if (element.namespaceURI !== "http://www.w3.org/1999/xhtml") throw new Error("Node is not an HTMLElement");
16166
16241
  return element.innerText;
16167
- });
16242
+ }));
16168
16243
  }
16169
16244
  async innerHTML(selector, options) {
16170
- return this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML);
16245
+ return withAbortPrefix("page.innerHTML", () => this.query(selector, `page.innerHTML(${JSON.stringify(selector)})`, options, false, (element) => element.innerHTML));
16171
16246
  }
16172
16247
  async isEditable(selector, options) {
16173
- return this.queryState(selector, "editable", options, false);
16248
+ return withAbortPrefix("page.isEditable", () => this.queryState(selector, "editable", options, false));
16174
16249
  }
16175
16250
  async isVisible(selector, options) {
16176
- assertQueryOptions(options, true);
16177
- this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16178
- if (options?.signal?.aborted) throw queryAborted(options.signal);
16251
+ return this.selectorIsVisible("isVisible", selector, options);
16252
+ }
16253
+ async isHidden(selector, options) {
16254
+ return !this.selectorIsVisible("isHidden", selector, options);
16255
+ }
16256
+ selectorIsVisible(method, selector, options) {
16257
+ assertQueryOptions(options, ["strict", "timeout"]);
16258
+ if (options?.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
16179
16259
  const element = options?.strict ? this.resolveLocatorElement(selector, true) : this.resolveAll(selector)[0];
16180
16260
  if (!element) return false;
16181
16261
  return this.elementState(element, "visible").matches;
16182
16262
  }
16183
- async isHidden(selector, options) {
16184
- return !await this.isVisible(selector, options);
16185
- }
16186
16263
  async click(selector, options) {
16187
16264
  assertPointerActionOptions("click", options);
16188
16265
  await this.clickSelector(selector, `page.click(${JSON.stringify(selector)})`, options?.timeout, void 0, {
@@ -16191,28 +16268,45 @@ var PageImpl = class PageImpl {
16191
16268
  });
16192
16269
  }
16193
16270
  async fill(selector, value, options) {
16194
- assertPageActionOptions("fill", options, ["noWaitAfter"]);
16195
- await this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout);
16271
+ assertPageActionOptions("fill", options, ["noWaitAfter", "strict"]);
16272
+ await withAbortPrefix("page.fill", () => this.fillSelector(selector, value, `page.fill(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16196
16273
  }
16197
16274
  async setInputFiles(selector, files, options) {
16198
- await this.setInputFilesSelector(selector, files, options);
16275
+ await withAbortPrefix("page.setInputFiles", () => this.setInputFilesSelector(selector, files, options));
16199
16276
  }
16200
16277
  async press(selector, key, options) {
16201
- assertPageActionOptions("press", options, ["noWaitAfter"]);
16202
- await this.pressSelector(selector, key, `page.press(${JSON.stringify(selector)})`, options?.timeout);
16278
+ const delay = assertPageActionOptions("press", options, [
16279
+ "delay",
16280
+ "noWaitAfter",
16281
+ "strict"
16282
+ ]);
16283
+ await withAbortPrefix("page.press", () => this.pressSelector(selector, key, `page.press(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal, delay));
16284
+ }
16285
+ async type(selector, text, options) {
16286
+ await withAbortPrefix("page.type", () => this.typeSelector(selector, text, options, `page.type(${JSON.stringify(selector)})`, options?.strict === true));
16203
16287
  }
16204
- async type(selector, text, options, label = `page.type(${JSON.stringify(selector)})`) {
16205
- assertPageActionOptions("type", options, ["delay", "noWaitAfter"]);
16288
+ async typeSelector(selector, text, options, label, strict) {
16289
+ const delay = assertPageActionOptions("type", options, [
16290
+ "delay",
16291
+ "noWaitAfter",
16292
+ "strict"
16293
+ ]);
16206
16294
  const deadline = this.createActionDeadline(options?.timeout);
16207
- for (const character of text) {
16208
- if (keyboardLayout.has(character)) await this.pressSelector(selector, character, label, options?.timeout, deadline);
16209
- else await this.insertTextSelector(selector, character, label, deadline);
16210
- if (options?.delay && options.delay > 0) await this.waitWithinActionDeadline(options.delay, deadline, "press");
16211
- }
16295
+ this.attachActionSignal(deadline, options?.signal);
16296
+ await this.query(selector, label, {
16297
+ signal: options?.signal,
16298
+ timeout: options?.timeout
16299
+ }, strict, (element) => {
16300
+ if (this.actionableInjected.focusNode(element, true) === "error:notconnected") throw new Error("Element is not connected");
16301
+ }, deadline);
16302
+ await this.keyboard.type(text, { delay }, deadline);
16212
16303
  }
16213
16304
  async focus(selector, options) {
16214
- assertPageActionOptions("focus", options);
16215
- await this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`, options);
16305
+ assertPageActionOptions("focus", options, ["strict"]);
16306
+ await withAbortPrefix("page.focus", () => this.focusSelector(selector, `page.focus(${JSON.stringify(selector)})`, {
16307
+ signal: options?.signal,
16308
+ timeout: options?.timeout
16309
+ }, options?.strict === true));
16216
16310
  }
16217
16311
  async hover(selector, options) {
16218
16312
  await this.hoverSelector(selector, `page.hover(${JSON.stringify(selector)})`, options?.timeout, void 0, {
@@ -16221,8 +16315,8 @@ var PageImpl = class PageImpl {
16221
16315
  });
16222
16316
  }
16223
16317
  async selectOption(selector, values, options) {
16224
- assertPageActionOptions("selectOption", options, ["noWaitAfter"]);
16225
- return this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout);
16318
+ assertPageActionOptions("selectOption", options, ["noWaitAfter", "strict"]);
16319
+ return withAbortPrefix("page.selectOption", () => this.selectOptionSelector(selector, values, `page.selectOption(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16226
16320
  }
16227
16321
  async check(selector, options) {
16228
16322
  await this.setCheckedSelector(selector, true, `page.check(${JSON.stringify(selector)})`, {
@@ -16250,10 +16344,14 @@ var PageImpl = class PageImpl {
16250
16344
  }
16251
16345
  async dispatchEvent(selector, type, eventInit = {}, options) {
16252
16346
  assertPageDispatchEventOptions(options);
16253
- await this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true);
16347
+ await withAbortPrefix("page.dispatchEvent", () => this.dispatchEventSelector(selector, type, eventInit, `page.dispatchEvent(${JSON.stringify(selector)})`, options?.timeout, void 0, options?.strict === true, options?.signal));
16254
16348
  }
16255
- async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true) {
16256
- await this.query(selector, label, { timeout }, strict, (element) => this.actionableInjected.dispatchEvent(element, type, eventInit), deadline);
16349
+ async dispatchEventSelector(selector, type, eventInit, label, timeout, deadline = this.createActionDeadline(timeout), strict = true, signal) {
16350
+ this.attachActionSignal(deadline, signal);
16351
+ await this.query(selector, label, {
16352
+ signal,
16353
+ timeout
16354
+ }, strict, (element) => this.actionableInjected.dispatchEvent(element, type, eventInit), deadline);
16257
16355
  }
16258
16356
  /**
16259
16357
  * Pinned 26a9e47 client/frame.ts and server/frames.ts default to load,
@@ -16321,10 +16419,12 @@ var PageImpl = class PageImpl {
16321
16419
  * and rendering. There is no frame traversal or protocol transport here.
16322
16420
  */
16323
16421
  async ariaSnapshot(options = {}) {
16324
- assertAriaSnapshotOptions(options);
16325
- if (options.signal?.aborted) throw queryAborted(options.signal);
16326
- await this.waitForDocumentParser(options);
16327
- return this.injectedAriaSnapshot(this.document.body ?? this.document.documentElement, options);
16422
+ return withAbortPrefix("page.ariaSnapshot", async () => {
16423
+ assertAriaSnapshotOptions(options);
16424
+ if (options.signal?.aborted) throw actionAborted(options.signal, false);
16425
+ await this.waitForDocumentParser(options);
16426
+ return this.injectedAriaSnapshot(this.document.body ?? this.document.documentElement, options);
16427
+ });
16328
16428
  }
16329
16429
  injectedAriaSnapshot(element, options = {}) {
16330
16430
  return this.injected.ariaSnapshot(element, {
@@ -16346,7 +16446,7 @@ var PageImpl = class PageImpl {
16346
16446
  else resolve();
16347
16447
  };
16348
16448
  const ready = () => settle();
16349
- const aborted = () => settle(queryAborted(options.signal));
16449
+ const aborted = () => settle(actionAborted(options.signal, true));
16350
16450
  this.window.addEventListener("DOMContentLoaded", ready, { once: true });
16351
16451
  options.signal?.addEventListener("abort", aborted, { once: true });
16352
16452
  if (timeout > 0) timeoutId = this.window.setTimeout(() => settle(new AdapterTimeoutError(`page.ariaSnapshot: Timeout ${timeout}ms exceeded.`)), timeout);
@@ -16512,17 +16612,25 @@ var PageImpl = class PageImpl {
16512
16612
  expiresAt: effectiveTimeout === 0 ? Infinity : Date.now() + effectiveTimeout
16513
16613
  };
16514
16614
  }
16615
+ attachActionSignal(deadline, signal) {
16616
+ deadline.signal = signal;
16617
+ if (signal?.aborted) throw actionAborted(signal, false);
16618
+ }
16515
16619
  assertActionDeadline(deadline, actionName) {
16620
+ if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
16516
16621
  if (deadline && Date.now() >= deadline.expiresAt) throw new AdapterTimeoutError(`${actionName}: Timeout ${deadline.timeout}ms exceeded.`);
16517
16622
  }
16518
16623
  checkKeyboardActionDeadline(deadline) {
16519
16624
  this.assertActionDeadline(deadline, "press");
16520
16625
  }
16626
+ async waitKeyboardDelay(durationMs, deadline) {
16627
+ await this.waitWithinActionDeadline(durationMs, deadline, "press");
16628
+ }
16521
16629
  async waitWithinActionDeadline(durationMs, deadline, actionName) {
16522
16630
  this.assertActionDeadline(deadline, actionName);
16523
16631
  if (!durationMs || durationMs <= 0) return;
16524
16632
  const remaining = deadline ? deadline.expiresAt - Date.now() : durationMs;
16525
- await this.wait(Math.min(durationMs, remaining));
16633
+ if (!await waitForExpectationRetry(this.window, Math.min(durationMs, remaining), deadline?.signal) && deadline?.signal) throw actionAborted(deadline.signal, true);
16526
16634
  this.assertActionDeadline(deadline, actionName);
16527
16635
  }
16528
16636
  async wait(durationMs) {
@@ -16566,9 +16674,7 @@ var PageImpl = class PageImpl {
16566
16674
  return this.queryState(selector, "editable", options, true, label);
16567
16675
  }
16568
16676
  locatorIsVisible(selector, label, options) {
16569
- assertQueryOptions(options, false);
16570
- this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16571
- if (options?.signal?.aborted) throw queryAborted(options.signal);
16677
+ assertQueryOptions(options, ["timeout"]);
16572
16678
  const element = this.resolveLocatorElement(selector, true);
16573
16679
  if (!element) return false;
16574
16680
  return this.elementState(element, "visible").matches;
@@ -16578,7 +16684,7 @@ var PageImpl = class PageImpl {
16578
16684
  }
16579
16685
  async locatorAriaSnapshot(selector, label, options = {}) {
16580
16686
  assertAriaSnapshotOptions(options);
16581
- if (options.signal?.aborted) throw queryAborted(options.signal);
16687
+ if (options.signal?.aborted) throw actionAborted(options.signal, false);
16582
16688
  if (options.mode === "ai") return this.injectedAriaSnapshot(this.queryElement(selector, label, true), options);
16583
16689
  return this.query(selector, label, {
16584
16690
  signal: options.signal,
@@ -16635,13 +16741,16 @@ var PageImpl = class PageImpl {
16635
16741
  const state = options.state ?? "visible";
16636
16742
  const timeout = this.resolveTimeout(options.timeout, DEFAULT_ACTION_TIMEOUT);
16637
16743
  const deadline = timeout === 0 ? Infinity : Date.now() + timeout;
16744
+ const signal = options.signal;
16745
+ if (signal?.aborted) throw actionAborted(signal, false);
16638
16746
  while (true) {
16639
16747
  const element = root instanceof this.window.Element ? this.resolveWithinElement(root, selector, options.strict === true) : this.resolveLocatorElement(selector, options.strict === true);
16640
16748
  const visible = !!element && this.elementState(element, "visible").matches === true;
16641
16749
  if (state === "attached" && element || state === "visible" && visible) return this.elementHandleFor(element);
16642
16750
  if (state === "detached" && !element || state === "hidden" && !visible) return null;
16643
16751
  if (Date.now() >= deadline) throw new AdapterTimeoutError(`page.waitForSelector: Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)} to be ${state}`);
16644
- await this.wait(Math.min(QUERY_RETRY_DELAY, deadline - Date.now()));
16752
+ const delay = Math.min(QUERY_RETRY_DELAY, deadline - Date.now());
16753
+ if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
16645
16754
  }
16646
16755
  }
16647
16756
  async elementMatchesState(element, state) {
@@ -16658,10 +16767,14 @@ var PageImpl = class PageImpl {
16658
16767
  return result.matches;
16659
16768
  }
16660
16769
  async query(selector, label, options, strict, evaluate, actionDeadline) {
16661
- assertQueryOptions(options, !strict);
16770
+ assertQueryOptions(options, strict ? ["signal", "timeout"] : [
16771
+ "signal",
16772
+ "strict",
16773
+ "timeout"
16774
+ ]);
16662
16775
  const timeout = actionDeadline?.timeout ?? this.resolveTimeout(options?.timeout, DEFAULT_QUERY_TIMEOUT);
16663
16776
  const signal = options?.signal;
16664
- if (signal?.aborted) throw queryAborted(signal);
16777
+ if (signal?.aborted) throw actionAborted(signal, false);
16665
16778
  const deadline = actionDeadline?.expiresAt ?? (timeout === 0 ? Infinity : Date.now() + timeout);
16666
16779
  while (true) try {
16667
16780
  return await evaluate(this.queryElement(selector, label, strict || options?.strict === true));
@@ -16670,7 +16783,7 @@ var PageImpl = class PageImpl {
16670
16783
  const remaining = deadline - Date.now();
16671
16784
  if (remaining <= 0) throw new AdapterTimeoutError(`Timeout ${timeout}ms exceeded.\nCall log:\n - waiting for ${formatLocator(selector)}`, { cause: error });
16672
16785
  const delay = Math.min(QUERY_RETRY_DELAY, remaining);
16673
- if (!await waitForExpectationRetry(this.window, delay, signal)) throw queryAborted(signal);
16786
+ if (!await waitForExpectationRetry(this.window, delay, signal)) throw actionAborted(signal, true);
16674
16787
  }
16675
16788
  }
16676
16789
  queryElement(selector, label, strict) {
@@ -16693,16 +16806,23 @@ var PageImpl = class PageImpl {
16693
16806
  throw new Error(`Element is not ${result.missingState}`);
16694
16807
  }
16695
16808
  async waitForActionDeadline(operation, deadline, timeoutError) {
16696
- if (!deadline || deadline.expiresAt === Infinity) return operation;
16697
- if (Date.now() >= deadline.expiresAt) throw timeoutError();
16809
+ if (deadline?.signal?.aborted) throw actionAborted(deadline.signal, true);
16810
+ if (deadline && Date.now() >= deadline.expiresAt) throw timeoutError();
16811
+ if (!deadline) return operation;
16698
16812
  let timeoutHandle;
16813
+ let onAbort;
16699
16814
  try {
16700
16815
  return await new Promise((resolve, reject) => {
16701
- timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
16816
+ if (deadline.expiresAt !== Infinity) timeoutHandle = this.window.setTimeout(() => reject(timeoutError()), Math.max(0, deadline.expiresAt - Date.now()));
16817
+ if (deadline.signal) {
16818
+ onAbort = () => reject(actionAborted(deadline.signal, true));
16819
+ deadline.signal.addEventListener("abort", onAbort, { once: true });
16820
+ }
16702
16821
  operation.then(resolve, reject);
16703
16822
  });
16704
16823
  } finally {
16705
16824
  if (timeoutHandle !== void 0) this.window.clearTimeout(timeoutHandle);
16825
+ if (onAbort) deadline.signal?.removeEventListener("abort", onAbort);
16706
16826
  }
16707
16827
  }
16708
16828
  actionabilityDeadlineError(element, states) {
@@ -16717,7 +16837,7 @@ var PageImpl = class PageImpl {
16717
16837
  }
16718
16838
  return /* @__PURE__ */ new Error("Element is not stable");
16719
16839
  }
16720
- async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions) {
16840
+ async retryActionability(selector, label, actionName, states, checkHitTarget, deadline, position, pointerOptions, strict = pointerOptions?.strict ?? true) {
16721
16841
  let lastError;
16722
16842
  let retry = 0;
16723
16843
  const log = [];
@@ -16729,7 +16849,7 @@ var PageImpl = class PageImpl {
16729
16849
  while (true) {
16730
16850
  if (Date.now() >= deadline.expiresAt) throwTimeout();
16731
16851
  try {
16732
- const element = this.resolvePointerElement(selector, label, pointerOptions?.strict ?? true);
16852
+ const element = this.resolvePointerElement(selector, label, strict);
16733
16853
  if (pointerOptions && !pointerOptions.force) log.push(` - waiting for element to be ${states.includes("enabled") ? "visible, enabled and stable" : "visible and stable"}`);
16734
16854
  if (!pointerOptions?.force) await this.ensureActionable(element, states, deadline);
16735
16855
  if (Date.now() >= deadline.expiresAt) throwTimeout();
@@ -16776,7 +16896,12 @@ var PageImpl = class PageImpl {
16776
16896
  if (log.length > 60) log.splice(0, log.length - 60);
16777
16897
  }
16778
16898
  if (remaining <= 0) throw timeoutError();
16779
- await this.wait(Math.min(delay, remaining));
16899
+ try {
16900
+ await this.waitWithinActionDeadline(Math.min(delay, remaining), deadline, actionName);
16901
+ } catch (error) {
16902
+ if (error instanceof AdapterTimeoutError) throw timeoutError();
16903
+ throw error;
16904
+ }
16780
16905
  }
16781
16906
  }
16782
16907
  }
@@ -16969,8 +17094,8 @@ var PageImpl = class PageImpl {
16969
17094
  this.assertActionDeadline(deadline, "press");
16970
17095
  this.insertPressedText(element, text, inputType, eventData, deadline);
16971
17096
  }
16972
- async insertTextSelector(selector, text, label, deadline) {
16973
- const element = await this.query(selector, label, { timeout: deadline.timeout }, true, (candidate) => candidate, deadline);
17097
+ async insertTextSelector(selector, text, label, deadline, strict = true) {
17098
+ const element = await this.query(selector, label, { timeout: deadline.timeout }, strict, (candidate) => candidate, deadline);
16974
17099
  this.assertActionDeadline(deadline, "press");
16975
17100
  this.focusElement(element);
16976
17101
  this.insertKeyboardText(element, text, "insertText", text, deadline);
@@ -17213,25 +17338,49 @@ var BrowserKeyboard = class {
17213
17338
  async up(key, deadline) {
17214
17339
  await this.upForTarget(key, deadline);
17215
17340
  }
17216
- async insertText(text) {
17217
- this.page.insertKeyboardText(this.activeTarget(), text);
17341
+ async insertText(text, deadline) {
17342
+ this.page.insertKeyboardText(this.activeTarget(), text, "insertText", text, deadline);
17218
17343
  }
17219
- async type(text, options = {}) {
17344
+ async type(text, options = {}, deadline) {
17220
17345
  const delay = options.delay || void 0;
17221
- for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay });
17346
+ for (const character of text) if (keyboardLayout.has(character)) await this.press(character, { delay }, deadline);
17222
17347
  else {
17223
- if (delay) await this.wait(delay);
17224
- await this.insertText(character);
17348
+ if (delay) await this.page.waitKeyboardDelay(delay, deadline);
17349
+ await this.insertText(character, deadline);
17225
17350
  }
17226
17351
  }
17227
17352
  async press(key, options = {}, deadline) {
17228
17353
  const tokens = splitKeyboardShortcut(key);
17229
17354
  const target = tokens.at(-1);
17230
- for (const modifier of tokens.slice(0, -1)) await this.down(modifier, deadline);
17231
- await this.down(target, deadline);
17232
- if (options.delay) await this.wait(options.delay, deadline);
17233
- await this.up(target, deadline);
17234
- for (const modifier of tokens.slice(0, -1).reverse()) await this.up(modifier, deadline);
17355
+ const modifiers = tokens.slice(0, -1);
17356
+ const held = /* @__PURE__ */ new Set();
17357
+ try {
17358
+ for (const modifier of modifiers) {
17359
+ held.add(modifier);
17360
+ await this.down(modifier, deadline);
17361
+ }
17362
+ held.add(target);
17363
+ await this.down(target, deadline);
17364
+ if (options.delay) await this.page.waitKeyboardDelay(options.delay, deadline);
17365
+ await this.up(target, deadline);
17366
+ held.delete(target);
17367
+ for (const modifier of modifiers.reverse()) {
17368
+ await this.up(modifier, deadline);
17369
+ held.delete(modifier);
17370
+ }
17371
+ } catch (error) {
17372
+ this.releaseKeys(held);
17373
+ throw error;
17374
+ }
17375
+ }
17376
+ releaseKeys(keys) {
17377
+ for (const key of keys) {
17378
+ const description = keyboardLayout.get(resolveKeyboardKey(key, this.page.window));
17379
+ if (!description) continue;
17380
+ this.pressedKeys.delete(description.code);
17381
+ this.keydownState.delete(description.code);
17382
+ if (isModifier(description.key)) this.pressedModifiers.delete(description.key);
17383
+ }
17235
17384
  }
17236
17385
  async downForTarget(key, deadline) {
17237
17386
  this.page.checkKeyboardActionDeadline(deadline);
@@ -17288,13 +17437,6 @@ var BrowserKeyboard = class {
17288
17437
  };
17289
17438
  return description;
17290
17439
  }
17291
- async wait(delay, deadline) {
17292
- this.page.checkKeyboardActionDeadline(deadline);
17293
- const remaining = deadline ? Math.max(0, deadline.expiresAt - Date.now()) : delay;
17294
- if (deadline && remaining <= 0) this.page.checkKeyboardActionDeadline(deadline);
17295
- await new Promise((resolve) => this.page.window.setTimeout(resolve, Math.min(delay, remaining)));
17296
- this.page.checkKeyboardActionDeadline(deadline);
17297
- }
17298
17440
  async waitForKeyboardPhase(deadline) {
17299
17441
  this.page.checkKeyboardActionDeadline(deadline);
17300
17442
  await new Promise((resolve) => this.page.window.setTimeout(resolve));
@@ -17411,12 +17553,17 @@ function validateTimeout(timeout, name) {
17411
17553
  if (typeof timeout !== "number" || timeout < 0 || !Number.isFinite(timeout)) throw new TypeError(`${name} must be a non-negative finite number`);
17412
17554
  return timeout;
17413
17555
  }
17556
+ /** Returns the normalized `delay`, unwrapped like the pointer options. */
17414
17557
  function assertPageActionOptions(method, options, supported = []) {
17415
- if (!options) return;
17416
- const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "timeout" && !supported.includes(key));
17558
+ if (!options) return void 0;
17559
+ const unsupported = Object.keys(options).filter((key) => options[key] !== void 0 && key !== "signal" && key !== "timeout" && !supported.includes(key));
17417
17560
  if (unsupported.length > 0) throw new Error(`${method}(): unsupported options: ${unsupported.join(", ")}. Unsupported Playwright option(s) are not supported by the single-document adapter.`);
17561
+ validateSignal(method, options.signal);
17418
17562
  if (options.timeout !== void 0) validateTimeout(options.timeout, `${method} timeout`);
17419
17563
  if (supported.includes("noWaitAfter")) validateNoWaitAfter(method, options.noWaitAfter);
17564
+ const delay = supported.includes("delay") ? validateDelay(options.delay) : void 0;
17565
+ if (supported.includes("strict") && options.strict !== void 0 && typeof options.strict !== "boolean") throw new TypeError(`${method} strict must be a boolean`);
17566
+ return delay;
17420
17567
  }
17421
17568
  function assertPageDispatchEventOptions(options) {
17422
17569
  assertPageActionOptions("dispatchEvent", options, ["strict"]);
@@ -17424,6 +17571,7 @@ function assertPageDispatchEventOptions(options) {
17424
17571
  }
17425
17572
  function assertPointerActionOptions(method, options) {
17426
17573
  const supported = [
17574
+ "signal",
17427
17575
  "noWaitAfter",
17428
17576
  "position",
17429
17577
  "trial",
@@ -17476,19 +17624,22 @@ function assertPointerActionOptions(method, options) {
17476
17624
  }
17477
17625
  function assertAriaSnapshotOptions(options) {
17478
17626
  queryTimeout(options.timeout);
17479
- if (options.signal !== void 0 && !(options.signal instanceof AbortSignal)) throw new TypeError("ARIA snapshot signal must be an AbortSignal");
17627
+ validateSignal("ARIA snapshot", options.signal);
17480
17628
  }
17481
- function assertQueryOptions(options, allowsStrict) {
17629
+ function assertQueryOptions(options, allowed) {
17482
17630
  if (!options) return;
17483
- for (const key of Object.keys(options)) if (key !== "signal" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported query option: ${key}`);
17484
- if (options.signal !== void 0 && !(options.signal instanceof AbortSignal)) throw new TypeError("Query signal must be an AbortSignal");
17485
- if (!allowsStrict && "strict" in options) throw new Error("Locator query options do not support strict");
17631
+ for (const key of Object.keys(options)) {
17632
+ if (key === "signal" && options.signal === void 0) continue;
17633
+ if (!allowed.includes(key)) throw new Error(`Unsupported query option: ${key}`);
17634
+ }
17635
+ validateSignal("Query", options.signal);
17486
17636
  }
17487
17637
  function assertDollarOptions(options) {
17488
17638
  for (const key of Object.keys(options)) if (key !== "strict") throw new Error(`Unsupported query option: ${key}`);
17489
17639
  }
17490
17640
  function assertWaitForSelectorOptions(options, allowsStrict) {
17491
- for (const key of Object.keys(options)) if (key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
17641
+ for (const key of Object.keys(options)) if (key !== "signal" && key !== "state" && key !== "timeout" && !(allowsStrict && key === "strict")) throw new Error(`Unsupported waitForSelector option: ${key}`);
17642
+ validateSignal("waitForSelector", options.signal);
17492
17643
  if (!allowsStrict && "strict" in options) throw new Error("ElementHandle waitForSelector does not support strict");
17493
17644
  if (options.state !== void 0 && ![
17494
17645
  "attached",
@@ -17525,8 +17676,24 @@ function presentOriginalXPath(error, selector) {
17525
17676
  if (rewritten === source.message) return source;
17526
17677
  return new Error(rewritten, { cause: source });
17527
17678
  }
17528
- function queryAborted(signal) {
17529
- return /* @__PURE__ */ new Error(`Query was aborted: ${abortReason(signal)}`);
17679
+ function actionAborted(signal, inFlight) {
17680
+ const reason = abortReason(signal);
17681
+ const error = new Error(inFlight ? `${reason}\nCall log:\n - operation was aborted: ${reason}` : "The operation was aborted", { cause: signal.reason });
17682
+ error.name = "AbortError";
17683
+ return error;
17684
+ }
17685
+ async function withAbortPrefix(apiName, run) {
17686
+ try {
17687
+ return await run();
17688
+ } catch (error) {
17689
+ throw prefixAbortError(error, apiName);
17690
+ }
17691
+ }
17692
+ function prefixAbortError(error, apiName) {
17693
+ const result = asError(error);
17694
+ if (result.name !== "AbortError") return error;
17695
+ result.message = `${apiName}: ${result.message}`;
17696
+ return result;
17530
17697
  }
17531
17698
  function unknownKey(value) {
17532
17699
  throw new Error(`Unknown key: "${value}"`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enekesabel/playwright-lite",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Playwright-compatible Page and Locator operations in the current browser document",
5
5
  "license": "MIT",
6
6
  "author": "Ábel Énekes",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "scripts": {
35
35
  "build": "pnpm generate:injected && tsdown",
36
- "lint": "eslint src --max-warnings 0",
36
+ "lint": "eslint src tests/contract --max-warnings 0",
37
37
  "test": "vitest run && node --test scripts/upstream-baseline.test.mjs scripts/generate-readme.test.mjs scripts/release.test.mjs scripts/release-bootstrap.test.mjs",
38
38
  "test:guards": "pnpm exec playwright test tests/upstream/_adapter-guard.spec.ts tests/upstream/_page-test-fixture.spec.ts tests/upstream/_synchronization-guard.spec.ts tests/upstream/_browser-compat-guard.spec.ts",
39
39
  "typecheck": "tsc --noEmit && tsc -p tsconfig.compatibility.json --noEmit",
@@ -46,7 +46,7 @@
46
46
  "format": "prettier --write .",
47
47
  "format:check": "prettier --check .",
48
48
  "test:package": "node scripts/packed-consumer.mjs",
49
- "check": "pnpm check:readme && pnpm build && pnpm lint && pnpm typecheck && pnpm upstream:check && pnpm test && pnpm test:evaluation && pnpm test:e2e && pnpm test:package && pnpm format:check",
49
+ "check": "pnpm check:readme && pnpm build && pnpm lint && pnpm typecheck && pnpm upstream:check && pnpm test && pnpm test:evaluation && pnpm test:package && pnpm format:check",
50
50
  "test:evaluation": "node scripts/evaluation-parity.mjs",
51
51
  "generate:readme": "node scripts/generate-readme.mjs",
52
52
  "check:readme": "node scripts/generate-readme.mjs --check"