very-happy-dom 0.2.0 → 0.3.1
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.
- package/CHANGELOG.md +41 -0
- package/README.md +220 -4
- package/dist/aria/roles.d.ts +13 -0
- package/dist/aria/state.d.ts +33 -0
- package/dist/aria/visibility.d.ts +24 -1
- package/dist/browser/BrowserContext.d.ts +12 -0
- package/dist/browser/BrowserFrame.d.ts +2 -0
- package/dist/browser/BrowserPage.d.ts +55 -4
- package/dist/browser/Dialog.d.ts +35 -0
- package/dist/browser/Locator.d.ts +33 -3
- package/dist/browser/keys.d.ts +48 -0
- package/dist/{chunk-76fz7rx8.js → chunk-1rvpej1f.js} +2 -2
- package/dist/{chunk-httdr8re.js → chunk-3j0xdgak.js} +2 -2
- package/dist/chunk-6sd65akb.js +2 -0
- package/dist/{chunk-h2qtm7yn.js → chunk-7vtf83p2.js} +2 -2
- package/dist/chunk-8bm80b93.js +2 -0
- package/dist/{chunk-j2wys65b.js → chunk-8r26c3ah.js} +2 -2
- package/dist/chunk-bd2npvc0.js +2 -0
- package/dist/chunk-c2ccy7s1.js +2 -0
- package/dist/chunk-cqy1f504.js +3 -0
- package/dist/{chunk-c195vfyf.js → chunk-fet56t0p.js} +2 -2
- package/dist/chunk-ftv7ktch.js +2 -0
- package/dist/{chunk-7yd4gnqy.js → chunk-gbbkvps6.js} +2 -2
- package/dist/chunk-gx33dcgq.js +2 -0
- package/dist/chunk-ha2jjx02.js +3 -0
- package/dist/chunk-jfqdhrwq.js +8 -0
- package/dist/chunk-k63rmfca.js +2 -0
- package/dist/chunk-k8rqbg4p.js +11 -0
- package/dist/chunk-n9azxffj.js +2 -0
- package/dist/chunk-sjmj8mb1.js +3 -0
- package/dist/{chunk-jk62hdff.js → chunk-t1v0nj69.js} +2 -2
- package/dist/chunk-x3xbed4x.js +2 -0
- package/dist/css/CSSOM.d.ts +0 -3
- package/dist/css/cascade.d.ts +2 -13
- package/dist/css/media.d.ts +38 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +15 -15
- package/dist/jsdom/index.js +1 -1
- package/dist/matchers.d.ts +60 -3
- package/dist/matchers.js +2 -2
- package/dist/network/RequestInterceptor.d.ts +27 -0
- package/dist/register.js +1 -1
- package/dist/window/Window.d.ts +8 -0
- package/package.json +1 -1
- package/dist/chunk-182syxjh.js +0 -2
- package/dist/chunk-3d9kwyx0.js +0 -3
- package/dist/chunk-7c8vh5me.js +0 -11
- package/dist/chunk-a7z9k802.js +0 -2
- package/dist/chunk-ew1knb9c.js +0 -2
- package/dist/chunk-gkeyaw9g.js +0 -2
- package/dist/chunk-ptess7d1.js +0 -3
- package/dist/chunk-qkxcr7jt.js +0 -2
- package/dist/chunk-rr2grqs5.js +0 -2
- package/dist/chunk-t7xttfys.js +0 -2
- package/dist/chunk-vxcq2fte.js +0 -10
- package/dist/chunk-wktrnbx6.js +0 -2
- package/dist/chunk-yqxxa2ez.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
[Compare changes](https://github.com/stacksjs/very-happy-dom/compare/v0.3.0...HEAD)
|
|
2
|
+
|
|
3
|
+
## 🐛 Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **dialog**: emit a declaration that parses ([55aa421](https://github.com/stacksjs/very-happy-dom/commit/55aa421)) _(by glennmichael123 <gtorregosa@gmail.com>)_
|
|
6
|
+
|
|
7
|
+
## 🤖 Continuous Integration
|
|
8
|
+
|
|
9
|
+
- **release**: pass the tag's notes to the GitHub Release ([3550904](https://github.com/stacksjs/very-happy-dom/commit/3550904)) _(by glennmichael123 <gtorregosa@gmail.com>)_
|
|
10
|
+
|
|
11
|
+
## Contributors
|
|
12
|
+
|
|
13
|
+
- _glennmichael123 <gtorregosa@gmail.com>_
|
|
14
|
+
|
|
15
|
+
[Compare changes](https://github.com/stacksjs/very-happy-dom/compare/v0.2.0...HEAD)
|
|
16
|
+
|
|
17
|
+
## 🚀 Features
|
|
18
|
+
|
|
19
|
+
- **matchers**: add the aria, CSS and property matchers ([7e203bd](https://github.com/stacksjs/very-happy-dom/commit/7e203bd)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1618](https://github.com/stacksjs/very-happy-dom/issues/1618), [#1608](https://github.com/stacksjs/very-happy-dom/issues/1608), [#1602](https://github.com/stacksjs/very-happy-dom/issues/1602))
|
|
20
|
+
- **page**: add dialog events for alert, confirm and prompt ([5de9417](https://github.com/stacksjs/very-happy-dom/commit/5de9417)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1612](https://github.com/stacksjs/very-happy-dom/issues/1612), [#1602](https://github.com/stacksjs/very-happy-dom/issues/1602))
|
|
21
|
+
- **locator**: add filter({has}), or() and and() ([c10931d](https://github.com/stacksjs/very-happy-dom/commit/c10931d)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1619](https://github.com/stacksjs/very-happy-dom/issues/1619))
|
|
22
|
+
- **locator**: add boundingBox and scrollIntoViewIfNeeded ([9f9055b](https://github.com/stacksjs/very-happy-dom/commit/9f9055b)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1609](https://github.com/stacksjs/very-happy-dom/issues/1609), [#1600](https://github.com/stacksjs/very-happy-dom/issues/1600), [#1617](https://github.com/stacksjs/very-happy-dom/issues/1617))
|
|
23
|
+
- **page**: add setContent, and fix the document parse it exposed ([a5e2bd4](https://github.com/stacksjs/very-happy-dom/commit/a5e2bd4)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1610](https://github.com/stacksjs/very-happy-dom/issues/1610), [#1595](https://github.com/stacksjs/very-happy-dom/issues/1595))
|
|
24
|
+
- **locator**: add the form-control actions ([d1068b0](https://github.com/stacksjs/very-happy-dom/commit/d1068b0)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1608](https://github.com/stacksjs/very-happy-dom/issues/1608), [#1615](https://github.com/stacksjs/very-happy-dom/issues/1615), [#1616](https://github.com/stacksjs/very-happy-dom/issues/1616))
|
|
25
|
+
- **locator**: add evaluate, evaluateAll and the all*Text helpers ([3549710](https://github.com/stacksjs/very-happy-dom/commit/3549710)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1607](https://github.com/stacksjs/very-happy-dom/issues/1607))
|
|
26
|
+
- **page**: add the waitFor* family for page events ([4039cb7](https://github.com/stacksjs/very-happy-dom/commit/4039cb7)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1606](https://github.com/stacksjs/very-happy-dom/issues/1606))
|
|
27
|
+
|
|
28
|
+
## 🐛 Bug Fixes
|
|
29
|
+
|
|
30
|
+
- **dom**: collapse whitespace in innerText, and resolve its visibility ([6589fe0](https://github.com/stacksjs/very-happy-dom/commit/6589fe0)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1614](https://github.com/stacksjs/very-happy-dom/issues/1614), [#1600](https://github.com/stacksjs/very-happy-dom/issues/1600), [#1607](https://github.com/stacksjs/very-happy-dom/issues/1607))
|
|
31
|
+
- **css**: apply @media rules, and add emulateMedia ([f67bf7a](https://github.com/stacksjs/very-happy-dom/commit/f67bf7a)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1611](https://github.com/stacksjs/very-happy-dom/issues/1611), [#1600](https://github.com/stacksjs/very-happy-dom/issues/1600))
|
|
32
|
+
- **page**: make waitForSelector throw on timeout ([32c5f0e](https://github.com/stacksjs/very-happy-dom/commit/32c5f0e)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1605](https://github.com/stacksjs/very-happy-dom/issues/1605))
|
|
33
|
+
- **keyboard**: parse modifier combinations and populate code ([ada3489](https://github.com/stacksjs/very-happy-dom/commit/ada3489)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1615](https://github.com/stacksjs/very-happy-dom/issues/1615))
|
|
34
|
+
- **aria**: treat a declared zero size as hidden ([480899c](https://github.com/stacksjs/very-happy-dom/commit/480899c)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1617](https://github.com/stacksjs/very-happy-dom/issues/1617), [#1604](https://github.com/stacksjs/very-happy-dom/issues/1604), [#1601](https://github.com/stacksjs/very-happy-dom/issues/1601))
|
|
35
|
+
- **aria**: read checked state through aria-checked ([524698f](https://github.com/stacksjs/very-happy-dom/commit/524698f)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1616](https://github.com/stacksjs/very-happy-dom/issues/1616))
|
|
36
|
+
- **routing**: stop setRequestInterception(false) from killing routes ([7537569](https://github.com/stacksjs/very-happy-dom/commit/7537569)) _(by glennmichael123 <gtorregosa@gmail.com>)_ ([#1613](https://github.com/stacksjs/very-happy-dom/issues/1613))
|
|
37
|
+
|
|
38
|
+
## Contributors
|
|
39
|
+
|
|
40
|
+
- _glennmichael123 <gtorregosa@gmail.com>_
|
|
41
|
+
|
|
1
42
|
[Compare changes](https://github.com/stacksjs/very-happy-dom/compare/v0.1.12...HEAD)
|
|
2
43
|
|
|
3
44
|
## 🚀 Features
|
package/README.md
CHANGED
|
@@ -146,11 +146,37 @@ The one-shot rewrite — `expect(await page.getByRole('alert').textContent()).to
|
|
|
146
146
|
drains is a race. `.not` waits for the opposite to become true rather than
|
|
147
147
|
inverting a single sample.
|
|
148
148
|
|
|
149
|
+
Checked state is read through ARIA, so a design system's
|
|
150
|
+
`<div role="checkbox" aria-checked>` answers truthfully — `isChecked()`,
|
|
151
|
+
`getByRole({ checked })`, `check()`/`uncheck()` and `toBeChecked()` all go through
|
|
152
|
+
one predicate. `locator.checkedState()` returns `'mixed'` for a tri-state control,
|
|
153
|
+
and `toBeChecked({ indeterminate: true })` asserts it. `toBeChecked()` refuses an
|
|
154
|
+
element with no checked state rather than answering `false`, so
|
|
155
|
+
`.not.toBeChecked()` cannot pass against a plain `<div>`.
|
|
156
|
+
|
|
149
157
|
Locators: `toBeAttached`, `toBeVisible`, `toBeHidden`, `toHaveCount`,
|
|
150
|
-
`toHaveText`, `toContainText`, `toHaveValue`, `
|
|
151
|
-
`
|
|
152
|
-
`
|
|
153
|
-
`
|
|
158
|
+
`toHaveText`, `toContainText`, `toHaveValue`, `toHaveValues`, `toHaveAttribute`,
|
|
159
|
+
`toHaveClass`, `toHaveId`, `toHaveCSS`, `toHaveJSProperty`, `toHaveRole`,
|
|
160
|
+
`toHaveAccessibleName`, `toHaveAccessibleDescription`, `toBeEnabled`,
|
|
161
|
+
`toBeDisabled`, `toBeChecked`, `toBeEditable`, `toBeFocused`, `toBeEmpty`.
|
|
162
|
+
Pages: `toHaveURL`, `toHaveTitle`. Each takes an optional `{ timeout }`,
|
|
163
|
+
defaulting to `page.setDefaultTimeout()`.
|
|
164
|
+
|
|
165
|
+
`toHaveRole` and `toHaveAccessibleName` assert what `getByRole` queries on, which
|
|
166
|
+
is how a failing role query becomes diagnosable. `toHaveCSS` compares values **as
|
|
167
|
+
the engine reports them**, so `'red'` will not match a computed `'rgb(255, 0, 0)'`
|
|
168
|
+
— use a RegExp. `toHaveJSProperty` takes a path, so `validity.valueMissing` works.
|
|
169
|
+
|
|
170
|
+
`toBeInViewport` is deliberately absent: with no layout pass a bounding box has no
|
|
171
|
+
position, so it could only ever answer "yes".
|
|
172
|
+
|
|
173
|
+
An element is hidden by `display: none`, `visibility: hidden`, the `hidden`
|
|
174
|
+
attribute, or a **declared** zero size — `height: 0`, `max-height: 0` and the
|
|
175
|
+
like, which is how a closed accordion or drawer is built when the author wants a
|
|
176
|
+
transition. Declared is the operative word: with no layout pass an element nobody
|
|
177
|
+
sized also measures `0 x 0`, so a zero box means *unknown* rather than
|
|
178
|
+
*collapsed*, and only a declaration is trusted. That is narrower than
|
|
179
|
+
Playwright's non-empty-bounding-box rule, deliberately.
|
|
154
180
|
|
|
155
181
|
Locator actions auto-wait on the same terms — present, rendered and not
|
|
156
182
|
disabled — and `locator.waitFor({ state })` covers `attached`, `detached`,
|
|
@@ -158,6 +184,196 @@ disabled — and `locator.waitFor({ state })` covers `attached`, `detached`,
|
|
|
158
184
|
stable (not mid-animation) and receives-events (not covered by another element).
|
|
159
185
|
Both need a layout pass.
|
|
160
186
|
|
|
187
|
+
### Rendered Text
|
|
188
|
+
|
|
189
|
+
`innerText` returns text as rendered: hidden subtrees left out, whitespace
|
|
190
|
+
collapsed, block elements separated by newlines, `<br>` honoured. Visibility is
|
|
191
|
+
resolved through the cascade, so a `display: none` from a stylesheet is excluded —
|
|
192
|
+
not only an inline one. `white-space: pre`, `pre-wrap` and `break-spaces` keep
|
|
193
|
+
their text verbatim, `pre-line` keeps newlines, and a `<pre>` element counts as
|
|
194
|
+
`pre` with no rule needed.
|
|
195
|
+
|
|
196
|
+
`textContent` is unchanged: raw, untrimmed, uncollapsed.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
document.body.innerHTML = '<p> Save changes </p>'
|
|
200
|
+
document.querySelector('p').textContent // ' Save changes '
|
|
201
|
+
document.querySelector('p').innerText // 'Save changes'
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Dialogs
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
page.on('dialog', dialog => dialog.accept()) // confirm() returns true
|
|
208
|
+
page.on('dialog', dialog => dialog.accept('Ridge')) // prompt() returns 'Ridge'
|
|
209
|
+
page.on('dialog', dialog => dialog.dismiss()) // false / null
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Without a handler every dialog is dismissed, which is Playwright's default and
|
|
213
|
+
what the old hardcoded `false`/`null` did — so nothing changes unless you opt in.
|
|
214
|
+
`dialog` carries `type`, `message` and `defaultValue`, so a test can assert *which*
|
|
215
|
+
dialog appeared, including an `alert()`.
|
|
216
|
+
|
|
217
|
+
The decision must be made **synchronously**: `confirm()` is a synchronous DOM API,
|
|
218
|
+
so a handler that awaits before deciding answers after the page has already acted
|
|
219
|
+
on the default. That throws rather than letting the wrong answer through.
|
|
220
|
+
`dialog.accept()` records the decision immediately, so `async dialog =>
|
|
221
|
+
await dialog.accept()` is fine — it is awaiting *before* deciding that is not.
|
|
222
|
+
|
|
223
|
+
### Combining Locators
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// Pick a row by what is inside it, then act within that row
|
|
227
|
+
const row = page.getByRole('row').filter({ has: page.getByText('Ridge Loop') })
|
|
228
|
+
await row.getByRole('button', { name: 'Delete' }).click()
|
|
229
|
+
|
|
230
|
+
// Two possible outcomes, without racing them
|
|
231
|
+
await expect(page.getByRole('alert').or(page.getByText('Saved'))).toBeVisible()
|
|
232
|
+
|
|
233
|
+
// Only the elements both match
|
|
234
|
+
await page.getByRole('button').and(page.locator('.primary')).click()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`filter({ has })` and `{ hasNot }` query the inner locator **from each candidate**,
|
|
238
|
+
not from the page — so a match elsewhere does not qualify a row. `hasText` is not
|
|
239
|
+
a substitute: it compares the candidate's whole text, so a neighbouring column
|
|
240
|
+
containing the string matches too, and it cannot ask about a role.
|
|
241
|
+
|
|
242
|
+
`filter()` throws on an unrecognised key. Ignoring one is how `filter({ has })`
|
|
243
|
+
used to look like it worked while matching every candidate. `or()` returns
|
|
244
|
+
document order with duplicates removed.
|
|
245
|
+
|
|
246
|
+
### Media Queries
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
await page.emulateMedia({ colorScheme: 'dark' })
|
|
250
|
+
await page.emulateMedia({ media: 'print' })
|
|
251
|
+
await page.emulateMedia({ reducedMotion: 'reduce', forcedColors: 'active' })
|
|
252
|
+
await page.emulateMedia({ colorScheme: null }) // back to the browser's setting
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`@media` blocks are parsed into real `CSSMediaRule`s and applied when their
|
|
256
|
+
condition holds, so a dark-mode or responsive stylesheet takes effect in
|
|
257
|
+
`getComputedStyle`, in `getBoundingClientRect` and in the locator queries that
|
|
258
|
+
read visibility. `matchMedia` and the cascade evaluate the query with the same
|
|
259
|
+
code, so they cannot disagree about the same document.
|
|
260
|
+
|
|
261
|
+
Understood features: `prefers-color-scheme`, `prefers-reduced-motion`,
|
|
262
|
+
`forced-colors`, `orientation`, and the `width`/`height` family with `px`, `em`
|
|
263
|
+
and `rem`. Media types (`screen`, `print`, `all`), `and`, comma lists, `not` and
|
|
264
|
+
`only` all work. Any other feature — `(hover: hover)`, for instance — makes its
|
|
265
|
+
query false, as an unrecognised feature does in a browser.
|
|
266
|
+
|
|
267
|
+
### Geometry
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
const box = await page.locator('.card').boundingBox() // { x, y, width, height } | null
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Width and height are real — the rect resolves through the cascade, so a size from
|
|
274
|
+
a stylesheet is reported. **`x` and `y` are always `0`**: there is no layout pass,
|
|
275
|
+
so position is not computed, and overlap, ordering and is-this-above-the-fold
|
|
276
|
+
cannot be asked here. `null` is returned for an element that is not rendered.
|
|
277
|
+
`scrollIntoViewIfNeeded()` resolves and fires a `scroll` event, which is as much
|
|
278
|
+
as is meaningful without layout.
|
|
279
|
+
|
|
280
|
+
### Setting Page Content
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
await page.setContent('<button>Save</button>')
|
|
284
|
+
await expect(page.getByRole('button')).toBeVisible()
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
A bare fragment becomes the body; a full `<!DOCTYPE html><html><head>…` string
|
|
288
|
+
lands intact. It replaces the whole document rather than filling the body, fires
|
|
289
|
+
`domcontentloaded` and `load` so an assertion straight afterwards needs no wait,
|
|
290
|
+
and leaves the URL alone — setting content is not navigating.
|
|
291
|
+
|
|
292
|
+
### Form Controls
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
await page.locator('#area').selectOption('north') // by value
|
|
296
|
+
await page.locator('#area').selectOption({ label: 'North' }) // by option text
|
|
297
|
+
await page.locator('#photos').setInputFiles({ name: 'trail.gpx', buffer: gpx })
|
|
298
|
+
await page.locator('#photos').setInputFiles('./fixtures/trail.gpx') // read from disk
|
|
299
|
+
await page.locator('#search').press('Control+Enter')
|
|
300
|
+
await page.locator('#search').clear()
|
|
301
|
+
await page.locator('#row').dblclick()
|
|
302
|
+
await page.locator('#terms').setChecked(true)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
`selectOption` fires `input` then `change`, which is the point: assigning
|
|
306
|
+
`select.value` by hand fires neither, so a component listening for it never
|
|
307
|
+
updates and the test passes against a DOM the app never saw. `setInputFiles`
|
|
308
|
+
builds the `FileList` that assigning `input.files` requires. Passing several
|
|
309
|
+
values to a non-`multiple` control is refused rather than silently truncated.
|
|
310
|
+
`press` focuses the element first — `page.keyboard` only reaches whatever already
|
|
311
|
+
has focus.
|
|
312
|
+
|
|
313
|
+
### Keyboard
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
await page.keyboard.press('Control+Enter') // key 'Enter', ctrlKey true
|
|
317
|
+
await page.keyboard.press('Shift+a') // types 'A'
|
|
318
|
+
await page.keyboard.down('Shift')
|
|
319
|
+
await page.keyboard.press('Tab') // shiftKey true
|
|
320
|
+
await page.keyboard.up('Shift')
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`Control`/`Ctrl`, `Shift`, `Alt`/`Option` and `Meta`/`Cmd`/`Command` are
|
|
324
|
+
recognised, several at a time; modifiers go down in order and come up in reverse.
|
|
325
|
+
`event.code` is populated (`KeyA`, `Digit1`, `ArrowDown`, `ShiftLeft`). A key held
|
|
326
|
+
with Control, Alt or Meta does not insert text — `Control+A` selects rather than
|
|
327
|
+
typing an "a" — while Shift produces the capital. Only a known modifier name is
|
|
328
|
+
consumed, so `press('Enter')` and even a nonsense `press('a+b')` are passed
|
|
329
|
+
through as literal keys.
|
|
330
|
+
|
|
331
|
+
### Running Code Against a Locator
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
const ids = await page.locator('tbody tr').evaluateAll(els => els.map(el => el.dataset.id))
|
|
335
|
+
const label = await page.getByRole('button').evaluate(el => el.dataset.state)
|
|
336
|
+
|
|
337
|
+
await page.locator('li').allTextContents() // raw textContent, per match
|
|
338
|
+
await page.locator('li').allInnerTexts() // rendered text: hidden subtrees left out
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`evaluate()` is strict and waits for the element to be attached; `evaluateAll()`
|
|
342
|
+
is neither, because many matches is its expected case and none is a legitimate
|
|
343
|
+
`[]`. The element is the real node, so writing through it changes the document.
|
|
344
|
+
|
|
345
|
+
Callbacks are recompiled against the frame's window and **cannot see their
|
|
346
|
+
closure**, the same as in Playwright — pass anything they need as the second
|
|
347
|
+
argument. `page.$eval` / `page.$$eval` exist for ports, but take the first match
|
|
348
|
+
rather than refusing an ambiguous selector.
|
|
349
|
+
|
|
350
|
+
### Waiting on Page Events
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const [response] = await Promise.all([
|
|
354
|
+
page.waitForResponse('**/api/trails'),
|
|
355
|
+
page.getByRole('button', { name: 'Search' }).click(),
|
|
356
|
+
])
|
|
357
|
+
|
|
358
|
+
expect((await response.json()).trails).toHaveLength(3)
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Subscribe *before* the action, as above. An event that has already fired is not
|
|
362
|
+
replayed — the same as Playwright, and it matters more here because `goto()`
|
|
363
|
+
emits synchronously and returns, so there is no window at all.
|
|
364
|
+
|
|
365
|
+
- `page.waitForEvent(event, predicateOrOptions)` — the primitive, for any of the
|
|
366
|
+
six page events.
|
|
367
|
+
- `page.waitForResponse(urlOrPredicate)` / `waitForRequest(...)` — a glob or
|
|
368
|
+
RegExp matches the URL through the same matcher `route()` uses; a function
|
|
369
|
+
receives the event itself, so it can read `status` too. Responses are reported
|
|
370
|
+
for navigations *and* for `fetch` calls made by page code. Requests need
|
|
371
|
+
interception on, which `page.route()` does as a side effect.
|
|
372
|
+
- `page.waitForLoadState('load' | 'domcontentloaded')` — returns at once if the
|
|
373
|
+
state has already been reached. `networkidle` throws rather than pretending:
|
|
374
|
+
nothing here tracks in-flight requests.
|
|
375
|
+
- `page.waitForURL(urlOrPredicate)` — polled, so a `pushState` counts.
|
|
376
|
+
|
|
161
377
|
### Browser Context
|
|
162
378
|
|
|
163
379
|
```typescript
|
package/dist/aria/roles.d.ts
CHANGED
|
@@ -11,6 +11,19 @@ export declare function computeRole(element: ElementLike): string | null;
|
|
|
11
11
|
* that allow it, then `title`, and `placeholder` as a last resort for fields.
|
|
12
12
|
*/
|
|
13
13
|
export declare function accessibleName(element: ElementLike): string;
|
|
14
|
+
/**
|
|
15
|
+
* The description a screen reader would announce after the name.
|
|
16
|
+
*
|
|
17
|
+
* `aria-describedby` first, resolved through the document the same way
|
|
18
|
+
* `accessibleName` resolves `aria-labelledby`; then `aria-description`, then
|
|
19
|
+
* `title`. An element with no description answers with an empty string rather than
|
|
20
|
+
* null, matching `accessibleName`.
|
|
21
|
+
*
|
|
22
|
+
* `title` is last because it is also a name source: an element whose only text is
|
|
23
|
+
* a `title` uses it as its name, and using it as the description too would have
|
|
24
|
+
* the same string answer both questions.
|
|
25
|
+
*/
|
|
26
|
+
export declare function accessibleDescription(element: ElementLike): string;
|
|
14
27
|
/** Heading depth, or null when the element is not a heading. */
|
|
15
28
|
export declare function headingLevel(element: ElementLike): number | null;
|
|
16
29
|
/**
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The element's checked state, or `undefined` when it is not checkable at all.
|
|
3
|
+
*
|
|
4
|
+
* The native property wins where there is one: it is the live state, and an
|
|
5
|
+
* author who writes `aria-checked` on a real `<input type=checkbox>` is
|
|
6
|
+
* duplicating something the browser already tracks.
|
|
7
|
+
*/
|
|
8
|
+
export declare function checkedState(element: ElementLike): CheckedState | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Checked as a plain boolean, which is what `isChecked()` reports.
|
|
11
|
+
*
|
|
12
|
+
* `mixed` is neither checked nor unchecked, and a boolean cannot say so, so it
|
|
13
|
+
* answers `false` here. `toBeChecked({ checked: 'mixed' })` is where the third
|
|
14
|
+
* state can be asked about without lying.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isChecked(element: ElementLike): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The element's selected state, or `undefined` when it is not selectable.
|
|
19
|
+
*
|
|
20
|
+
* `<option selected>` keeps a live property, the same as a native checkbox;
|
|
21
|
+
* everything else goes through `aria-selected`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function selectedState(element: ElementLike): boolean | undefined;
|
|
24
|
+
/** Selected as a plain boolean. */
|
|
25
|
+
export declare function isSelected(element: ElementLike): boolean;
|
|
26
|
+
declare interface ElementLike {
|
|
27
|
+
tagName?: string
|
|
28
|
+
checked?: boolean
|
|
29
|
+
selected?: boolean
|
|
30
|
+
getAttribute?: (name: string) => string | null
|
|
31
|
+
}
|
|
32
|
+
/** `mixed` is a real third state, for a tri-state checkbox. */
|
|
33
|
+
export type CheckedState = boolean | 'mixed';
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Whether the element is painted: nothing in its ancestor chain hides it with
|
|
3
|
-
* `display: none`, `visibility: hidden|collapse
|
|
3
|
+
* `display: none`, `visibility: hidden|collapse`, the `hidden` attribute, or a
|
|
4
|
+
* declared zero size.
|
|
4
5
|
*/
|
|
5
6
|
export declare function isRendered(element: ElementLike): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the element's own style hides it, ignoring its ancestors.
|
|
9
|
+
*
|
|
10
|
+
* @internal Shared with `innerText`, which walks the tree itself and so has
|
|
11
|
+
* already dealt with ancestors by not descending into a hidden one. Calling the
|
|
12
|
+
* ancestor-walking form per node would make that walk quadratic, and having two
|
|
13
|
+
* definitions of "hidden" is the thing #1601 set out to avoid.
|
|
14
|
+
*/
|
|
15
|
+
export declare function hidesItself(element: ElementLike, style?: any): boolean;
|
|
6
16
|
/**
|
|
7
17
|
* Whether the element reaches the accessibility tree: painted, and not marked
|
|
8
18
|
* `aria-hidden` on itself or an ancestor.
|
|
@@ -23,6 +33,19 @@ export declare function isExposedToAria(element: ElementLike): boolean;
|
|
|
23
33
|
* Both walk the ancestor chain, because hiding a container hides everything
|
|
24
34
|
* inside it, and both resolve through `getComputedStyle()` so a rule from a
|
|
25
35
|
* stylesheet counts, not only an inline style.
|
|
36
|
+
*
|
|
37
|
+
* Collapsing an element to nothing hides it too (#1617). `height: 0` is how a
|
|
38
|
+
* closed accordion, disclosure or drawer is built when the author wants a
|
|
39
|
+
* transition, since `display: none` cannot be animated — and that markup was
|
|
40
|
+
* fully reachable, so a role query matched a button inside a shut drawer and,
|
|
41
|
+
* since #1604, clicking it succeeded.
|
|
42
|
+
*
|
|
43
|
+
* This is narrower than Playwright's rule, deliberately. Playwright asks whether
|
|
44
|
+
* the bounding box is non-empty; there is no layout pass here, so an element
|
|
45
|
+
* nobody sized reports `0 × 0` — a plain `<button>Save</button>` with no CSS has
|
|
46
|
+
* an empty box. Zero therefore means *unknown*, not *collapsed*, and only a
|
|
47
|
+
* declared zero can be trusted to mean the latter. A reader who knows
|
|
48
|
+
* Playwright's definition should not assume the box is being consulted.
|
|
26
49
|
*/
|
|
27
50
|
declare interface ElementLike {
|
|
28
51
|
nodeType?: number
|
|
@@ -19,6 +19,12 @@ export declare class BrowserContext {
|
|
|
19
19
|
grantPermissions(permissions: string[], _options?: { origin?: string }): Promise<void>;
|
|
20
20
|
clearPermissions(): Promise<void>;
|
|
21
21
|
setGeolocation(geolocation: { latitude: number, longitude: number, accuracy?: number } | null): Promise<void>;
|
|
22
|
+
emulateMedia(options?: {
|
|
23
|
+
media?: 'screen' | 'print' | null
|
|
24
|
+
colorScheme?: 'light' | 'dark' | null
|
|
25
|
+
reducedMotion?: 'reduce' | 'no-preference' | null
|
|
26
|
+
forcedColors?: 'active' | 'none' | null
|
|
27
|
+
}): Promise<void>;
|
|
22
28
|
setOffline(offline: boolean): Promise<void>;
|
|
23
29
|
setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
|
|
24
30
|
addInitScript(script: string | ((...args: any[]) => any)): Promise<void>;
|
|
@@ -27,6 +33,12 @@ export declare class BrowserContext {
|
|
|
27
33
|
permissions: string[] | null
|
|
28
34
|
geolocation: { latitude: number, longitude: number, accuracy?: number } | null
|
|
29
35
|
offline: boolean
|
|
36
|
+
media: {
|
|
37
|
+
type?: 'screen' | 'print'
|
|
38
|
+
colorScheme?: 'light' | 'dark'
|
|
39
|
+
reducedMotion?: 'reduce' | 'no-preference'
|
|
40
|
+
forcedColors?: 'active' | 'none'
|
|
41
|
+
}
|
|
30
42
|
};
|
|
31
43
|
_extraHTTPHeaders(): Record<string, string>;
|
|
32
44
|
_initScriptSources(): Array<string | ((...args: any[]) => any)>;
|
|
@@ -23,6 +23,8 @@ export declare class BrowserFrame {
|
|
|
23
23
|
waitForNavigation(): Promise<void>;
|
|
24
24
|
abort(): Promise<void>;
|
|
25
25
|
evaluate(code: string | ((...args: any[]) => any), arg?: any): any;
|
|
26
|
+
_evaluateWith(code: string | ((...args: any[]) => any), args: any[]): any;
|
|
27
|
+
setContent(html: string): void;
|
|
26
28
|
goto(url: string, options?: { referer?: string }): Promise<Response | null>;
|
|
27
29
|
reload(): Promise<Response | null>;
|
|
28
30
|
goBack(): Promise<Response | null>;
|
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
import { BrowserFrame } from './BrowserFrame';
|
|
2
2
|
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { isChecked } from '../aria/state';
|
|
3
4
|
import { Locator } from './Locator';
|
|
4
5
|
import type { BrowserContext } from './BrowserContext';
|
|
5
|
-
import type {
|
|
6
|
+
import type { DialogOutcome, DialogType } from './Dialog';
|
|
7
|
+
import type { GetByRoleOptions, GetByTextOptions, WaitForState } from './Locator';
|
|
6
8
|
import type { RouteHandler, RoutePattern } from '../network/routing';
|
|
7
9
|
export declare interface IBrowserPageViewport {
|
|
8
10
|
width: number
|
|
9
11
|
height: number
|
|
10
12
|
}
|
|
11
|
-
export
|
|
13
|
+
export declare interface WaitForEventOptions {
|
|
14
|
+
predicate?: (event: any) => boolean
|
|
15
|
+
timeout?: number
|
|
16
|
+
}
|
|
17
|
+
export type PageEventType = 'console' | 'request' | 'response' | 'error' | 'load' | 'domcontentloaded' | 'dialog';
|
|
12
18
|
// eslint-disable-next-line pickier/no-unused-vars
|
|
13
19
|
export type PageEventHandler = (event: any) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Which event to settle on.
|
|
22
|
+
*
|
|
23
|
+
* A string is a Playwright glob and a RegExp is used as written, both against
|
|
24
|
+
* the URL. A function receives the event itself — the `Response` or the request
|
|
25
|
+
* — rather than its URL, so it can look at the status too. That is Playwright's
|
|
26
|
+
* split, and it is why this cannot simply be a `RoutePattern`, whose function
|
|
27
|
+
* form takes a URL.
|
|
28
|
+
*/
|
|
29
|
+
// eslint-disable-next-line pickier/no-unused-vars
|
|
30
|
+
export type EventTarget<T = any> = string | RegExp | ((event: T) => boolean);
|
|
31
|
+
/** The load states this page can actually report. */
|
|
32
|
+
export type LoadState = 'load' | 'domcontentloaded';
|
|
33
|
+
/** How a caller can name an `<option>`: by value, label, index, or bare value. */
|
|
34
|
+
export type SelectOptionValue = string | { value?: string, label?: string, index?: number }
|
|
35
|
+
/** A file to attach: a path on disk, or bytes with a name. */
|
|
36
|
+
export type InputFile = string | { name: string, mimeType?: string, buffer: Uint8Array | ArrayBuffer | string }
|
|
14
37
|
/**
|
|
15
38
|
* BrowserPage represents a browser page (tab or popup window)
|
|
16
39
|
* Compatible with Happy DOM's BrowserPage API
|
|
@@ -31,6 +54,7 @@ export declare class BrowserPage {
|
|
|
31
54
|
waitUntilComplete(): Promise<void>;
|
|
32
55
|
waitForNavigation(): Promise<void>;
|
|
33
56
|
abort(): Promise<void>;
|
|
57
|
+
_evaluateWith(code: string | ((...args: any[]) => any), args: any[]): any;
|
|
34
58
|
evaluate(code: string | ((...args: any[]) => any), arg?: any): any;
|
|
35
59
|
setViewport(viewport: IBrowserPageViewport): void;
|
|
36
60
|
goto(url: string, options?: { referer?: string }): Promise<Response | null>;
|
|
@@ -41,21 +65,45 @@ export declare class BrowserPage {
|
|
|
41
65
|
_applyEmulation(): void;
|
|
42
66
|
_runInitScripts(): void;
|
|
43
67
|
setDefaultTimeout(timeout: number): void;
|
|
68
|
+
setContent(html: string): Promise<void>;
|
|
69
|
+
emulateMedia(options?: {
|
|
70
|
+
media?: 'screen' | 'print' | null
|
|
71
|
+
colorScheme?: 'light' | 'dark' | null
|
|
72
|
+
reducedMotion?: 'reduce' | 'no-preference' | null
|
|
73
|
+
forcedColors?: 'active' | 'none' | null
|
|
74
|
+
}): Promise<void>;
|
|
44
75
|
_defaultTimeoutMs(): number;
|
|
45
|
-
waitForSelector(selector: string, options?: { timeout?: number, visible?: boolean }): Promise<any | null>;
|
|
76
|
+
waitForSelector(selector: string, options?: { timeout?: number, state?: WaitForState, visible?: boolean }): Promise<any | null>;
|
|
46
77
|
waitForFunction(options?: { timeout?: number, polling?: number | 'raf' }): Promise<any>;
|
|
47
78
|
waitForTimeout(ms: number): Promise<void>;
|
|
79
|
+
waitForEvent(event: PageEventType, optionsOrPredicate?: WaitForEventOptions | ((event: any) => boolean)): Promise<any>;
|
|
80
|
+
waitForResponse(urlOrPredicate: EventTarget, options?: { timeout?: number }): Promise<any>;
|
|
81
|
+
waitForRequest(urlOrPredicate: EventTarget, options?: { timeout?: number }): Promise<any>;
|
|
82
|
+
waitForLoadState(state?: LoadState, options?: { timeout?: number }): Promise<void>;
|
|
83
|
+
waitForURL(urlOrPredicate: EventTarget<string>, options?: { timeout?: number }): Promise<void>;
|
|
48
84
|
click(selector: string, options?: { delay?: number, button?: 'left' | 'right' | 'middle' }): Promise<void>;
|
|
49
85
|
type(selector: string, text: string, options?: { delay?: number }): Promise<void>;
|
|
50
86
|
_typeIntoElement(element: any, text: string, options?: { delay?: number }): Promise<void>;
|
|
51
87
|
fill(selector: string, value: string): Promise<void>;
|
|
88
|
+
_selectOptions(element: any, wanted: SelectOptionValue[]): Promise<string[]>;
|
|
89
|
+
_setInputFiles(element: any, files: InputFile[]): Promise<void>;
|
|
90
|
+
_dblclickElement(element: any): Promise<void>;
|
|
52
91
|
_fillElement(element: any, value: string): Promise<void>;
|
|
92
|
+
selectOption(selector: string, values: SelectOptionValue | SelectOptionValue[] | null): Promise<string[]>;
|
|
93
|
+
setInputFiles(selector: string, files: InputFile | InputFile[] | null): Promise<void>;
|
|
94
|
+
press(selector: string, key: string, options?: { delay?: number }): Promise<void>;
|
|
95
|
+
clear(selector: string): Promise<void>;
|
|
96
|
+
dblclick(selector: string): Promise<void>;
|
|
97
|
+
check(selector: string): Promise<void>;
|
|
98
|
+
uncheck(selector: string): Promise<void>;
|
|
53
99
|
focus(selector: string): Promise<void>;
|
|
54
100
|
blur(selector: string): Promise<void>;
|
|
55
101
|
hover(selector: string): Promise<void>;
|
|
56
102
|
_hoverElement(element: any): Promise<void>;
|
|
57
103
|
get keyboard(): {
|
|
58
104
|
press: (key: string, options?: { delay?: number }) => Promise<void>
|
|
105
|
+
down: (key: string) => Promise<void>
|
|
106
|
+
up: (key: string) => Promise<void>
|
|
59
107
|
type: (text: string, options?: { delay?: number }) => Promise<void>
|
|
60
108
|
};
|
|
61
109
|
get mouse(): {
|
|
@@ -72,6 +120,8 @@ export declare class BrowserPage {
|
|
|
72
120
|
getByAltText(text: string | RegExp, options?: GetByTextOptions): Locator;
|
|
73
121
|
getByTitle(text: string | RegExp, options?: GetByTextOptions): Locator;
|
|
74
122
|
getByTestId(testId: string | RegExp): Locator;
|
|
123
|
+
$eval(selector: string, fn: string | ((element: any, arg?: any) => any), arg?: any): Promise<any>;
|
|
124
|
+
$$eval(selector: string, fn: string | ((elements: any[], arg?: any) => any), arg?: any): Promise<any>;
|
|
75
125
|
title(): Promise<string>;
|
|
76
126
|
textContent(selector: string): Promise<string | null>;
|
|
77
127
|
innerText(selector: string): Promise<string>;
|
|
@@ -87,6 +137,7 @@ export declare class BrowserPage {
|
|
|
87
137
|
on(event: PageEventType, handler: PageEventHandler): void;
|
|
88
138
|
off(event: PageEventType, handler: PageEventHandler): void;
|
|
89
139
|
emit(event: PageEventType, data: any): void;
|
|
140
|
+
_requestDialog(type: DialogType, message: string, defaultValue?: string): DialogOutcome;
|
|
90
141
|
_emitConsole(type: string, ...args: any[]): void;
|
|
91
142
|
_emitRequest(request: any): void;
|
|
92
143
|
_emitResponse(response: any): void;
|
|
@@ -94,7 +145,7 @@ export declare class BrowserPage {
|
|
|
94
145
|
dragAndDrop(source: string, target: string, options?: { delay?: number }): Promise<void>;
|
|
95
146
|
route(url: RoutePattern, handler: RouteHandler): Promise<void>;
|
|
96
147
|
unroute(url?: RoutePattern, handler?: RouteHandler): Promise<void>;
|
|
97
|
-
|
|
148
|
+
_syncRouting(): void;
|
|
98
149
|
setRequestInterception(enabled: boolean): Promise<void>;
|
|
99
150
|
screenshot(options?: {
|
|
100
151
|
type?: 'png' | 'jpeg' | 'webp'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** What a dialog was answered with. */
|
|
2
|
+
export declare interface DialogOutcome {
|
|
3
|
+
accepted: boolean
|
|
4
|
+
text: string | null
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A dialog the page opened, and the decision a handler makes about it (#1612).
|
|
8
|
+
*
|
|
9
|
+
* `confirm()` returned a hardcoded `false`, so a confirm-gated action could only
|
|
10
|
+
* ever be cancelled:
|
|
11
|
+
*
|
|
12
|
+
* deleteButton.addEventListener('click', () => {
|
|
13
|
+
* if (!confirm('Delete this trail?')) return
|
|
14
|
+
* removeTrail() // unreachable, always
|
|
15
|
+
* })
|
|
16
|
+
*
|
|
17
|
+
* The test clicked the button, nothing happened, and the assertion failed with no
|
|
18
|
+
* hint that a dialog was involved. The "delete" half of every destructive flow
|
|
19
|
+
* was untestable, and destructive flows are the ones most worth a test.
|
|
20
|
+
*
|
|
21
|
+
* `alert()` was the benign one — a no-op is close enough to auto-dismissing —
|
|
22
|
+
* except that there was no way to assert an alert had happened at all.
|
|
23
|
+
*/
|
|
24
|
+
/** `beforeunload` is deliberately absent: nothing here fires it. */
|
|
25
|
+
export type DialogType = 'alert' | 'confirm' | 'prompt';
|
|
26
|
+
export declare class Dialog {
|
|
27
|
+
readonly type: DialogType;
|
|
28
|
+
readonly message: string;
|
|
29
|
+
readonly defaultValue?: string;
|
|
30
|
+
constructor(type: DialogType, message: string, defaultValue?: string);
|
|
31
|
+
accept(promptText?: string): Promise<void>;
|
|
32
|
+
dismiss(): Promise<void>;
|
|
33
|
+
get _wasSettled(): boolean;
|
|
34
|
+
_outcome(): DialogOutcome;
|
|
35
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { accessibleName } from '../aria/roles';
|
|
1
|
+
import { accessibleDescription, accessibleName } from '../aria/roles';
|
|
2
|
+
import { checkedState, isChecked } from '../aria/state';
|
|
3
|
+
import type { InputFile, SelectOptionValue } from './BrowserPage';
|
|
2
4
|
/** @internal Collapse whitespace, the way Playwright compares rendered text. */
|
|
3
5
|
export declare function normalize(value: string | null | undefined): string;
|
|
4
6
|
/**
|
|
@@ -43,6 +45,8 @@ export declare interface GetByTextOptions {
|
|
|
43
45
|
export declare interface FilterOptions {
|
|
44
46
|
hasText?: string | RegExp
|
|
45
47
|
hasNotText?: string | RegExp
|
|
48
|
+
has?: Locator
|
|
49
|
+
hasNot?: Locator
|
|
46
50
|
}
|
|
47
51
|
export declare interface WaitForOptions {
|
|
48
52
|
state?: WaitForState
|
|
@@ -52,8 +56,16 @@ export declare interface WaitForOptions {
|
|
|
52
56
|
export declare interface ActionOptions {
|
|
53
57
|
timeout?: number
|
|
54
58
|
}
|
|
55
|
-
/**
|
|
56
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Returns the current matches, re-evaluated on each call.
|
|
61
|
+
*
|
|
62
|
+
* The optional root is what makes `filter({ has })` work. Playwright queries an
|
|
63
|
+
* inner locator *starting from the outer match*, not from the document, so a
|
|
64
|
+
* locator has to be answerable against an arbitrary element rather than only
|
|
65
|
+
* against the page. Every derived locator threads it through to its parent.
|
|
66
|
+
*/
|
|
67
|
+
// eslint-disable-next-line pickier/no-unused-vars
|
|
68
|
+
declare type Resolver = (root?: any) => any[];
|
|
57
69
|
/**
|
|
58
70
|
* What a wait is waiting for.
|
|
59
71
|
*
|
|
@@ -70,6 +82,9 @@ export declare class Locator {
|
|
|
70
82
|
elementHandles(): Promise<any[]>;
|
|
71
83
|
locator(selector: string): Locator;
|
|
72
84
|
filter(options: FilterOptions): Locator;
|
|
85
|
+
or(other: Locator): Locator;
|
|
86
|
+
and(other: Locator): Locator;
|
|
87
|
+
get page(): any;
|
|
73
88
|
nth(index: number): Locator;
|
|
74
89
|
first(): Locator;
|
|
75
90
|
last(): Locator;
|
|
@@ -87,11 +102,16 @@ export declare class Locator {
|
|
|
87
102
|
innerHTML(): Promise<string>;
|
|
88
103
|
inputValue(): Promise<string>;
|
|
89
104
|
getAttribute(name: string): Promise<string | null>;
|
|
105
|
+
allTextContents(): Promise<string[]>;
|
|
106
|
+
allInnerTexts(): Promise<string[]>;
|
|
90
107
|
ariaRole(): Promise<string | null>;
|
|
91
108
|
accessibleName(): Promise<string>;
|
|
109
|
+
accessibleDescription(): Promise<string>;
|
|
110
|
+
selectedValues(): Promise<string[]>;
|
|
92
111
|
isVisible(): Promise<boolean>;
|
|
93
112
|
isHidden(): Promise<boolean>;
|
|
94
113
|
isChecked(): Promise<boolean>;
|
|
114
|
+
checkedState(): Promise<boolean | 'mixed' | undefined>;
|
|
95
115
|
isEnabled(): Promise<boolean>;
|
|
96
116
|
isDisabled(): Promise<boolean>;
|
|
97
117
|
isEditable(): Promise<boolean>;
|
|
@@ -102,5 +122,15 @@ export declare class Locator {
|
|
|
102
122
|
fill(value: string, options?: ActionOptions): Promise<void>;
|
|
103
123
|
type(text: string, options?: { delay?: number, timeout?: number }): Promise<void>;
|
|
104
124
|
check(options?: ActionOptions): Promise<void>;
|
|
125
|
+
selectOption(values: SelectOptionValue | SelectOptionValue[] | null, options?: ActionOptions): Promise<string[]>;
|
|
126
|
+
setInputFiles(files: InputFile | InputFile[] | null, options?: ActionOptions): Promise<void>;
|
|
127
|
+
press(key: string, options?: ActionOptions & { delay?: number }): Promise<void>;
|
|
128
|
+
clear(options?: ActionOptions): Promise<void>;
|
|
129
|
+
dblclick(options?: ActionOptions): Promise<void>;
|
|
130
|
+
setChecked(checked: boolean, options?: ActionOptions): Promise<void>;
|
|
105
131
|
uncheck(options?: ActionOptions): Promise<void>;
|
|
132
|
+
boundingBox(options?: ActionOptions): Promise<{ x: number, y: number, width: number, height: number } | null>;
|
|
133
|
+
scrollIntoViewIfNeeded(options?: ActionOptions): Promise<void>;
|
|
134
|
+
evaluate(fn: string | ((element: any, arg?: any) => any), arg?: any, options?: ActionOptions): Promise<any>;
|
|
135
|
+
evaluateAll(fn: string | ((elements: any[], arg?: any) => any), arg?: any): Promise<any>;
|
|
106
136
|
}
|