codeceptjs 4.2.0-beta.2 → 4.2.0-beta.3

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.
@@ -28,9 +28,9 @@ process lifecycle, the same way Playwright manages its own browser process.
28
28
  never spawns or kills anything, no matter what `binaryPath`/`port` are set to.
29
29
  * **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
30
30
  the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
31
- spawns `obscura serve --port <port> --allow-private-network` (`port` from the config, or a
32
- free port picked automatically), waits for it to answer, connects, and kills it in
33
- `_finishTest`.
31
+ spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
32
+ the config, or a free port picked automatically), waits for it to answer, connects, and kills
33
+ it in `_finishTest`.
34
34
  * **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
35
35
  answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
36
36
  before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -43,12 +43,13 @@ Download a release binary and put it on your `PATH` (or point `binaryPath`/`OBSC
43
43
  it directly) and the helper launches and tears it down for you automatically:
44
44
 
45
45
  ```sh
46
- curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.0/obscura-x86_64-linux.tar.gz | tar xz
46
+ curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.2/obscura-x86_64-linux.tar.gz | tar xz
47
47
  ```
48
48
 
49
- `--allow-private-network` is always passed by this helper (it's required to reach apps running
50
- on `localhost`/private IPs, e.g. a dev server on `127.0.0.1:8000` — Obscura blocks
51
- private-network requests by default).
49
+ `--allow-private-network` and `--allow-file-access` are always passed by this helper: the first
50
+ is required to reach apps running on `localhost`/private IPs, e.g. a dev server on
51
+ `127.0.0.1:8000`, the second to let `attachFile` upload local files. Obscura blocks both by
52
+ default.
52
53
 
53
54
  ## Config presets
54
55
 
@@ -67,7 +68,7 @@ Set them explicitly in your own config to skip probing or to force a mode.
67
68
  ## Limitations
68
69
 
69
70
  * `input` is always `synthetic`, even on rendering builds — see `input` above.
70
- * No frames, popups, or file uploads.
71
+ * No frames or popups.
71
72
  * On `-no-render` builds and v0.1.x: no screenshots, no visibility assertions
72
73
  (`seeElement`/`dontSeeElement` always throw) — only DOM presence
73
74
  (`seeElementInDOM`/`dontSeeElementInDOM`) is meaningful without a layout engine.
@@ -78,7 +78,7 @@ Type: [object][6]
78
78
  * `ignoreHTTPSErrors` **[boolean][27]?** Allows access to untrustworthy pages, e.g. to a page with an expired certificate. Default value is `false`
79
79
  * `bypassCSP` **[boolean][27]?** bypass Content Security Policy or CSP
80
80
  * `highlightElement` **[boolean][27]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
81
- * `visibleLocator` **[boolean][27]?** append [`visible()`][49] to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`, which check the DOM regardless of visibility. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
81
+ * `visibleLocator` **[boolean][27]?** append [`visible()`][49] to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to steps that must reach hidden elements: `grab*` methods, `scrollTo`, `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
82
82
  * `recordHar` **[object][6]?** record HAR and will be saved to `output/har`. See more of [HAR options][3].
83
83
  * `testIdAttribute` **[string][9]?** locate elements based on the testIdAttribute. See more of [locate by test id][50].
84
84
  * `storageState` **([string][9] | [object][6])?** Playwright storage state (path to JSON file or object)
@@ -21,9 +21,16 @@ function parsePlaywrightBrowsers(output) {
21
21
  return versions.join(', ')
22
22
  }
23
23
 
24
+ // Bun has its own package runner and a Bun-only install has no `npx` on PATH at all, so the
25
+ // runner has to follow the runtime that is actually executing rather than what PATH happens to hold.
26
+ function getPackageRunner() {
27
+ if (process.versions.bun) return 'bunx'
28
+ return 'npx'
29
+ }
30
+
24
31
  async function getPlaywrightBrowsers() {
25
32
  try {
26
- const info = execSync('npx playwright install --dry-run').toString().trim()
33
+ const info = execSync(`${getPackageRunner()} playwright install --dry-run`).toString().trim()
27
34
  return parsePlaywrightBrowsers(info)
28
35
  } catch (err) {
29
36
  return 'Playwright not installed'
@@ -85,7 +92,7 @@ export default async function (path) {
85
92
  output.print('***************************************')
86
93
  }
87
94
 
88
- export { parsePlaywrightBrowsers, getRuntimeInfo }
95
+ export { parsePlaywrightBrowsers, getRuntimeInfo, getPackageRunner }
89
96
 
90
97
  export const getMachineInfo = async () => {
91
98
  const info = {
@@ -1631,6 +1631,9 @@ class CDPBrowser extends Helper {
1631
1631
  const value = Array.isArray(option) ? option.map(String) : String(option)
1632
1632
  const res = await this._run(this._candidates(select, 'field'), 'select', { value }, context)
1633
1633
  if (!res.found) throw new ElementNotFound(select, 'Selectable field')
1634
+ if (res.result === '__RADIOGROUP_MULTI__') {
1635
+ throw new Error(`selectOption: a radio group holds one value, but ${value.length} options were passed: ${value.join(', ')}`)
1636
+ }
1634
1637
  if (res.result === false) throw new Error(`Option "${Array.isArray(option) ? option.join(',') : option}" not found in ${new Locator(select).toString()}`)
1635
1638
  }
1636
1639
 
@@ -1810,7 +1813,6 @@ class CDPBrowser extends Helper {
1810
1813
  */
1811
1814
  async waitInUrl(urlPart, sec = null) {
1812
1815
  const timeout = sec || this.options.waitForTimeout
1813
- const expectedUrl = resolveUrl(urlPart, this.options.url)
1814
1816
  let lastUrl = ''
1815
1817
  try {
1816
1818
  return await this._poll(
@@ -1822,7 +1824,7 @@ class CDPBrowser extends Helper {
1822
1824
  'placeholder',
1823
1825
  )
1824
1826
  } catch (e) {
1825
- throw new Error(`expected url to include ${expectedUrl}, but found ${lastUrl}`)
1827
+ throw new Error(`expected url to include ${urlPart}, but found ${lastUrl}`)
1826
1828
  }
1827
1829
  }
1828
1830
 
@@ -45,9 +45,9 @@ const config = {}
45
45
  * never spawns or kills anything, no matter what `binaryPath`/`port` are set to.
46
46
  * - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
47
47
  * the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
48
- * spawns `obscura serve --port <port> --allow-private-network` (`port` from the config, or a
49
- * free port picked automatically), waits for it to answer, connects, and kills it in
50
- * `_finishTest`.
48
+ * spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
49
+ * the config, or a free port picked automatically), waits for it to answer, connects, and kills
50
+ * it in `_finishTest`.
51
51
  * - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
52
52
  * answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
53
53
  * before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -60,12 +60,13 @@ const config = {}
60
60
  * it directly) and the helper launches and tears it down for you automatically:
61
61
  *
62
62
  * ```sh
63
- * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.0/obscura-x86_64-linux.tar.gz | tar xz
63
+ * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.2/obscura-x86_64-linux.tar.gz | tar xz
64
64
  * ```
65
65
  *
66
- * `--allow-private-network` is always passed by this helper (it's required to reach apps running
67
- * on `localhost`/private IPs, e.g. a dev server on `127.0.0.1:8000` — Obscura blocks
68
- * private-network requests by default).
66
+ * `--allow-private-network` and `--allow-file-access` are always passed by this helper: the first
67
+ * is required to reach apps running on `localhost`/private IPs, e.g. a dev server on
68
+ * `127.0.0.1:8000`, the second to let `attachFile` upload local files. Obscura blocks both by
69
+ * default.
69
70
  *
70
71
  * ## Config presets
71
72
  *
@@ -84,7 +85,7 @@ const config = {}
84
85
  * ## Limitations
85
86
  *
86
87
  * - `input` is always `synthetic`, even on rendering builds — see `input` above.
87
- * - No frames, popups, or file uploads.
88
+ * - No frames or popups.
88
89
  * - On `-no-render` builds and v0.1.x: no screenshots, no visibility assertions
89
90
  * (`seeElement`/`dontSeeElement` always throw) — only DOM presence
90
91
  * (`seeElementInDOM`/`dontSeeElementInDOM`) is meaningful without a layout engine.
@@ -179,7 +180,7 @@ class Obscura extends CDPBrowser {
179
180
  const port = this.options.port || (await this._findFreePort())
180
181
  this.options.port = port
181
182
  this.serverError = null
182
- this.serverProcess = spawn(binaryPath, ['serve', '--port', String(port), '--allow-private-network'], { stdio: 'ignore' })
183
+ this.serverProcess = spawn(binaryPath, ['serve', '--port', String(port), '--allow-private-network', '--allow-file-access'], { stdio: 'ignore' })
183
184
  this.serverProcess.on('error', err => {
184
185
  this.serverError = err
185
186
  })
@@ -50,7 +50,7 @@ let defaultSelectorEnginesInitialized = false
50
50
  const popupStore = new Popup()
51
51
  const consoleLogStore = new Console()
52
52
  const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron']
53
- const domPresenceSteps = ['seeElementInDOM', 'dontSeeElementInDOM', 'seeNumberOfElements']
53
+ const visibilityAgnosticSteps = ['seeElementInDOM', 'dontSeeElementInDOM', 'seeNumberOfElements', 'scrollTo']
54
54
  const checkableRoles = ['checkbox', 'radio', 'switch']
55
55
 
56
56
  import { setRestartStrategy, restartsSession, restartsContext, restartsBrowser } from './extras/PlaywrightRestartOpts.js'
@@ -103,7 +103,7 @@ const pathSeparator = path.sep
103
103
  * @prop {boolean} [ignoreHTTPSErrors] - Allows access to untrustworthy pages, e.g. to a page with an expired certificate. Default value is `false`
104
104
  * @prop {boolean} [bypassCSP] - bypass Content Security Policy or CSP
105
105
  * @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
106
- * @prop {boolean} [visibleLocator=false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`, which check the DOM regardless of visibility. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
106
+ * @prop {boolean} [visibleLocator=false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to steps that must reach hidden elements: `grab*` methods, `scrollTo`, `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
107
107
  * @prop {object} [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
108
108
  * @prop {string} [testIdAttribute=data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
109
109
  * @prop {string|object} [storageState] - Playwright storage state (path to JSON file or object)
@@ -559,7 +559,8 @@ class Playwright extends Helper {
559
559
  }
560
560
 
561
561
  _beforeStep(step) {
562
- store.visibleLocator = step.opts?.visibleLocator ?? (this.options.visibleLocator && !domPresenceSteps.includes(step.helperMethod))
562
+ const reachesHidden = step.helperMethod?.startsWith('grab') || visibilityAgnosticSteps.includes(step.helperMethod)
563
+ store.visibleLocator = step.opts?.visibleLocator ?? (this.options.visibleLocator && !reachesHidden)
563
564
  }
564
565
 
565
566
  async _before(test) {
@@ -1525,6 +1526,7 @@ class Playwright extends Helper {
1525
1526
  assertElementExists(el, locator)
1526
1527
  }
1527
1528
 
1529
+ await el.scrollIntoViewIfNeeded()
1528
1530
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
1529
1531
  const { x, y } = await clickablePoint(el)
1530
1532
  await this.page.mouse.move(x + offsetX, y + offsetY)
@@ -845,6 +845,9 @@ class Puppeteer extends Helper {
845
845
  }
846
846
  }
847
847
 
848
+ if (!(await el.isIntersectingViewport({ threshold: 1 }))) {
849
+ await el.evaluate(el => el.scrollIntoView({ block: 'center', inline: 'center' }))
850
+ }
848
851
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
849
852
  const { x, y } = await getClickablePoint(el)
850
853
  await this.page.mouse.move(x + offsetX, y + offsetY)
@@ -387,6 +387,17 @@ export default function installCodeceptClient(xpathNeedsPolyfill) {
387
387
  return true
388
388
  }
389
389
 
390
+ if (resolveRole(el) === 'radiogroup') {
391
+ if (values.length > 1) return '__RADIOGROUP_MULTI__'
392
+ const radios = Array.from(el.querySelectorAll('[role="radio"]'))
393
+ const [wanted] = values
394
+ const named = (radio, matchFn) => roleTextCandidates(radio).some(matchFn)
395
+ const radio = radios.find(r => named(r, t => t === wanted)) || radios.find(r => named(r, t => t.indexOf(wanted) !== -1))
396
+ if (!radio) return false
397
+ radio.click()
398
+ return true
399
+ }
400
+
390
401
  // ARIA combobox/listbox widgets: click the trigger (if any) to reveal the
391
402
  // listbox, then click each matching [role="option"].
392
403
  let container = el
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "4.2.0-beta.2",
3
+ "version": "4.2.0-beta.3",
4
4
  "type": "module",
5
5
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
6
6
  "keywords": [
@@ -3429,9 +3429,9 @@ declare namespace CodeceptJS {
3429
3429
  * never spawns or kills anything, no matter what `binaryPath`/`port` are set to.
3430
3430
  * - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
3431
3431
  * the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
3432
- * spawns `obscura serve --port <port> --allow-private-network` (`port` from the config, or a
3433
- * free port picked automatically), waits for it to answer, connects, and kills it in
3434
- * `_finishTest`.
3432
+ * spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
3433
+ * the config, or a free port picked automatically), waits for it to answer, connects, and kills
3434
+ * it in `_finishTest`.
3435
3435
  * - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
3436
3436
  * answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
3437
3437
  * before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -3444,12 +3444,13 @@ declare namespace CodeceptJS {
3444
3444
  * it directly) and the helper launches and tears it down for you automatically:
3445
3445
  *
3446
3446
  * ```sh
3447
- * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.0/obscura-x86_64-linux.tar.gz | tar xz
3447
+ * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.2/obscura-x86_64-linux.tar.gz | tar xz
3448
3448
  * ```
3449
3449
  *
3450
- * `--allow-private-network` is always passed by this helper (it's required to reach apps running
3451
- * on `localhost`/private IPs, e.g. a dev server on `127.0.0.1:8000` — Obscura blocks
3452
- * private-network requests by default).
3450
+ * `--allow-private-network` and `--allow-file-access` are always passed by this helper: the first
3451
+ * is required to reach apps running on `localhost`/private IPs, e.g. a dev server on
3452
+ * `127.0.0.1:8000`, the second to let `attachFile` upload local files. Obscura blocks both by
3453
+ * default.
3453
3454
  *
3454
3455
  * ## Config presets
3455
3456
  *
@@ -3468,7 +3469,7 @@ declare namespace CodeceptJS {
3468
3469
  * ## Limitations
3469
3470
  *
3470
3471
  * - `input` is always `synthetic`, even on rendering builds — see `input` above.
3471
- * - No frames, popups, or file uploads.
3472
+ * - No frames or popups.
3472
3473
  * - On `-no-render` builds and v0.1.x: no screenshots, no visibility assertions
3473
3474
  * (`seeElement`/`dontSeeElement` always throw) — only DOM presence
3474
3475
  * (`seeElementInDOM`/`dontSeeElementInDOM`) is meaningful without a layout engine.
@@ -3607,7 +3608,7 @@ declare namespace CodeceptJS {
3607
3608
  * @property [ignoreHTTPSErrors] - Allows access to untrustworthy pages, e.g. to a page with an expired certificate. Default value is `false`
3608
3609
  * @property [bypassCSP] - bypass Content Security Policy or CSP
3609
3610
  * @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
3610
- * @property [visibleLocator = false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`, which check the DOM regardless of visibility. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
3611
+ * @property [visibleLocator = false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to steps that must reach hidden elements: `grab*` methods, `scrollTo`, `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
3611
3612
  * @property [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
3612
3613
  * @property [testIdAttribute = data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
3613
3614
  * @property [storageState] - Playwright storage state (path to JSON file or object)
@@ -3462,9 +3462,9 @@ declare namespace CodeceptJS {
3462
3462
  * never spawns or kills anything, no matter what `binaryPath`/`port` are set to.
3463
3463
  * - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
3464
3464
  * the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
3465
- * spawns `obscura serve --port <port> --allow-private-network` (`port` from the config, or a
3466
- * free port picked automatically), waits for it to answer, connects, and kills it in
3467
- * `_finishTest`.
3465
+ * spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
3466
+ * the config, or a free port picked automatically), waits for it to answer, connects, and kills
3467
+ * it in `_finishTest`.
3468
3468
  * - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
3469
3469
  * answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
3470
3470
  * before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -3477,12 +3477,13 @@ declare namespace CodeceptJS {
3477
3477
  * it directly) and the helper launches and tears it down for you automatically:
3478
3478
  *
3479
3479
  * ```sh
3480
- * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.0/obscura-x86_64-linux.tar.gz | tar xz
3480
+ * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.2/obscura-x86_64-linux.tar.gz | tar xz
3481
3481
  * ```
3482
3482
  *
3483
- * `--allow-private-network` is always passed by this helper (it's required to reach apps running
3484
- * on `localhost`/private IPs, e.g. a dev server on `127.0.0.1:8000` — Obscura blocks
3485
- * private-network requests by default).
3483
+ * `--allow-private-network` and `--allow-file-access` are always passed by this helper: the first
3484
+ * is required to reach apps running on `localhost`/private IPs, e.g. a dev server on
3485
+ * `127.0.0.1:8000`, the second to let `attachFile` upload local files. Obscura blocks both by
3486
+ * default.
3486
3487
  *
3487
3488
  * ## Config presets
3488
3489
  *
@@ -3501,7 +3502,7 @@ declare namespace CodeceptJS {
3501
3502
  * ## Limitations
3502
3503
  *
3503
3504
  * - `input` is always `synthetic`, even on rendering builds — see `input` above.
3504
- * - No frames, popups, or file uploads.
3505
+ * - No frames or popups.
3505
3506
  * - On `-no-render` builds and v0.1.x: no screenshots, no visibility assertions
3506
3507
  * (`seeElement`/`dontSeeElement` always throw) — only DOM presence
3507
3508
  * (`seeElementInDOM`/`dontSeeElementInDOM`) is meaningful without a layout engine.
@@ -3641,7 +3642,7 @@ declare namespace CodeceptJS {
3641
3642
  * @property [ignoreHTTPSErrors] - Allows access to untrustworthy pages, e.g. to a page with an expired certificate. Default value is `false`
3642
3643
  * @property [bypassCSP] - bypass Content Security Policy or CSP
3643
3644
  * @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
3644
- * @property [visibleLocator = false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`, which check the DOM regardless of visibility. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
3645
+ * @property [visibleLocator = false] - append [`visible()`](https://playwright.dev/docs/api/class-locator#locator-visible) to locators, so only visible elements are matched. Requires Playwright 1.63 or newer. Switch it off for a single step with `stepOpts({ visibleLocator: false })`. Not applied to `dragAndDrop`, which passes selectors to Playwright directly, nor to steps that must reach hidden elements: `grab*` methods, `scrollTo`, `seeElementInDOM`, `dontSeeElementInDOM` and `seeNumberOfElements`. When enabled, a locator matching only hidden elements fails as "element not found" instead of timing out on actionability, `strict` mode ignores hidden duplicates, and elements hidden by CSS (like a custom checkbox built on a visually hidden `input`) are no longer found.
3645
3646
  * @property [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
3646
3647
  * @property [testIdAttribute = data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
3647
3648
  * @property [storageState] - Playwright storage state (path to JSON file or object)