codeceptjs 4.1.0 → 4.2.0-beta.2

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 (49) hide show
  1. package/docs/advanced.md +1 -1
  2. package/docs/alternative-browsers.md +153 -0
  3. package/docs/basics.md +9 -1
  4. package/docs/configuration.md +2 -0
  5. package/docs/helpers/CDPBrowser.md +2138 -0
  6. package/docs/helpers/Kitesurf.md +118 -0
  7. package/docs/helpers/Obscura.md +210 -0
  8. package/docs/helpers/Playwright.md +5 -2
  9. package/docs/migration-4.md +3 -1
  10. package/docs/parallel.md +10 -0
  11. package/docs/plugins/screencast.md +18 -13
  12. package/docs/plugins.md +1 -1
  13. package/lib/command/info.js +11 -3
  14. package/lib/command/workers/runTests.js +14 -20
  15. package/lib/container.js +6 -0
  16. package/lib/data/context.js +7 -5
  17. package/lib/element/WebElement.js +5 -0
  18. package/lib/helper/Appium.js +14 -2
  19. package/lib/helper/CDPBrowser.js +3004 -0
  20. package/lib/helper/Kitesurf.js +139 -0
  21. package/lib/helper/Obscura.js +344 -0
  22. package/lib/helper/Playwright.js +41 -10
  23. package/lib/helper/Puppeteer.js +30 -7
  24. package/lib/helper/WebDriver.js +27 -6
  25. package/lib/helper/clientscripts/cdpBrowserClient.js +486 -0
  26. package/lib/helper/clientscripts/xpathPolyfill.js +31 -0
  27. package/lib/helper/errors/MultipleElementsFound.js +60 -3
  28. package/lib/helper/extras/CDPConnection.js +92 -0
  29. package/lib/helper/extras/CDPElementHandle.js +27 -0
  30. package/lib/helper/extras/PlaywrightLocator.js +2 -2
  31. package/lib/helper/extras/apngAssembler.js +156 -0
  32. package/lib/html.js +9 -2
  33. package/lib/listener/retryEnhancer.js +2 -1
  34. package/lib/listener/steps.js +8 -0
  35. package/lib/locator.js +7 -2
  36. package/lib/mocha/asyncWrapper.js +7 -1
  37. package/lib/mocha/hooks.js +10 -0
  38. package/lib/parser.js +14 -2
  39. package/lib/plugin/junitReporter.js +17 -1
  40. package/lib/plugin/screencast.js +116 -24
  41. package/lib/step/base.js +15 -3
  42. package/lib/step/config.js +1 -0
  43. package/lib/store.js +6 -0
  44. package/lib/utils/loaderCheck.js +6 -0
  45. package/lib/utils.js +1 -1
  46. package/lib/workers.js +17 -0
  47. package/package.json +5 -2
  48. package/typings/promiseBasedTypes.d.ts +1835 -0
  49. package/typings/types.d.ts +1848 -0
@@ -0,0 +1,2138 @@
1
+ ---
2
+ permalink: /helpers/CDPBrowser
3
+ editLink: false
4
+ sidebar: auto
5
+ title: CDPBrowser
6
+ ---
7
+
8
+ <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
9
+
10
+ ## CDPBrowser
11
+
12
+ **Extends Helper**
13
+
14
+ CDPBrowser drives a browser directly over the raw Chrome DevTools Protocol, without depending
15
+ on Puppeteer, Playwright, or WebDriver. It opens its own WebSocket connection (via `CDPConnection`),
16
+ creates and attaches to a fresh target per test, and evaluates expressions through `Runtime.evaluate`.
17
+
18
+ It is intended as the minimal, dependency-light base class for helpers that only need navigation,
19
+ script evaluation, and simple in-page element interaction (installed lazily through the
20
+ `window.__codecept` client script). It does not launch a browser itself — point `endpoint` at an
21
+ already-running Chrome (or any CDP-compatible browser) started with `--remote-debugging-port`.
22
+
23
+ ## Example
24
+
25
+ ```js
26
+ // inside codecept.conf.js
27
+ {
28
+ helpers: {
29
+ CDPBrowser: {
30
+ url: 'http://localhost',
31
+ endpoint: 'http://127.0.0.1:9222',
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+
38
+
39
+ ## Configuration
40
+
41
+ This helper should be configured in codecept.conf.js
42
+
43
+ Type: [object][5]
44
+
45
+ ### Properties
46
+
47
+ * `url` **[string][2]?** base url of website to be tested.
48
+ * `endpoint` **[string][2]?** Chrome DevTools Protocol endpoint. Either an `http(s)://` address exposing `/json/version` (from which the `webSocketDebuggerUrl` is resolved) or a raw `ws(s)://` debugger URL.
49
+ * `headers` **[object][5]?** headers sent with the endpoint resolution request and the WebSocket handshake. Useful for authenticated remote browser providers.
50
+ * `input` **[string][2]?** how synthetic user actions (click, fill, etc.) are dispatched by helpers built on top of this class. `auto` picks `cdp` when a real layout engine is detected and `synthetic` otherwise; can be pinned to `cdp` or `synthetic`.
51
+ * `xpathPolyfill` **([string][2] | [boolean][7])?** whether to inject the bundled XPath polyfill before installing the in-page client. `auto` probes the page and only injects when `document.evaluate` is unavailable or broken; `true`/`false` force the behavior.
52
+ * `capabilities` **[object][5]?** pre-seed detected browser capabilities (`layout`, `xpath`, `screenshot`, `innerText`) to skip runtime probing. Values set here are never overwritten by `_probeCapabilities`/`_ensureClient`.
53
+ * `waitForTimeout` **[number][8]?** default wait* timeout in seconds, used by helpers built on top of this class.
54
+ * `waitForAction` **[number][8]?** only takes effect when set explicitly: a literal fixed pacing sleep (in milliseconds) after click, type, or other interactions, mirroring other browser helpers. Left unset, actions settle in an event-aware way instead — near-instant when nothing navigates, waiting for the navigation to actually finish (not a guessed fixed delay) when one does.
55
+ * `pollInterval` **[number][8]?** interval in milliseconds between retries while polling for a condition (e.g. page ready state, `waitFor*`). Distinct from `waitForAction`.
56
+ * `getPageTimeout` **[number][8]?** maximum time in seconds to wait for a page to finish loading after navigation or reload; also used as the CDP command timeout (in ms, x1000).
57
+ * `waitForNavigation` **[string][2]?** when to consider a navigation finished: `load`, `domcontentloaded`, or `networkidle`. Mirrors the Puppeteer helper's option name. `networkidle` waits for the CDP `networkIdle` lifecycle event, which on a busy page can lag `load` by a second or more — only opt in if the extra wait is actually needed.
58
+
59
+
60
+
61
+ ## Methods
62
+
63
+ ### Parameters
64
+
65
+ * `config` **CDPBrowserConfig**&#x20;
66
+
67
+ ### _after
68
+
69
+ Hook executed after each test. Closes the target opened in `_before` via `Target.closeTarget`
70
+ and clears `this.targetId`/`this.sessionId`. The underlying `CDPConnection` is left open so it
71
+ can be reused by the next test.
72
+
73
+ ### _armActionSettle
74
+
75
+ Arms the event-aware settle's navigation-start listener. Must be called *before* the action
76
+ that might trigger a navigation is dispatched, not after — see `_ensureLifecycleListener` for
77
+ why. Returns `null` when `options.waitForAction` was set explicitly, since `_waitForAction`
78
+ ignores the armed listener entirely in that case (a literal fixed sleep, as before this round).
79
+
80
+ No timeout here: `_waitForAction` applies the grace window itself, starting from when *it*
81
+ runs (after the action's own dispatch already resolved), racing this already-armed listener
82
+ against a fresh timer instead of one that started ticking before the action even began.
83
+
84
+ Returns **({promise: [Promise][1]<([string][2] | null)>, cancel: [function][3]} | null)**&#x20;
85
+
86
+ ### _assertLayoutSupported
87
+
88
+ Throws if the current page has no real layout engine (`capabilities.layout === 'none'`),
89
+ used to guard visibility-dependent assertions that cannot be evaluated without one.
90
+
91
+ #### Parameters
92
+
93
+ * `action` **[string][2]** name of the calling assertion, used in the error message.
94
+
95
+ <!---->
96
+
97
+ * Throws **[Error][4]** if the page has no layout engine.
98
+
99
+ ### _before
100
+
101
+ Hook executed before each test. Ensures a live `CDPConnection` exists (connecting lazily on
102
+ first use, and reconnecting if a previous connection was closed), then creates a fresh
103
+ `about:blank` target and attaches to it with `Target.attachToTarget`, storing `this.targetId`
104
+ and `this.sessionId`. `Page` and `Runtime` domains are enabled on the new session, and engine
105
+ capabilities are probed here (against `about:blank`, uncontended) rather than only lazily on
106
+ the first real page — see `_probeCapabilities`.
107
+
108
+ Also resets `_navStartWaiters` and `_lastMainFrameNav`: both are scoped to a single
109
+ `sessionId`/`targetId`, which are about to change, so anything left over from the previous test
110
+ (e.g. an action-settle waiter still armed because its test threw between arming and settling)
111
+ can never legitimately resolve against the new session — better to drop it here than leave it
112
+ waiting for the rest of the run.
113
+
114
+ ### _candidates
115
+
116
+ Builds the list of `{type, value}` candidates `_run` should try, in order, for a given
117
+ locator and `kind`. A strict locator (CSS/XPath/object form) resolves to a single candidate.
118
+ A fuzzy (plain-text) locator is expanded into a strategy-specific list of XPath expressions
119
+ mirroring the click/field/checkbox matching used by other browser helpers (matching by
120
+ visible text, label, name, placeholder, ARIA attributes, etc.), falling back to treating the
121
+ raw text as a CSS selector.
122
+
123
+ A role locator (`{role, text, exact}`) resolves to a single `role`-type candidate, resolved
124
+ in-page by the client's implicit ARIA role mapping (native elements) plus explicit `role`
125
+ attributes, filtered by accessible name/text when `text` is given.
126
+
127
+ #### Parameters
128
+
129
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator, or plain fuzzy text.
130
+ * `kind` **(`"element"` | `"clickable"` | `"field"` | `"checkable"`)** matching strategy to use when `locator` is fuzzy.
131
+
132
+ ### _candidatesLabel
133
+
134
+ A short, human-readable label built from `candidates`, used in `_run`'s elementIndex/strict
135
+ error messages when no locator string is otherwise available.
136
+
137
+ #### Parameters
138
+
139
+ * `candidates` &#x20;
140
+
141
+ Returns **[string][2]**&#x20;
142
+
143
+ ### _candidatesNeedXPath
144
+
145
+ Whether any candidate strategy — in `candidates` itself, or in any of the `within` scoping
146
+ `layers` searched before it — is an `xpath` locator. Used to decide, before the client is even
147
+ installed, whether the XPath polyfill needs to be bundled into that install or can be deferred.
148
+
149
+ #### Parameters
150
+
151
+ * `candidates` **[Array][6]<{type: [string][2], value: [string][2]}>?**&#x20;
152
+ * `layers` **[Array][6]<[Array][6]<{type: [string][2], value: [string][2]}>>**&#x20;
153
+
154
+ Returns **[boolean][7]**&#x20;
155
+
156
+ ### _checkText
157
+
158
+ Shared implementation for `see`/`dontSee`. Without a `context` locator and outside any `within`
159
+ block, checks presence via `_runTextCheck`'s fast, boolean-only round trip; the full haystack is
160
+ only fetched (one extra, rare evaluate) when the assertion is about to fail, to build the same
161
+ `stringIncludes` error as before this optimization. With a `context` or inside `within`, this is
162
+ unchanged from before — already a small, per-element read, not the identified cost.
163
+
164
+ #### Parameters
165
+
166
+ * `text` **[string][2]**&#x20;
167
+ * `context` **([string][2]? | [object][5])**&#x20;
168
+ * `negate` **[boolean][7]**&#x20;
169
+
170
+ Returns **[Promise][1]<void>**&#x20;
171
+
172
+ ### _connect
173
+
174
+ Resolves the CDP endpoint and opens the underlying `CDPConnection`, storing it on `this.cdp`.
175
+
176
+ ### _ensureClient
177
+
178
+ Ensures the in-page client (`window.__codecept`, installed from `cdpBrowserClient.js`) is
179
+ present on the current page, installing it (and the XPath polyfill, if needed) exactly once.
180
+ Safe to call repeatedly; it is a no-op once the client is detected.
181
+
182
+ ### _ensureLifecycleListener
183
+
184
+ Lazily installs a single, persistent `Page.lifecycleEvent` listener on the underlying
185
+ `CDPConnection` and drains it into whichever `_waitForLoadEvent` calls are currently pending,
186
+ matched by `loaderId`. Installed once per helper instance (the connection outlives individual
187
+ tests), never removed — `CDPConnection` has no listener-removal API, so a single persistent
188
+ dispatcher (rather than one listener per navigation) is what keeps this leak-free.
189
+
190
+ Also, for the main frame (`params.frameId === this.targetId`, which holds for a page target's
191
+ own top-level frame) only:
192
+
193
+ * Drains `_navStartWaiters` (armed by `_armActionSettle`, before an action, for `_waitForAction`'s
194
+ event-aware settle) on an `'init'` event — confirmed via a raw probe (against both Obscura and
195
+ Chrome, through the actual CLI path) to be the earliest signal CDP emits when a new top-level
196
+ navigation begins. Arming happens *before* the action is dispatched, not after: the same probe
197
+ found `'init'` can arrive while the action's own CDP round trip is still in flight, sometimes
198
+ only a millisecond or two after it started — a listener installed only once the action's
199
+ promise resolves can already be too late, not merely unlucky.
200
+ * Maintains `_lastMainFrameNav`, a rolling `{loaderId, events}` record of every lifecycle event
201
+ name seen for the current main-frame navigation (reset whenever `loaderId` changes). On a
202
+ fast/local navigation, the same raw probe found the *entire* sequence — `init` through
203
+ `networkIdle` — arriving as one batch while the triggering action's own round trip was still
204
+ in flight. Without this cache, `_waitForAction` would correctly detect that a navigation
205
+ started, then arm a *fresh* wait for the `load` event specifically — which, in that common
206
+ case, had already fired and will never fire again, paying the full grace-window-plus-poll cost
207
+ of `_waitForPageLoad` on every single navigating action instead of settling immediately.
208
+
209
+ ### _evaluate
210
+
211
+ Evaluates a JavaScript expression in the page attached to the current session via
212
+ `Runtime.evaluate`, awaiting any returned promise and returning the value by reference
213
+ (`returnByValue: true`). If the expression throws, the browser-side exception description
214
+ (or fallback text) is re-thrown as a JS `Error`.
215
+
216
+ #### Parameters
217
+
218
+ * `expression` **[string][2]** a JavaScript expression (or IIFE) to run in the page context.
219
+
220
+ Returns **[Promise][1]<any>** the evaluated value, or `undefined` if the expression has no result.
221
+
222
+ ### _finishTest
223
+
224
+ Hook executed after all tests are run. Closes the underlying `CDPConnection` (and its
225
+ WebSocket) and clears `this.cdp`. Must leave no open sockets or pending timers behind, so the
226
+ process can exit on its own.
227
+
228
+ ### _grabCurrentPath
229
+
230
+ Resolves the current page URL to a `pathname`, ignoring the origin, query string, and hash.
231
+
232
+ Returns **[Promise][1]<[string][2]>** the pathname of the current page.
233
+
234
+ ### _init
235
+
236
+ No-op hook kept for interface parity with other browser helpers. Connecting to the CDP
237
+ endpoint is deferred to `_before`, since a fresh target/session is opened per test.
238
+
239
+ ### _installClient
240
+
241
+ Installs the in-page client unconditionally — no `typeof window.__codecept` presence check.
242
+ Used by callers that already know, from a sentinel value returned alongside a failed action,
243
+ that the client is missing on the current page, so re-checking would just be a redundant
244
+ contended round trip.
245
+
246
+ The 171KB XPath polyfill is only injected alongside the client when `needsXPath` is true (the
247
+ default, for callers without candidate information) *and* the engine actually needs it
248
+ (`capabilities.xpath === 'polyfill'`, cached from `_before`'s probe). Callers that know their
249
+ candidates never resolve to an `xpath` strategy (e.g. `_runSelected`, once it has inspected
250
+ `candidates`/`within`) can pass `false` to skip that inject — the client is still told, via the
251
+ `xpathNeedsPolyfill` flag baked in at install time, that the *engine* will eventually need it,
252
+ so a later call that does hit an xpath candidate gets a clean `'__NO_XPATH__'` miss signal
253
+ (from `window.__codecept.run`) instead of silently falling through to a broken native
254
+ `document.evaluate` — `_runSelected` reacts to that sentinel by injecting the polyfill and
255
+ retrying once, mirroring the `'__NO_CLIENT__'` handling right next to it.
256
+
257
+ #### Parameters
258
+
259
+ * `needsXPath` **[boolean][7]**
260
+
261
+ ### _needsVisibleTextFallback
262
+
263
+ Determines whether `see`/`dontSee`/`waitForText` should read whole-page text through the
264
+ client's own visibility-aware `visibleText()` walker instead of the native
265
+ `document.body.innerText`. Probes once per page by appending a `display:none` element and a
266
+ `<script>` element, each with distinguishing text, and checking that native `innerText`
267
+ excludes both — some engines return an `innerText` that does not honor computed visibility or
268
+ exclude script/style content, even when `getComputedStyle`/layout are otherwise reliable. The
269
+ result is cached on `capabilities.innerText` (`'native'` or `'computed'`).
270
+
271
+ Returns **[Promise][1]<[boolean][7]>** `true` if the `visibleText()` fallback should be used.
272
+
273
+ ### _needsXPathPolyfill
274
+
275
+ Determines whether the bundled XPath polyfill must be injected before the in-page client is
276
+ installed. Honors an explicit `options.xpathPolyfill` boolean; otherwise reuses a previously
277
+ probed `capabilities.xpath`, or probes the page's native `document.evaluate`. The probe appends
278
+ two throwaway elements distinguished only by text content and asserts that a text-value XPath
279
+ predicate (`normalize-space(string(.))=...`, the basis of every fuzzy/clickable locator) resolves
280
+ to exactly the matching one — merely checking that `document.evaluate` runs without throwing is
281
+ not enough, since some engines execute a text-value predicate without actually filtering by it,
282
+ silently returning every candidate node instead of none or one. The result is cached on
283
+ `capabilities.xpath` (`'native'` or `'polyfill'`).
284
+
285
+ Returns **[Promise][1]<[boolean][7]>** `true` if the polyfill should be injected.
286
+
287
+ ### _onScreencastFrame
288
+
289
+ `Page.screencastFrame` handler: ignores frames from a session other than the currently active
290
+ one (stale frames from a previous test, since the listener is never removed), acknowledges the
291
+ frame so the browser keeps sending more, and buffers `{data, timestamp}` for `stopScreencast`
292
+ to assemble.
293
+
294
+ #### Parameters
295
+
296
+ * `params` &#x20;
297
+ * `sessionId` &#x20;
298
+
299
+ ### _onTrafficLoadingFailed
300
+
301
+ `Network.loadingFailed` handler, resolving a still-pending `response` promise to `null`
302
+ (matching Puppeteer's `request.response()` for a failed request) so `grabRecordedNetworkTraffics`
303
+ never awaits a promise that would otherwise never settle.
304
+
305
+ #### Parameters
306
+
307
+ * `params` &#x20;
308
+ * `sessionId` &#x20;
309
+
310
+ ### _onTrafficRequest
311
+
312
+ `Network.requestWillBeSent` handler, pushed into `this.requests` when it belongs to the
313
+ currently active session and recording is on.
314
+
315
+ #### Parameters
316
+
317
+ * `params` &#x20;
318
+ * `sessionId` &#x20;
319
+
320
+ ### _onTrafficResponse
321
+
322
+ `Network.responseReceived` handler, resolving the matching pending `response` promise pushed
323
+ by `_onTrafficRequest` with a Puppeteer-`HTTPResponse`-like object.
324
+
325
+ #### Parameters
326
+
327
+ * `params` &#x20;
328
+ * `sessionId` &#x20;
329
+
330
+ ### _poll
331
+
332
+ Repeatedly calls `fn` until it returns a truthy value or `timeoutSec` elapses, checking
333
+ immediately and waiting `options.pollInterval` milliseconds between subsequent attempts.
334
+
335
+ #### Parameters
336
+
337
+ * `fn` **[function][3]** the condition to poll; should resolve to a truthy value once satisfied.
338
+ * `timeoutSec` **[number][8]** maximum time to poll, in seconds.
339
+ * `message` **[string][2]** error message used when the timeout is reached.
340
+ * `cancelToken` **{cancelled: [boolean][7]}??** when `cancelled` becomes `true` (set by the caller from outside), polling stops early with an error instead of continuing to `timeoutSec`. Used by `_waitForPageLoad` to tear down the losing side of a race instead of leaving it running.
341
+
342
+ <!---->
343
+
344
+ * Throws **[Error][4]** with `message` if `timeoutSec` elapses without `fn` returning a truthy value, or a cancellation error if `cancelToken.cancelled` is set first.
345
+
346
+ Returns **[Promise][1]<any>** the truthy value returned by `fn`.
347
+
348
+ ### _probeCapabilities
349
+
350
+ Probes and caches capabilities that depend on the actual browser *engine* rather than any
351
+ particular page's content: `capabilities.layout` (via `getComputedStyle`), `capabilities.screenshot`
352
+ (inferred from `layout`), `capabilities.xpath` (via `_needsXPathPolyfill`), and
353
+ `capabilities.innerText` (via `_needsVisibleTextFallback`). Already-known capabilities
354
+ (pre-seeded through `options.capabilities`, or probed earlier) are never re-probed — so, across
355
+ a whole run, this issues a handful of `_evaluate` calls exactly once and is a no-op afterward.
356
+
357
+ Called from `_before`, against the fresh `about:blank` target created there, specifically so
358
+ these probes run before any real navigation — measured directly (a full stall ledger against
359
+ `github.com`) that running them on the first *real* page instead can cost seconds each, since
360
+ every one is an `_evaluate` competing with that page's own JavaScript for the V8 isolate.
361
+ `about:blank` has no such competition. Also called (cheaply, already cached by then) from
362
+ `amOnPage`, so a helper that skips `_before` for some reason still probes correctly.
363
+
364
+ The `xpath`/`innerText` probes determine *whether* their respective fallback is needed; they
365
+ do not install anything — injection stays deferred to `_ensureClient`'s reactive install and
366
+ `_textSource`'s own read, matching `amOnPage` no longer eagerly installing the client.
367
+
368
+ ### _resolveEndpoint
369
+
370
+ Resolves `options.endpoint` to a raw WebSocket debugger URL. If the configured endpoint is
371
+ an `http(s)://` address, this fetches `/json/version` from it and reads `webSocketDebuggerUrl`
372
+ from the response, matching the discovery flow exposed by Chrome's `--remote-debugging-port`.
373
+ A `ws(s)://` endpoint is returned unchanged.
374
+
375
+ This is the subclass override point for helpers that connect through a different discovery
376
+ mechanism (e.g. a cloud browser provider with its own session-creation API).
377
+
378
+ Returns **[Promise][1]<[string][2]>** a `ws(s)://` debugger URL ready to be passed to `CDPConnection`.
379
+
380
+ ### _run
381
+
382
+ Delegates a find-and-act call to `window.__codecept.run(candidates, action, payload)`. This is
383
+ the primary extension point used by helpers built on top of this class for element queries and
384
+ interactions.
385
+
386
+ A per-call `context` locator, when given, is resolved and layered on top of any active
387
+ `within` block (searched inside it, not instead of it), so `context` narrows the search
388
+ without breaking out of a surrounding `within`.
389
+
390
+ #### Parameters
391
+
392
+ * `candidates` &#x20;
393
+ * `action` **[string][2]** name of the action to run against the matched elements (e.g. `count`, `click`, `fill`).
394
+ * `payload` **[object][5]?** extra data the action needs (e.g. `{ value }` for `fill`).
395
+ * `context` **([string][2]? | [object][5])** element to search in, narrowing the candidates below it.
396
+
397
+ Returns **[Promise][1]<{found: [number][8], result: any}>** number of matched elements and the action's result.
398
+
399
+ ### _runSelected
400
+
401
+ Same as `_run`, but takes an explicit selection descriptor instead of reading one from
402
+ `store.currentStep`/`options.strict`. Used internally by `CDPElementHandle` to address one
403
+ specific element out of a candidate set by its 1-based index.
404
+
405
+ The in-page client's presence is checked in the same round-trip as the action itself: the
406
+ evaluated expression resolves to a sentinel string when `window.__codecept` is missing (e.g.
407
+ right after a navigation the registered script didn't reach), in which case the client is
408
+ installed and the call is retried exactly once. Separately, if the client is already present
409
+ but reports (via its own `'__NO_XPATH__'` sentinel) that this call needs the XPath polyfill and
410
+ it was not bundled into that earlier install, the polyfill is injected and the call is retried
411
+ once more — see `_installClient`.
412
+
413
+ #### Parameters
414
+
415
+ * `candidates` &#x20;
416
+ * `action` **[string][2]**&#x20;
417
+ * `payload` **([object][5] | null)**&#x20;
418
+ * `selection` **([object][5] | null)** `{index}` or `{strict: true}`, mirroring `_selectionDescriptor`.
419
+ * `context` **([string][2]? | [object][5])**
420
+
421
+ Returns **[Promise][1]<{found: [number][8], result: any}>**&#x20;
422
+
423
+ ### _runTextCheck
424
+
425
+ Runs the in-page `containsText` check against the whole page (no `context`/`within` scoping —
426
+ those stay on `_textSource`'s per-element path, already small). Returns only `{found, snippet}`
427
+ instead of the full haystack: on a page with a large body, serializing that whole string across
428
+ the CDP wire (and, on engines where `capabilities.innerText` requires the `visibleText()`
429
+ walker, holding it in memory) is avoidable work `see`/`dontSee`/`waitForText` don't actually
430
+ need on their common, non-throwing path.
431
+
432
+ Also folds the client's install into the very same round trip when it is still missing, instead
433
+ of a separate presence-check evaluate followed by an install evaluate before the check itself
434
+ can even run — mirroring `_runSelected`'s sentinel-retry design, but collapsed into one evaluate
435
+ since the install source itself is known and cacheable up front. That install is client-only,
436
+ never the 171KB XPath polyfill: `containsText` never calls `document.evaluate`, so bundling it
437
+ here would be pure waste for a scenario that never resolves an xpath locator. The client is
438
+ still told, via `installCodeceptClient`'s `xpathNeedsPolyfill` flag, whether the *engine*
439
+ (`capabilities.xpath`, cached by `_before`'s `about:blank` probe) will eventually need it, so a
440
+ later xpath-resolving action on the same page gets a clean `'__NO_XPATH__'` miss signal from
441
+ `window.__codecept.run` instead of silently hitting a broken native `document.evaluate` —
442
+ `_runSelected` reacts to that sentinel already. The bootstrap source is built once and reused
443
+ for the life of the instance, since whether the engine needs the polyfill never changes.
444
+
445
+ #### Parameters
446
+
447
+ * `text` **[string][2]**&#x20;
448
+ * `opts` **{ignoreCase: [boolean][7], useWalker: [boolean][7]}**&#x20;
449
+
450
+ Returns **[Promise][1]<{found: [boolean][7], snippet: ([string][2] | null)}>**&#x20;
451
+
452
+ ### _seeInField
453
+
454
+ Shared implementation for `seeInField`/`dontSeeInField`.
455
+
456
+ #### Parameters
457
+
458
+ * `assertType` **(`"assert"` | `"negate"`)**&#x20;
459
+ * `field` **([string][2] | [object][5])**&#x20;
460
+ * `value` **([string][2] | [object][5])**&#x20;
461
+ * `context` **([string][2]? | [object][5])**
462
+
463
+ Returns **[Promise][1]<void>**&#x20;
464
+
465
+ ### _selectionDescriptor
466
+
467
+ Builds the `{index, strict}` element-selection descriptor from the current step's options
468
+ (`store.currentStep.opts`) and `options.strict`, mirroring the semantics of
469
+ `lib/helper/extras/elementSelection.js` (used by Puppeteer/WebDriver): a per-step
470
+ `elementIndex` (numeric, or the `'first'`/`'last'` aliases) always takes precedence and
471
+ disables strict mode for that step; otherwise `exact`/`strictMode` per-step options
472
+ override `options.strict` to enable or cancel strict mode.
473
+
474
+ Returns **([object][5] | null)** descriptor with optional `index` and `strict` keys, or `null` when neither applies.
475
+
476
+ ### _texts
477
+
478
+ Resolves whether the `texts` action should read via the client's `visibleText()` walker
479
+ (probed once via `_needsVisibleTextFallback` and cached on `capabilities.innerText`) instead
480
+ of each element's native `innerText`, then runs it.
481
+
482
+ #### Parameters
483
+
484
+ * `candidates` **[Array][6]<{type: [string][2], value: ([string][2] | [object][5])}>**&#x20;
485
+
486
+ Returns **[Promise][1]<{found: [number][8], result: any}>**&#x20;
487
+
488
+ ### _textSource
489
+
490
+ Resolves the text to search `see`/`dontSee`/`waitForText` against, when no explicit `context`
491
+ locator is given. An explicit `context` is always resolved through `_run`, so it is implicitly
492
+ scoped to the active `within` block, if any. Without a `context`, this reads the `within` root's
493
+ text when a `within` block is active, or the whole page's text otherwise — via native
494
+ `document.body.innerText`, or the client's `visibleText()` walker when
495
+ `_needsVisibleTextFallback` determines native `innerText` is not trustworthy.
496
+
497
+ #### Parameters
498
+
499
+ * `context` **([string][2]? | [object][5])**&#x20;
500
+
501
+ Returns **[Promise][1]<[string][2]>**&#x20;
502
+
503
+ ### _url
504
+
505
+ Resolves a path against `options.url`. Absolute URLs (matching `scheme://`) are returned
506
+ unchanged; anything else is appended to `options.url` with its trailing slash stripped.
507
+
508
+ #### Parameters
509
+
510
+ * `path` **[string][2]** an absolute URL or a path relative to `options.url`.
511
+
512
+ Returns **[string][2]** the resolved, absolute URL.
513
+
514
+ ### _waitForAction
515
+
516
+ Settles after an interaction (click, key press, etc.) before the next step runs, using the
517
+ listener `_armActionSettle` started *before* the interaction was dispatched (`armed`; a fresh
518
+ one is armed here too, as a safety net, if a call site forgot to — but arming this late can
519
+ only miss a navigation that already started during the action's own dispatch, exactly the race
520
+ this design exists to avoid, so every call site should pass its own pre-armed `armed`, not rely
521
+ on this fallback).
522
+
523
+ If `options.waitForAction` was set explicitly in the config, honors it literally as a fixed
524
+ pacing sleep, exactly as before this round — an explicit value is a deliberate choice
525
+ (slow-motion debugging, a known-slow app) this never second-guesses.
526
+
527
+ Otherwise, event-aware: races the armed listener against a *fresh* `ACTION_SETTLE_GRACE_MS`
528
+ window (started now, not when it was armed — the action's own dispatch already ran concurrently
529
+ with the arm, so this is genuinely bounded extra time, not a guess). If nothing declares a
530
+ navigation, returns immediately once the window elapses — the common case for most actions
531
+ (typing, toggling a checkbox, focusing a field) — instead of a fixed `options.waitForAction`
532
+ (100ms by default) sleep on every single action regardless of whether anything is happening.
533
+
534
+ If a navigation *did* start, `_lastMainFrameNav` (see `_ensureLifecycleListener`) is checked
535
+ first: on a fast/local page, the entire lifecycle sequence through the target event has
536
+ typically already arrived in the same batch that announced the navigation started, in which
537
+ case this returns immediately. Only a navigation still genuinely in flight falls through to
538
+ `_waitForPageLoad` (the same mechanism `amOnPage`/`refreshPage` use) — which waits for it to
539
+ actually finish, rather than a fixed sleep that has no relationship to how long the navigation
540
+ actually takes: strictly more correct for a slow navigation, not just faster for a fast one.
541
+
542
+ #### Parameters
543
+
544
+ * `armed` **({promise: [Promise][1]<([string][2] | null)>, cancel: [function][3]} | null)?** from `_armActionSettle`, called before the action.
545
+
546
+ Returns **[Promise][1]<void>**&#x20;
547
+
548
+ ### _waitForLoadEvent
549
+
550
+ Starts waiting for a `Page.lifecycleEvent` named `eventName` for the given `loaderId` on the
551
+ current session. `loaderId` (from the `Page.navigate` response) discriminates the awaited
552
+ navigation from any other in-flight or stale lifecycle events (e.g. the `about:blank` target
553
+ created in `_before`), which is essential since Chrome emits the target's initial `about:blank`
554
+ lifecycle sequence asynchronously, sometimes after this listener is already installed.
555
+
556
+ Returns a `{promise, cancel}` pair rather than a bare promise: `_waitForPageLoad` races this
557
+ against a readyState poll, and whichever side loses must be actively torn down (not just have
558
+ its rejection swallowed) — an abandoned-but-still-pending wait would sit in `_pageLoadWaiters`
559
+ for the full timeout on every single navigation, for no purpose.
560
+
561
+ #### Parameters
562
+
563
+ * `loaderId` **[string][2]** the loader id of the navigation to wait for, from `Page.navigate`'s response.
564
+ * `eventName` **[string][2]** the `Page.lifecycleEvent` name to wait for (e.g. `load`, `DOMContentLoaded`, `networkIdle`).
565
+ * `timeoutSec` **[number][8]** maximum time to wait, in seconds.
566
+
567
+ Returns **{promise: [Promise][1]<void>, cancel: [function][3]}**&#x20;
568
+
569
+ ### _waitForPageLoad
570
+
571
+ Waits for a page to finish loading after `Page.navigate`/`Page.reload`, per `options.waitForNavigation`.
572
+
573
+ Purely event-driven for the first `PAGE_LOAD_GRACE_MS`: only the push-based
574
+ `Page.lifecycleEvent` signal (matched by `loaderId`) is awaited, issuing zero `_evaluate` calls
575
+ — this matters because an `_evaluate` sent while the page's own JavaScript is still busy (e.g.
576
+ a real-world page doing post-load hydration/analytics work) can queue behind it for hundreds of
577
+ ms to multiple seconds, measured directly against a JS-heavy page. Only if the grace window
578
+ elapses without the event (an engine that doesn't emit it, or a genuinely slow navigation) does
579
+ the `document.readyState` poll (via `_poll`) start, racing the still-pending lifecycle wait —
580
+ both bounded by the same `options.getPageTimeout`, so a lifecycle-less engine costs at most
581
+ `PAGE_LOAD_GRACE_MS` more than the poll alone would have, never double the timeout. No
582
+ `loaderId` (e.g. from `Page.reload`, which returns none) skips straight to the poll.
583
+
584
+ Whichever side ultimately loses is actively cancelled, not merely abandoned — an abandoned poll
585
+ or lifecycle wait would otherwise keep running (issuing readyState `_evaluate` calls every
586
+ `pollInterval`, or holding a `_pageLoadWaiters` entry) for up to the full timeout on every
587
+ navigation, competing for the same CDP connection with real work.
588
+
589
+ #### Parameters
590
+
591
+ * `loaderId` **([string][2] | null)** loader id from the triggering `Page.navigate` response, if any.
592
+ * `timeoutMessage` **[string][2]** error message used if the readyState poll times out.
593
+
594
+ Returns **[Promise][1]<void>**&#x20;
595
+
596
+ ### _withinBegin
597
+
598
+ Starts a `within` block, scoping every subsequent `_run` call (and therefore every element
599
+ lookup performed by this helper) to the descendants of the element matched by `locator`.
600
+ Verifies the element exists (against the full document, i.e. unscoped) before narrowing.
601
+
602
+ #### Parameters
603
+
604
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
605
+
606
+ <!---->
607
+
608
+ * Throws **ElementNotFound** if no element matches `locator`.
609
+
610
+ Returns **[Promise][1]<void>**&#x20;
611
+
612
+ ### _withinEnd
613
+
614
+ Ends the current `within` block, restoring unscoped element lookups.
615
+
616
+ Returns **[Promise][1]<void>**&#x20;
617
+
618
+ ### amOnPage
619
+
620
+ Opens a web page in the current session.
621
+
622
+ ```js
623
+ I.amOnPage('/'); // opens main page of website
624
+ I.amOnPage('https://github.com'); // opens github
625
+ I.amOnPage('/login'); // opens a login page
626
+ ```
627
+
628
+ Navigates via `Page.navigate`, then waits (up to `options.getPageTimeout` seconds) for the page
629
+ to finish loading, preferring the push-based `Page.lifecycleEvent` signal (per
630
+ `options.waitForNavigation`) over polling `document.readyState`. Capabilities are (re-)probed
631
+ (a no-op after the first page, since they're cached for the helper's lifetime).
632
+
633
+ The in-page client is deliberately *not* eagerly (re-)installed here — navigation discards any
634
+ previously injected script, but installing it is deferred to the first actual action after
635
+ this call, via `_runSelected`'s sentinel-and-retry. This keeps `amOnPage` itself down to the
636
+ navigate command plus the push-based wait: no `_evaluate` call is issued on this hot path,
637
+ which matters most right when the page's own JavaScript may still be busy (measured directly:
638
+ an `_evaluate` sent in that window can queue behind it for hundreds of ms to multiple seconds
639
+ on a JS-heavy real-world page, regardless of how small the evaluated expression is).
640
+
641
+ #### Parameters
642
+
643
+ * `url` **[string][2]** url path or global url.
644
+
645
+ Returns **[Promise][1]<void>**&#x20;
646
+
647
+ ### appendField
648
+
649
+ Appends text to a input field or textarea.
650
+ Field is located by name, label, CSS or XPath
651
+
652
+ ```js
653
+ I.appendField('#myTextField', 'appended');
654
+ // typing secret
655
+ I.appendField('password', secret('123456'));
656
+ ```
657
+
658
+ #### Parameters
659
+
660
+ * `field` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator
661
+ * `value` **[string][2]** text value to append.
662
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
663
+
664
+ Returns **[Promise][1]<void>**&#x20;
665
+
666
+ ### attachFile
667
+
668
+ Attaches a file to a file input field, or drops it onto a drag-and-drop dropzone element,
669
+ resolved by label|name|CSS|XPath|strict locator. `pathToFile` is resolved relative to
670
+ `codecept_dir` (matching Puppeteer/WebDriver). Since `CDPBrowser` never brings element handles
671
+ back to Node, the resolved element is marked with a throwaway `data-codecept-upload` attribute
672
+ in-page (respecting `context`/`within`/elementIndex exactly like every other action). A real
673
+ `<input type="file">` is then addressed by that attribute through the CDP `DOM` domain, which
674
+ `CDPBrowser` otherwise never uses, to call `DOM.setFileInputFiles`; any other element (a
675
+ drag-and-drop dropzone) instead gets a synthetic `dragenter`/`dragover`/`drop` sequence with a
676
+ `DataTransfer` built from the file's contents, entirely in-page. The marker is removed again in
677
+ a `finally`.
678
+
679
+ ```js
680
+ I.attachFile('Avatar', 'data/avatar.jpg');
681
+ I.attachFile('#file', 'data/avatar.jpg');
682
+ I.attachFile('#dropzone', 'data/avatar.jpg');
683
+ ```
684
+
685
+ #### Parameters
686
+
687
+ * `field` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
688
+ * `pathToFile` **[string][2]** path to file, relative to `codecept_dir`.
689
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
690
+
691
+ Returns **[Promise][1]<void>**&#x20;
692
+
693
+ ### blur
694
+
695
+ Removes focus from a given element.
696
+
697
+ ```js
698
+ I.blur('#name');
699
+ ```
700
+
701
+ #### Parameters
702
+
703
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
704
+
705
+ Returns **[Promise][1]<void>**&#x20;
706
+
707
+ ### checkOption
708
+
709
+ Selects a checkbox or radio button.
710
+ Element is located by label or name or CSS or XPath.
711
+
712
+ ```js
713
+ I.checkOption('#agree');
714
+ I.checkOption('I Agree to Terms and Conditions');
715
+ I.checkOption('agree', '//form');
716
+ ```
717
+
718
+ #### Parameters
719
+
720
+ * `field` **([string][2] | [object][5])** checkbox located by label | name | CSS | XPath | strict locator.
721
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element located by CSS | XPath | strict locator.
722
+
723
+ Returns **[Promise][1]<void>**&#x20;
724
+
725
+ ### clearCookie
726
+
727
+ Clears a cookie by name,
728
+ if none provided clears all cookies.
729
+
730
+ ```js
731
+ I.clearCookie();
732
+ I.clearCookie('test');
733
+ ```
734
+
735
+ #### Parameters
736
+
737
+ * `name` **([string][2] | null)** (optional, `null` by default) cookie name
738
+
739
+ Returns **[Promise][1]<void>**&#x20;
740
+
741
+ ### clearField
742
+
743
+ Clears a `<textarea>` or text `<input>` element's value.
744
+
745
+ ```js
746
+ I.clearField('Email');
747
+ I.clearField('user[email]');
748
+ I.clearField('#email');
749
+ ```
750
+
751
+ #### Parameters
752
+
753
+ * `field` **([string][2] | [object][5])** editable field located by label|name|CSS|XPath|strict locator.
754
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
755
+
756
+ Returns **[Promise][1]<void>**&#x20;
757
+
758
+ ### click
759
+
760
+ Perform a click on a link or a button, given by a locator.
761
+ If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
762
+ For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
763
+ For images, the "alt" attribute and inner text of any parent links are searched.
764
+
765
+ When `options.input` is `'cdp'`, the click is dispatched as real `Input.dispatchMouseEvent` mouse events
766
+ (`mouseMoved` / `mousePressed` / `mouseReleased`) at the center of the element's bounding box, so it
767
+ exercises the same input pipeline a real user would. Otherwise it delegates to `forceClick`. A matched
768
+ element with a zero-size bounding box (e.g. `display: none`) has no valid coordinate to click and throws;
769
+ use `forceClick` to dispatch a synthetic click on such elements instead.
770
+
771
+ ```js
772
+ // simple link
773
+ I.click('Logout');
774
+ // button of form
775
+ I.click('Submit');
776
+ // CSS button
777
+ I.click('#form input[type=submit]');
778
+ // XPath
779
+ I.click('//form/*[@type=submit]');
780
+ // using strict locator
781
+ I.click({css: 'nav a.login'});
782
+ ```
783
+
784
+ #### Parameters
785
+
786
+ * `locator` **([string][2] | [object][5])** clickable link or button located by text, or any element located by CSS|XPath|strict locator.
787
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
788
+
789
+ <!---->
790
+
791
+ * Throws **[Error][4]** if the matched element has a zero-size bounding box.
792
+
793
+ Returns **[Promise][1]<void>**&#x20;
794
+
795
+ ### clickXY
796
+
797
+ Clicks at global page coordinates, or at coordinates relative to an element.
798
+ Dispatches a real CDP mouse click and therefore requires a real layout engine.
799
+
800
+ ```js
801
+ I.clickXY(100, 200); // global coordinates
802
+ I.clickXY('#area', 50, 30); // relative to #area
803
+ ```
804
+
805
+ #### Parameters
806
+
807
+ * `locator` **([string][2] | [object][5] | [number][8])** element to click relative to, or a global X coordinate.
808
+ * `x` **[number][8]?** X coordinate relative to element, or global Y coordinate if `locator` is a number.
809
+ * `y` **[number][8]?** Y coordinate relative to element.
810
+
811
+ Returns **[Promise][1]<void>**&#x20;
812
+
813
+ ### dontSee
814
+
815
+ Opposite to `see`. Checks that a text is not present on a page.
816
+ Use context parameter to narrow down the search.
817
+
818
+ ```js
819
+ I.dontSee('Login'); // assume we are already logged in.
820
+ I.dontSee('Login', '.nav'); // no login inside .nav element
821
+ ```
822
+
823
+ #### Parameters
824
+
825
+ * `text` **[string][2]** which is not present.
826
+ * `context` **([string][2]? | [object][5])** (optional) element located by CSS|XPath|strict locator in which to perform search.
827
+
828
+ Returns **[Promise][1]<void>**&#x20;
829
+
830
+ ### dontSeeCheckboxIsChecked
831
+
832
+ Verifies that the specified checkbox is not checked.
833
+
834
+ ```js
835
+ I.dontSeeCheckboxIsChecked('#agree'); // located by ID
836
+ I.dontSeeCheckboxIsChecked('I agree to terms'); // located by label
837
+ ```
838
+
839
+ #### Parameters
840
+
841
+ * `locator` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
842
+
843
+ Returns **[Promise][1]<void>**&#x20;
844
+
845
+ ### dontSeeCookie
846
+
847
+ Checks that a cookie with the given name is not set.
848
+
849
+ #### Parameters
850
+
851
+ * `name` **[string][2]** cookie name.
852
+
853
+ Returns **[Promise][1]<void>**&#x20;
854
+
855
+ ### dontSeeCurrentPathEquals
856
+
857
+ Opposite to `seeCurrentPathEquals`.
858
+
859
+ #### Parameters
860
+
861
+ * `path` **[string][2]** value to check.
862
+
863
+ Returns **[Promise][1]<void>**&#x20;
864
+
865
+ ### dontSeeCurrentUrlEquals
866
+
867
+ Checks that current url is not equal to provided one.
868
+ Unlike `dontSeeInCurrentUrl` performs a strict comparison.
869
+
870
+ #### Parameters
871
+
872
+ * `url` **[string][2]** value to check.
873
+
874
+ Returns **[Promise][1]<void>**&#x20;
875
+
876
+ ### dontSeeElement
877
+
878
+ Opposite to `seeElement`. Checks that element is not visible.
879
+
880
+ ```js
881
+ I.dontSeeElement('.modal'); // modal is not shown
882
+ ```
883
+
884
+ #### Parameters
885
+
886
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
887
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
888
+
889
+ Returns **[Promise][1]<void>**&#x20;
890
+
891
+ ### dontSeeElementInDOM
892
+
893
+ Opposite to `seeElementInDOM`. Checks that element is not on page.
894
+
895
+ ```js
896
+ I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
897
+ ```
898
+
899
+ #### Parameters
900
+
901
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
902
+
903
+ Returns **[Promise][1]<void>**&#x20;
904
+
905
+ ### dontSeeInCurrentUrl
906
+
907
+ Checks that current url does not contain a provided fragment.
908
+
909
+ #### Parameters
910
+
911
+ * `url` **[string][2]** value to check.
912
+
913
+ Returns **[Promise][1]<void>**&#x20;
914
+
915
+ ### dontSeeInField
916
+
917
+ Opposite to `seeInField`.
918
+
919
+ #### Parameters
920
+
921
+ * `field` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
922
+ * `value` **([string][2] | [object][5])** value to check.
923
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
924
+
925
+ Returns **[Promise][1]<void>**&#x20;
926
+
927
+ ### dontSeeInSource
928
+
929
+ Checks that the current page does not contain the given string in its raw source code.
930
+
931
+ #### Parameters
932
+
933
+ * `text` **[string][2]** value to check.
934
+
935
+ Returns **[Promise][1]<void>**&#x20;
936
+
937
+ ### dontSeeInTitle
938
+
939
+ Checks that title does not contain text.
940
+
941
+ #### Parameters
942
+
943
+ * `text` **[string][2]** value to check.
944
+
945
+ Returns **[Promise][1]<void>**&#x20;
946
+
947
+ ### dontSeeTraffic
948
+
949
+ Verifies that a certain request is not part of network traffic.
950
+
951
+ Examples:
952
+
953
+ ```js
954
+ I.dontSeeTraffic({ name: 'Unexpected API Call', url: 'https://api.example.com' });
955
+ I.dontSeeTraffic({ name: 'Unexpected API Call of "user" endpoint', url: /api.example.com.*user/ });
956
+ ```
957
+
958
+ #### Parameters
959
+
960
+ * `opts` **[Object][5]** options when checking the traffic network.
961
+
962
+ * `opts.name` **[string][2]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
963
+ * `opts.url` **([string][2] | [RegExp][9])** Expected URL of request in network traffic. Can be a string or a regular expression.
964
+
965
+ Returns **void** automatically synchronized promise through #recorder
966
+
967
+ ### doubleClick
968
+
969
+ Performs a double-click on an element matched by locator.
970
+
971
+ ```js
972
+ I.doubleClick('Edit');
973
+ ```
974
+
975
+ #### Parameters
976
+
977
+ * `locator` **([string][2] | [object][5])** clickable element located by text, or any element located by CSS|XPath|strict locator.
978
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default, currently ignored by this helper).
979
+
980
+ Returns **[Promise][1]<void>**&#x20;
981
+
982
+ ### executeAsyncScript
983
+
984
+ Executes an asynchronous script (callback-style, in the same way `window.setTimeout` works)
985
+ in the browser context and returns the value passed to `done`.
986
+
987
+ ```js
988
+ const val = await I.executeAsyncScript(function(val, done) {
989
+ setTimeout(() => done(val + 1), 100)
990
+ }, 5)
991
+ ```
992
+
993
+ #### Parameters
994
+
995
+ * `fn` **[function][3]** an asynchronous function to be executed in the browser context; its last argument is a `done` callback.
996
+ * `args` **...any** arguments to pass into the function (before `done`).
997
+
998
+ Returns **[Promise][1]<any>** the value passed to `done`.
999
+
1000
+ ### executeScript
1001
+
1002
+ Executes a JavaScript function in the browser context and returns its result.
1003
+
1004
+ If a function is passed, it is serialized with `Function.prototype.toString()`, so it must
1005
+ not reference variables from the outer (Node.js) scope — pass any needed data as arguments
1006
+ instead. A string is evaluated as-is.
1007
+
1008
+ ```js
1009
+ let title = await I.executeScript(() => document.title);
1010
+ let sum = await I.executeScript((a, b) => a + b, 2, 3);
1011
+ ```
1012
+
1013
+ If the function returns a promise, `executeScript` waits for it to resolve.
1014
+
1015
+ #### Parameters
1016
+
1017
+ * `fn` **([string][2] | [function][3])** a JavaScript function to be executed in the browser context, or a string expression.
1018
+ * `args` **...any** arguments to pass into the function.
1019
+
1020
+ Returns **[Promise][1]<any>** the value returned (or resolved) by the function.
1021
+
1022
+ ### fillField
1023
+
1024
+ Fills a text field or textarea, after clearing its value, with the given string.
1025
+ Field is located by name, label, CSS, or XPath.
1026
+
1027
+ ```js
1028
+ // by label
1029
+ I.fillField('Email', 'hello@world.com');
1030
+ // by name
1031
+ I.fillField('password', secret('123456'));
1032
+ // by CSS
1033
+ I.fillField('form#login input[name=username]', 'John');
1034
+ // or by strict locator
1035
+ I.fillField({css: 'form#login input[name=username]'}, 'John');
1036
+ ```
1037
+
1038
+ #### Parameters
1039
+
1040
+ * `field` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
1041
+ * `value` **([string][2] | [object][5])** text value to fill.
1042
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1043
+
1044
+ Returns **[Promise][1]<void>**&#x20;
1045
+
1046
+ ### flushNetworkTraffics
1047
+
1048
+ Resets all recorded network requests.
1049
+
1050
+ ```js
1051
+ I.flushNetworkTraffics();
1052
+ ```
1053
+
1054
+ ### focus
1055
+
1056
+ Focuses a given element.
1057
+
1058
+ ```js
1059
+ I.focus('#name');
1060
+ ```
1061
+
1062
+ #### Parameters
1063
+
1064
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1065
+
1066
+ Returns **[Promise][1]<void>**&#x20;
1067
+
1068
+ ### forceClick
1069
+
1070
+ Perform an emulated click on a link or a button, given by a locator.
1071
+ Unlike `click`, this always dispatches a synthetic in-page `el.click()` instead of sending native
1072
+ CDP input events. This works on hidden, animated or inactive elements as well.
1073
+
1074
+ If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
1075
+ For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
1076
+ For images, the "alt" attribute and inner text of any parent links are searched.
1077
+
1078
+ ```js
1079
+ // simple link
1080
+ I.forceClick('Logout');
1081
+ // button of form
1082
+ I.forceClick('Submit');
1083
+ // CSS button
1084
+ I.forceClick('#form input[type=submit]');
1085
+ // XPath
1086
+ I.forceClick('//form/*[@type=submit]');
1087
+ // using strict locator
1088
+ I.forceClick({css: 'nav a.login'});
1089
+ ```
1090
+
1091
+ #### Parameters
1092
+
1093
+ * `locator` **([string][2] | [object][5])** clickable link or button located by text, or any element located by CSS|XPath|strict locator.
1094
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1095
+
1096
+ Returns **[Promise][1]<void>**&#x20;
1097
+
1098
+ ### grabAttributeFrom
1099
+
1100
+ Retrieves an attribute from an element located by CSS or XPath and returns it to test.
1101
+ Resumes test execution, so **should be used inside async with `await`** operator.
1102
+ If more than one element is found - attribute of first element is returned.
1103
+
1104
+ ```js
1105
+ let hint = await I.grabAttributeFrom('#tooltip', 'title');
1106
+ ```
1107
+
1108
+ #### Parameters
1109
+
1110
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1111
+ * `attr` **[string][2]** attribute name.
1112
+
1113
+ Returns **[Promise][1]<[string][2]>** attribute value
1114
+
1115
+ ### grabAttributeFromAll
1116
+
1117
+ Retrieves an array of attributes from elements located by CSS or XPath and returns it to test.
1118
+ Resumes test execution, so **should be used inside async with `await`** operator.
1119
+
1120
+ ```js
1121
+ let hints = await I.grabAttributeFromAll('.tooltip', 'title');
1122
+ ```
1123
+
1124
+ #### Parameters
1125
+
1126
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1127
+ * `attr` **[string][2]** attribute name.
1128
+
1129
+ Returns **[Promise][1]<[Array][6]<[string][2]>>** array of attribute values
1130
+
1131
+ ### grabCookie
1132
+
1133
+ Gets a cookie object by name.
1134
+ If none provided gets all cookies.
1135
+ Resumes test execution, so **should be used inside async function with `await`** operator.
1136
+
1137
+ ```js
1138
+ let cookie = await I.grabCookie('auth');
1139
+ assert(cookie.value, '123456');
1140
+ ```
1141
+
1142
+ #### Parameters
1143
+
1144
+ * `name` **([string][2] | null)** cookie name.
1145
+
1146
+ Returns **[Promise][1]<(CodeceptJS.Cookie | [Array][6]<CodeceptJS.Cookie>)>** a cookie object, or an array of all cookies when `name` is not provided.
1147
+
1148
+ ### grabCookies
1149
+
1150
+ Retrieves all cookies visible to the current page.
1151
+ Resumes test execution, so **should be used inside async function with `await`** operator.
1152
+
1153
+ ```js
1154
+ let cookies = await I.grabCookies();
1155
+ ```
1156
+
1157
+ Returns **[Promise][1]<[Array][6]<CodeceptJS.Cookie>>** array of cookie objects.
1158
+
1159
+ ### grabCssPropertyFrom
1160
+
1161
+ Retrieves a CSS property from an element located by CSS or XPath.
1162
+ If more than one element is found - value of first element is returned.
1163
+
1164
+ ```js
1165
+ const value = await I.grabCssPropertyFrom('h3', 'font-weight');
1166
+ ```
1167
+
1168
+ #### Parameters
1169
+
1170
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1171
+ * `cssProperty` **[string][2]** CSS property name.
1172
+
1173
+ Returns **[Promise][1]<[string][2]>** CSS value
1174
+
1175
+ ### grabCssPropertyFromAll
1176
+
1177
+ Retrieves an array of CSS properties from elements located by CSS or XPath.
1178
+
1179
+ ```js
1180
+ const values = await I.grabCssPropertyFromAll('h3', 'font-weight');
1181
+ ```
1182
+
1183
+ #### Parameters
1184
+
1185
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1186
+ * `cssProperty` **[string][2]** CSS property name.
1187
+
1188
+ Returns **[Promise][1]<[Array][6]<[string][2]>>** array of CSS values
1189
+
1190
+ ### grabCurrentUrl
1191
+
1192
+ Retrieves the page URL of the current page.
1193
+
1194
+ ```js
1195
+ let url = await I.grabCurrentUrl();
1196
+ console.log(`Current URL is [${url}]`);
1197
+ ```
1198
+
1199
+ Returns **[Promise][1]<[string][2]>** current URL.
1200
+
1201
+ ### grabHTMLFrom
1202
+
1203
+ Retrieves the inner HTML from an element located by CSS or XPath.
1204
+ If more than one element is found - HTML of first element is returned.
1205
+
1206
+ ```js
1207
+ let postHTML = await I.grabHTMLFrom('#post');
1208
+ ```
1209
+
1210
+ #### Parameters
1211
+
1212
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1213
+
1214
+ Returns **[Promise][1]<[string][2]>** HTML code for an element
1215
+
1216
+ ### grabHTMLFromAll
1217
+
1218
+ Retrieves the inner HTML from elements located by CSS or XPath.
1219
+
1220
+ ```js
1221
+ let postHTMLs = await I.grabHTMLFromAll('.post');
1222
+ ```
1223
+
1224
+ #### Parameters
1225
+
1226
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1227
+
1228
+ Returns **[Promise][1]<[Array][6]<[string][2]>>** HTML code for matched elements
1229
+
1230
+ ### grabNumberOfElements
1231
+
1232
+ Grab number of elements by locator.
1233
+ Resumes test execution, so **should be used inside async function with `await`** operator.
1234
+
1235
+ ```js
1236
+ let numOfElements = await I.grabNumberOfElements('p');
1237
+ ```
1238
+
1239
+ #### Parameters
1240
+
1241
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
1242
+
1243
+ Returns **[Promise][1]<[number][8]>** number of matched elements.
1244
+
1245
+ ### grabNumberOfVisibleElements
1246
+
1247
+ Grab number of visible elements by locator.
1248
+
1249
+ ```js
1250
+ let numOfVisibleElements = await I.grabNumberOfVisibleElements('p');
1251
+ ```
1252
+
1253
+ #### Parameters
1254
+
1255
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
1256
+
1257
+ Returns **[Promise][1]<[number][8]>** number of visible matched elements.
1258
+
1259
+ ### grabPageScrollPosition
1260
+
1261
+ Retrieves the current page scroll position.
1262
+
1263
+ ```js
1264
+ let { x, y } = await I.grabPageScrollPosition();
1265
+ ```
1266
+
1267
+ Returns **[Promise][1]<{x: [number][8], y: [number][8]}>** scroll position.
1268
+
1269
+ ### grabRecordedNetworkTraffics
1270
+
1271
+ Grab the recording network traffics
1272
+
1273
+ ```js
1274
+ const traffics = await I.grabRecordedNetworkTraffics();
1275
+ expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1');
1276
+ expect(traffics[0].response.status).to.equal(200);
1277
+ expect(traffics[0].response.body).to.contain({ name: 'this was mocked' });
1278
+ ```
1279
+
1280
+ Returns **[Array][6]** recorded network traffics
1281
+
1282
+ ### grabSource
1283
+
1284
+ Retrieves the source code of the current page.
1285
+
1286
+ ```js
1287
+ let pageSource = await I.grabSource();
1288
+ ```
1289
+
1290
+ Returns **[Promise][1]<[string][2]>** source code of the current page (the outer HTML of `<html>`).
1291
+
1292
+ ### grabTextFrom
1293
+
1294
+ Retrieves a text from an element located by CSS or XPath and returns it to test.
1295
+ Resumes test execution, so **should be used inside async with `await`** operator.
1296
+
1297
+ ```js
1298
+ let pin = await I.grabTextFrom('#pin');
1299
+ ```
1300
+
1301
+ If multiple elements found returns first element.
1302
+
1303
+ #### Parameters
1304
+
1305
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1306
+
1307
+ Returns **[Promise][1]<[string][2]>** text value
1308
+
1309
+ ### grabTextFromAll
1310
+
1311
+ Retrieves all texts from elements located by CSS or XPath and returns it to test.
1312
+ Resumes test execution, so **should be used inside async with `await`** operator.
1313
+
1314
+ ```js
1315
+ let pins = await I.grabTextFromAll('#pin li');
1316
+ ```
1317
+
1318
+ #### Parameters
1319
+
1320
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1321
+
1322
+ Returns **[Promise][1]<[Array][6]<[string][2]>>** array of text values
1323
+
1324
+ ### grabTitle
1325
+
1326
+ Retrieves a page title.
1327
+
1328
+ ```js
1329
+ let title = await I.grabTitle();
1330
+ ```
1331
+
1332
+ Returns **[Promise][1]<[string][2]>** title of the page.
1333
+
1334
+ ### grabValueFrom
1335
+
1336
+ Retrieves a value from a form element located by CSS or XPath and returns it to test.
1337
+ Resumes test execution, so **should be used inside async function with `await`** operator.
1338
+ If more than one element is found - value of first element is returned.
1339
+
1340
+ ```js
1341
+ let email = await I.grabValueFrom('input[name=email]');
1342
+ ```
1343
+
1344
+ #### Parameters
1345
+
1346
+ * `locator` **([string][2] | [object][5])** field located by label|name|CSS|XPath|strict locator.
1347
+
1348
+ Returns **[Promise][1]<[string][2]>** attribute value
1349
+
1350
+ ### grabValueFromAll
1351
+
1352
+ Retrieves an array of values from fields located by CSS or XPath and returns it to test.
1353
+ Resumes test execution, so **should be used inside async function with `await`** operator.
1354
+
1355
+ ```js
1356
+ let inputs = await I.grabValueFromAll('//form/input');
1357
+ ```
1358
+
1359
+ #### Parameters
1360
+
1361
+ * `locator` **([string][2] | [object][5])** field located by label|name|CSS|XPath|strict locator.
1362
+
1363
+ Returns **[Promise][1]<[Array][6]<[string][2]>>** array of attribute values
1364
+
1365
+ ### grabWebElement
1366
+
1367
+ Retrieves the first `WebElement` matching a locator.
1368
+
1369
+ ```js
1370
+ const button = await I.grabWebElement({ role: 'button', text: 'Submit' });
1371
+ ```
1372
+
1373
+ #### Parameters
1374
+
1375
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1376
+
1377
+ <!---->
1378
+
1379
+ * Throws **ElementNotFound** if no element matches `locator`.
1380
+
1381
+ Returns **[Promise][1]<[object][5]>** a WebElement instance.
1382
+
1383
+ ### grabWebElements
1384
+
1385
+ Retrieves an array of `WebElement`s matching a locator (`lib/element/WebElement.js`,
1386
+ wrapping a `CDPElementHandle`). Element handles are re-resolved on demand by re-running
1387
+ `candidates` and picking the matching index, since `CDPBrowser` never keeps a persistent
1388
+ handle to a DOM node on the Node side.
1389
+
1390
+ ```js
1391
+ const buttons = await I.grabWebElements({ role: 'button' });
1392
+ ```
1393
+
1394
+ #### Parameters
1395
+
1396
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1397
+
1398
+ Returns **[Promise][1]<[Array][6]<[object][5]>>** array of WebElement instances.
1399
+
1400
+ ### pressKey
1401
+
1402
+ Presses a key or key combination on the currently focused element.
1403
+ Under `options.strict`, a modifier+editing-key combination (e.g. `Ctrl+A`) dispatched with no
1404
+ element focused throws `NonFocusedType`, mirroring `focusCheck.js`'s behavior on other helpers.
1405
+
1406
+ ```js
1407
+ I.pressKey('Enter');
1408
+ I.pressKey(['Control', 'a']);
1409
+ ```
1410
+
1411
+ #### Parameters
1412
+
1413
+ * `key` **([string][2] | [Array][6]<[string][2]>)** a key or an array of keys to combine (modifiers first).
1414
+
1415
+ Returns **[Promise][1]<void>**&#x20;
1416
+
1417
+ ### refreshPage
1418
+
1419
+ Reloads the current page.
1420
+
1421
+ ```js
1422
+ I.refreshPage();
1423
+ ```
1424
+
1425
+ Triggers `Page.reload` and waits (up to `options.getPageTimeout` seconds) for
1426
+ `document.readyState` to reach `'complete'`.
1427
+
1428
+ Returns **[Promise][1]<void>**&#x20;
1429
+
1430
+ ### resizeWindow
1431
+
1432
+ Resizes the browser viewport.
1433
+
1434
+ ```js
1435
+ I.resizeWindow(1024, 768);
1436
+ ```
1437
+
1438
+ #### Parameters
1439
+
1440
+ * `width` **([number][8] | `"maximize"`)** window width, or `'maximize'`.
1441
+ * `height` **[number][8]?** window height.
1442
+
1443
+ Returns **[Promise][1]<void>**&#x20;
1444
+
1445
+ ### rightClick
1446
+
1447
+ Performs a right-click on an element matched by locator.
1448
+
1449
+ ```js
1450
+ I.rightClick('Menu');
1451
+ ```
1452
+
1453
+ #### Parameters
1454
+
1455
+ * `locator` **([string][2] | [object][5])** clickable element located by text, or any element located by CSS|XPath|strict locator.
1456
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default, currently ignored by this helper).
1457
+
1458
+ Returns **[Promise][1]<void>**&#x20;
1459
+
1460
+ ### saveElementScreenshot
1461
+
1462
+ Saves a screenshot of a single element to the output folder.
1463
+
1464
+ ```js
1465
+ I.saveElementScreenshot('#logo', 'logo.png');
1466
+ ```
1467
+
1468
+ #### Parameters
1469
+
1470
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1471
+ * `fileName` **[string][2]** file name to save.
1472
+
1473
+ Returns **[Promise][1]<void>**&#x20;
1474
+
1475
+ ### saveScreenshot
1476
+
1477
+ Saves a screenshot to the output folder (set in codecept.conf.ts or codecept.conf.js).
1478
+ Filename is relative to the output folder.
1479
+
1480
+ ```js
1481
+ I.saveScreenshot('debug.png');
1482
+ ```
1483
+
1484
+ #### Parameters
1485
+
1486
+ * `fileName` **[string][2]** file name to save.
1487
+
1488
+ Returns **[Promise][1]<void>**&#x20;
1489
+
1490
+ ### scrollPageToBottom
1491
+
1492
+ Scrolls to the bottom of the page.
1493
+
1494
+ ```js
1495
+ I.scrollPageToBottom();
1496
+ ```
1497
+
1498
+ Returns **[Promise][1]<void>**&#x20;
1499
+
1500
+ ### scrollPageToTop
1501
+
1502
+ Scrolls to the top of the page.
1503
+
1504
+ ```js
1505
+ I.scrollPageToTop();
1506
+ ```
1507
+
1508
+ Returns **[Promise][1]<void>**&#x20;
1509
+
1510
+ ### scrollTo
1511
+
1512
+ Scrolls to the element matched by locator, or to given coordinates.
1513
+
1514
+ ```js
1515
+ I.scrollTo('#submit');
1516
+ I.scrollTo(100, 200);
1517
+ ```
1518
+
1519
+ #### Parameters
1520
+
1521
+ * `locator` **([string][2] | [object][5] | [number][8])** element to scroll to, or an X coordinate if no element.
1522
+ * `offsetX` **[number][8]** X offset, or Y coordinate if `locator` is a number.
1523
+ * `offsetY` **[number][8]** Y offset applied when scrolling to an element.
1524
+
1525
+ Returns **[Promise][1]<void>**&#x20;
1526
+
1527
+ ### see
1528
+
1529
+ Checks that a page contains a visible text.
1530
+ Use context parameter to narrow down the search.
1531
+
1532
+ ```js
1533
+ I.see('Welcome'); // text welcome on a page
1534
+ I.see('Welcome', '.content'); // text inside .content div
1535
+ I.see('Register', {css: 'form.register'}); // use strict locator
1536
+ ```
1537
+
1538
+ #### Parameters
1539
+
1540
+ * `text` **[string][2]** expected on page.
1541
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
1542
+
1543
+ Returns **[Promise][1]<void>**&#x20;
1544
+
1545
+ ### seeAttributesOnElements
1546
+
1547
+ Checks that all elements matched by locator have the given attribute values.
1548
+ An expected value is matched either as an exact match or as a regular expression against the actual value.
1549
+
1550
+ ```js
1551
+ I.seeAttributesOnElements('//form', { method: 'post' });
1552
+ ```
1553
+
1554
+ #### Parameters
1555
+
1556
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1557
+ * `attributes` **[object][5]** object with attribute names and expected values.
1558
+
1559
+ Returns **[Promise][1]<void>**&#x20;
1560
+
1561
+ ### seeCheckboxIsChecked
1562
+
1563
+ Verifies that the specified checkbox is checked.
1564
+
1565
+ ```js
1566
+ I.seeCheckboxIsChecked('Agree');
1567
+ I.seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms
1568
+ I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
1569
+ ```
1570
+
1571
+ #### Parameters
1572
+
1573
+ * `locator` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
1574
+
1575
+ Returns **[Promise][1]<void>**&#x20;
1576
+
1577
+ ### seeCookie
1578
+
1579
+ Checks that a cookie with the given name is set.
1580
+
1581
+ #### Parameters
1582
+
1583
+ * `name` **[string][2]** cookie name.
1584
+
1585
+ Returns **[Promise][1]<void>**&#x20;
1586
+
1587
+ ### seeCssPropertiesOnElements
1588
+
1589
+ Checks that all elements matched by locator have the given CSS properties.
1590
+
1591
+ ```js
1592
+ I.seeCssPropertiesOnElements('h3', { 'font-weight': 'bold', display: 'block' });
1593
+ ```
1594
+
1595
+ #### Parameters
1596
+
1597
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1598
+ * `cssProperties` **[object][5]** object with CSS properties and their values to check.
1599
+
1600
+ Returns **[Promise][1]<void>**&#x20;
1601
+
1602
+ ### seeCurrentPathEquals
1603
+
1604
+ Checks that current url path (ignoring query string and hash) equals to provided one.
1605
+
1606
+ ```js
1607
+ I.seeCurrentPathEquals('/info');
1608
+ ```
1609
+
1610
+ #### Parameters
1611
+
1612
+ * `path` **[string][2]** value to check.
1613
+
1614
+ Returns **[Promise][1]<void>**&#x20;
1615
+
1616
+ ### seeCurrentUrlEquals
1617
+
1618
+ Checks that current url is equal to provided one.
1619
+ Unlike `seeInCurrentUrl` performs a strict comparison.
1620
+
1621
+ ```js
1622
+ I.seeCurrentUrlEquals('/register');
1623
+ ```
1624
+
1625
+ #### Parameters
1626
+
1627
+ * `url` **[string][2]** value to check.
1628
+
1629
+ Returns **[Promise][1]<void>**&#x20;
1630
+
1631
+ ### seeElement
1632
+
1633
+ Checks that a given Element is visible.
1634
+ Element is located by CSS or XPath.
1635
+
1636
+ ```js
1637
+ I.seeElement('#modal');
1638
+ ```
1639
+
1640
+ #### Parameters
1641
+
1642
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
1643
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1644
+
1645
+ Returns **[Promise][1]<void>**&#x20;
1646
+
1647
+ ### seeElementInDOM
1648
+
1649
+ Checks that a given Element is present in the DOM.
1650
+ Element is located by CSS or XPath.
1651
+
1652
+ ```js
1653
+ I.seeElementInDOM('#modal');
1654
+ ```
1655
+
1656
+ #### Parameters
1657
+
1658
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1659
+
1660
+ Returns **[Promise][1]<void>**&#x20;
1661
+
1662
+ ### seeInCurrentUrl
1663
+
1664
+ Checks that current url contains a provided fragment.
1665
+
1666
+ ```js
1667
+ I.seeInCurrentUrl('/register'); // we are on registration page
1668
+ ```
1669
+
1670
+ #### Parameters
1671
+
1672
+ * `url` **[string][2]** a fragment to check
1673
+
1674
+ Returns **[Promise][1]<void>**&#x20;
1675
+
1676
+ ### seeInField
1677
+
1678
+ Checks that the given input field or textarea equals (contains) the given value.
1679
+ For fuzzy locators, the field is searched by label|name|CSS|XPath|strict locator.
1680
+
1681
+ ```js
1682
+ I.seeInField('Username', 'davert');
1683
+ ```
1684
+
1685
+ #### Parameters
1686
+
1687
+ * `field` **([string][2] | [object][5])** located by label|name|CSS|XPath|strict locator.
1688
+ * `value` **([string][2] | [object][5])** value to check.
1689
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1690
+
1691
+ Returns **[Promise][1]<void>**&#x20;
1692
+
1693
+ ### seeInSource
1694
+
1695
+ Checks that the current page contains the given string in its raw source code.
1696
+
1697
+ ```js
1698
+ I.seeInSource('<h1>Green eggs &amp; ham</h1>');
1699
+ ```
1700
+
1701
+ #### Parameters
1702
+
1703
+ * `text` **[string][2]** value to check.
1704
+
1705
+ Returns **[Promise][1]<void>**&#x20;
1706
+
1707
+ ### seeInTitle
1708
+
1709
+ Checks that title contains text.
1710
+
1711
+ ```js
1712
+ I.seeInTitle('Home Page');
1713
+ ```
1714
+
1715
+ #### Parameters
1716
+
1717
+ * `text` **[string][2]** text value to check.
1718
+
1719
+ Returns **[Promise][1]<void>**&#x20;
1720
+
1721
+ ### seeNumberOfVisibleElements
1722
+
1723
+ Asserts that an element appears a given number of times on the page, and that all matching elements are visible.
1724
+
1725
+ ```js
1726
+ I.seeNumberOfVisibleElements('.buttons', 3);
1727
+ ```
1728
+
1729
+ #### Parameters
1730
+
1731
+ * `locator` **([string][2] | [object][5])** located by CSS|XPath|strict locator.
1732
+ * `num` **[number][8]** expected number of elements.
1733
+
1734
+ Returns **[Promise][1]<void>**&#x20;
1735
+
1736
+ ### seeTraffic
1737
+
1738
+ Verifies that a certain request is part of network traffic.
1739
+
1740
+ ```js
1741
+ // checking the request url contains certain query strings
1742
+ I.amOnPage('https://openai.com/blog/chatgpt');
1743
+ I.startRecordingTraffic();
1744
+ await I.seeTraffic({
1745
+ name: 'sentry event',
1746
+ url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600',
1747
+ parameters: {
1748
+ width: '1919',
1749
+ height: '1138',
1750
+ },
1751
+ });
1752
+ ```
1753
+
1754
+ ```js
1755
+ // checking the request url contains certain post data
1756
+ I.amOnPage('https://openai.com/blog/chatgpt');
1757
+ I.startRecordingTraffic();
1758
+ await I.seeTraffic({
1759
+ name: 'event',
1760
+ url: 'https://cloudflareinsights.com/cdn-cgi/rum',
1761
+ requestPostData: {
1762
+ st: 2,
1763
+ },
1764
+ });
1765
+ ```
1766
+
1767
+ #### Parameters
1768
+
1769
+ * `opts` **[Object][5]** options when checking the traffic network.
1770
+
1771
+ * `opts.name` **[string][2]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
1772
+ * `opts.url` **[string][2]** Expected URL of request in network traffic
1773
+ * `opts.parameters` **[Object][5]?** Expected parameters of that request in network traffic
1774
+ * `opts.requestPostData` **[Object][5]?** Expected that request contains post data in network traffic
1775
+ * `opts.timeout` **[number][8]?** Timeout to wait for request in seconds. Default is 10 seconds.
1776
+
1777
+ Returns **void** automatically synchronized promise through #recorder
1778
+
1779
+ ### selectOption
1780
+
1781
+ Selects an option in a drop-down select.
1782
+ Field is searched by label | name | CSS | XPath.
1783
+ Option is selected by visible text or by value.
1784
+
1785
+ ```js
1786
+ I.selectOption('Choose Plan', 'Monthly'); // select by label
1787
+ I.selectOption('subscription', 'Monthly'); // match option by text
1788
+ I.selectOption('subscription', '0'); // or by value
1789
+ I.selectOption('//form/select[@name=account]','Premium');
1790
+ I.selectOption('form select[name=account]', 'Premium');
1791
+ I.selectOption({css: 'form select[name=account]'}, 'Premium');
1792
+ ```
1793
+
1794
+ #### Parameters
1795
+
1796
+ * `select` **([string][2] | [object][5])** field located by label|name|CSS|XPath|strict locator.
1797
+ * `option` **([string][2] | [Array][6]<[string][2]>)** visible text or value of option, or an array of them for a multi-select.
1798
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1799
+
1800
+ Returns **[Promise][1]<void>**&#x20;
1801
+
1802
+ ### setCookie
1803
+
1804
+ Sets cookie(s).
1805
+
1806
+ Can be a single cookie object or an array of cookies:
1807
+
1808
+ ```js
1809
+ I.setCookie({name: 'auth', value: true});
1810
+
1811
+ // as array
1812
+ I.setCookie([
1813
+ {name: 'auth', value: true},
1814
+ {name: 'agree', value: true}
1815
+ ]);
1816
+ ```
1817
+
1818
+ #### Parameters
1819
+
1820
+ * `cookie` **(CodeceptJS.Cookie | [Array][6]<CodeceptJS.Cookie>)** a cookie object or array of cookie objects.
1821
+
1822
+ Returns **[Promise][1]<void>**&#x20;
1823
+
1824
+ ### startRecordingTraffic
1825
+
1826
+ Starts recording network traffic via CDP's `Network.requestWillBeSent`/`responseReceived`
1827
+ events, in the same shape (`{url, method, requestHeaders, requestPostData, response}` per
1828
+ request, `response` a promise of `{url(), status(), statusText(), body()}`) the shared
1829
+ `lib/helper/network` actions expect from Puppeteer/Playwright. The CDP listeners are
1830
+ installed once (lazily) and left in place afterwards, since `CDPConnection` has no listener
1831
+ removal and `this.cdp` is reused across tests; they filter by `this.sessionId`, so only the
1832
+ currently active test/page's requests are recorded.
1833
+
1834
+ ```js
1835
+ I.startRecordingTraffic();
1836
+ ```
1837
+
1838
+ Returns **[Promise][1]<void>**&#x20;
1839
+
1840
+ ### startScreencast
1841
+
1842
+ Starts recording a CDP `Page.startScreencast` session for the current test's target: frames
1843
+ arrive as `Page.screencastFrame` events, are acknowledged immediately (`Page.screencastFrameAck`,
1844
+ required or the browser stops sending more), and buffered in `this._screencastFrames`. The
1845
+ underlying `Page.screencastFrame` listener is installed once (lazily) and left in place, like
1846
+ `startRecordingTraffic`'s listeners, since `CDPConnection` has no listener-removal API; it
1847
+ filters by `this.sessionId` so only the currently active test's frames are buffered. Call
1848
+ `stopScreencast` to end the capture and assemble the buffered frames into an APNG.
1849
+
1850
+ ```js
1851
+ I.startScreencast();
1852
+ ```
1853
+
1854
+ #### Parameters
1855
+
1856
+ * `options` **[object][5]?** {maxWidth: number, maxHeight: number, quality: number, everyNthFrame: number} — CDP `Page.startScreencast` pass-throughs. `format` is always `'png'`.
1857
+
1858
+ Returns **[Promise][1]<void>**&#x20;
1859
+
1860
+ ### stopRecordingTraffic
1861
+
1862
+ Stops recording network traffic started by `startRecordingTraffic`. Already-recorded requests
1863
+ in `this.requests` are kept; only new requests stop being appended.
1864
+
1865
+ ```js
1866
+ I.stopRecordingTraffic();
1867
+ ```
1868
+
1869
+ Returns **void**&#x20;
1870
+
1871
+ ### stopScreencast
1872
+
1873
+ Stops the screencast started by `startScreencast` and assembles the buffered frames into a
1874
+ single APNG (Animated PNG) file, returned as a Buffer. Frame delays are derived from the CDP
1875
+ frame metadata's `timestamp` deltas (frame arrival is activity-driven — Obscura and Chrome both
1876
+ only emit a frame on damage — so this reproduces the actual pacing of what happened, not a
1877
+ fixed frame rate); the last frame is held for `options.lastFrameDelayMs` (default 1000ms) since
1878
+ it has no "next" frame to derive a delay from. Every frame is checked for the PNG signature
1879
+ before assembly — CDP's `format: 'png'` is honored by both Chrome and Obscura (verified
1880
+ directly), but if some other engine ever sends a different format regardless, this reports it
1881
+ via `debugSection` and returns `null` instead of muxing a broken file. Returns `null` if no
1882
+ frames were captured (screencast never started, or stopped immediately after starting).
1883
+
1884
+ ```js
1885
+ const apngBuffer = await I.stopScreencast();
1886
+ ```
1887
+
1888
+ #### Parameters
1889
+
1890
+ * `options` **[object][5]?** {lastFrameDelayMs: number} — hold time in milliseconds for the final frame (default 1000).
1891
+
1892
+ Returns **[Promise][1]<[object][5]>** a Buffer with the assembled APNG, or null if there was nothing to assemble.
1893
+
1894
+ ### type
1895
+
1896
+ Types characters into the currently focused element (as set by `click`, `focus`, etc). Each
1897
+ character dispatches a real `keydown` → `keypress` → (value mutated) → `input` → `keyup`
1898
+ sequence, and mutates a `contenteditable` host's `textContent` instead of `.value`, so this
1899
+ works on rich-text/contenteditable targets as well as `input`/`textarea`. Mirrors Puppeteer's
1900
+ `type(text, options)` semantics.
1901
+
1902
+ Without a `delay`, every character is dispatched in a single round-trip to the page. With a
1903
+ `delay`, characters are dispatched one round-trip at a time so the requested pause actually
1904
+ elapses between key presses.
1905
+
1906
+ ```js
1907
+ I.click('Name');
1908
+ I.type('CodeceptJS');
1909
+ I.type(['C', 'o', 'd', 'e']);
1910
+ ```
1911
+
1912
+ #### Parameters
1913
+
1914
+ * `keys` **([string][2] | [Array][6]<[string][2]>)** characters to type, either as a string or an array of characters.
1915
+ * `delay` **[number][8]?** (optional) delay in milliseconds between key presses.
1916
+
1917
+ Returns **[Promise][1]<void>**&#x20;
1918
+
1919
+ ### uncheckOption
1920
+
1921
+ Unselects a checkbox or radio button.
1922
+ Element is located by label or name or CSS or XPath.
1923
+
1924
+ ```js
1925
+ I.uncheckOption('#agree');
1926
+ I.uncheckOption('I Agree to Terms and Conditions');
1927
+ I.uncheckOption('agree', '//form');
1928
+ ```
1929
+
1930
+ #### Parameters
1931
+
1932
+ * `field` **([string][2] | [object][5])** checkbox located by label | name | CSS | XPath | strict locator.
1933
+ * `context` **([string][2]? | [object][5])** (optional, `null` by default) element located by CSS | XPath | strict locator.
1934
+
1935
+ Returns **[Promise][1]<void>**&#x20;
1936
+
1937
+ ### wait
1938
+
1939
+ Pauses execution for a number of seconds.
1940
+
1941
+ ```js
1942
+ I.wait(2); // waits 2 secs
1943
+ ```
1944
+
1945
+ #### Parameters
1946
+
1947
+ * `sec` **[number][8]** number of seconds to wait.
1948
+
1949
+ Returns **[Promise][1]<void>**&#x20;
1950
+
1951
+ ### waitCurrentPathEquals
1952
+
1953
+ Waits for current url path (ignoring query string and hash) to equal to the expected.
1954
+
1955
+ ```js
1956
+ I.waitCurrentPathEquals('/info', 2);
1957
+ ```
1958
+
1959
+ #### Parameters
1960
+
1961
+ * `path` **[string][2]** value to check.
1962
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
1963
+
1964
+ Returns **[Promise][1]<void>**&#x20;
1965
+
1966
+ ### waitForCookie
1967
+
1968
+ Waits for a cookie with the given name to be set (by default waits for `options.waitForTimeout` seconds).
1969
+
1970
+ ```js
1971
+ I.waitForCookie('auth', 5);
1972
+ ```
1973
+
1974
+ #### Parameters
1975
+
1976
+ * `name` **[string][2]** cookie name.
1977
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
1978
+
1979
+ Returns **[Promise][1]<void>**&#x20;
1980
+
1981
+ ### waitForDetached
1982
+
1983
+ Waits for an element to be removed from the DOM (by default waits for `options.waitForTimeout` seconds).
1984
+
1985
+ ```js
1986
+ I.waitForDetached('#popup', 5);
1987
+ ```
1988
+
1989
+ #### Parameters
1990
+
1991
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
1992
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
1993
+
1994
+ Returns **[Promise][1]<void>**&#x20;
1995
+
1996
+ ### waitForElement
1997
+
1998
+ Waits for element to be present on page (by default waits for `options.waitForTimeout` seconds).
1999
+ Element can be located by CSS or XPath.
2000
+
2001
+ ```js
2002
+ I.waitForElement('.btn.continue');
2003
+ I.waitForElement('.btn.continue', 5); // wait for 5 secs
2004
+ ```
2005
+
2006
+ #### Parameters
2007
+
2008
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
2009
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2010
+
2011
+ Returns **[Promise][1]<void>**&#x20;
2012
+
2013
+ ### waitForFunction
2014
+
2015
+ Waits for a function to return true (waits for `options.waitForTimeout` seconds by default).
2016
+ Running in browser context.
2017
+
2018
+ ```js
2019
+ I.waitForFunction(() => window.requests == 0);
2020
+ I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec
2021
+ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec
2022
+ ```
2023
+
2024
+ #### Parameters
2025
+
2026
+ * `fn` **([string][2] | [function][3])** to be executed in browser context.
2027
+ * `argsOrSec` **([Array][6]<any> | [number][8])?** (optional) arguments for function or, if a number, seconds to wait.
2028
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2029
+
2030
+ Returns **[Promise][1]<void>**&#x20;
2031
+
2032
+ ### waitForInvisible
2033
+
2034
+ Waits for an element to become invisible (by default waits for `options.waitForTimeout` seconds).
2035
+
2036
+ ```js
2037
+ I.waitForInvisible('#popup', 5);
2038
+ ```
2039
+
2040
+ #### Parameters
2041
+
2042
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
2043
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2044
+
2045
+ Returns **[Promise][1]<void>**&#x20;
2046
+
2047
+ ### waitForText
2048
+
2049
+ Waits for a text to appear (by default waits for `options.waitForTimeout` seconds).
2050
+ Element can be located by CSS or XPath.
2051
+ Narrow down search results by providing context.
2052
+
2053
+ ```js
2054
+ I.waitForText('Thank you, form has been submitted');
2055
+ I.waitForText('Thank you, form has been submitted', 5, '#modal');
2056
+ ```
2057
+
2058
+ #### Parameters
2059
+
2060
+ * `text` **[string][2]** to wait for.
2061
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2062
+ * `context` **([string][2]? | [object][5])** (optional) element located by CSS|XPath|strict locator.
2063
+
2064
+ Returns **[Promise][1]<void>**&#x20;
2065
+
2066
+ ### waitForVisible
2067
+
2068
+ Waits for an element to become visible (by default waits for `options.waitForTimeout` seconds).
2069
+
2070
+ ```js
2071
+ I.waitForVisible('#popup', 5);
2072
+ ```
2073
+
2074
+ #### Parameters
2075
+
2076
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
2077
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2078
+
2079
+ Returns **[Promise][1]<void>**&#x20;
2080
+
2081
+ ### waitInUrl
2082
+
2083
+ Waiting for the part of the URL to match the expected. Useful for SPA to understand that page was changed.
2084
+
2085
+ ```js
2086
+ I.waitInUrl('/info', 2);
2087
+ ```
2088
+
2089
+ #### Parameters
2090
+
2091
+ * `urlPart` **[string][2]** value to check.
2092
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2093
+
2094
+ Returns **[Promise][1]<void>**&#x20;
2095
+
2096
+ ### waitToHide
2097
+
2098
+ Waits for an element to be hidden. Alias of `waitForInvisible`.
2099
+
2100
+ #### Parameters
2101
+
2102
+ * `locator` **([string][2] | [object][5])** element located by CSS|XPath|strict locator.
2103
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2104
+
2105
+ Returns **[Promise][1]<void>**&#x20;
2106
+
2107
+ ### waitUrlEquals
2108
+
2109
+ Waits for the entire URL to match the expected (by default waits for `options.waitForTimeout` seconds).
2110
+
2111
+ ```js
2112
+ I.waitUrlEquals('/info', 2);
2113
+ ```
2114
+
2115
+ #### Parameters
2116
+
2117
+ * `urlPart` **[string][2]** value to check.
2118
+ * `sec` **[number][8]?** (optional, `options.waitForTimeout` by default) time in seconds to wait
2119
+
2120
+ Returns **[Promise][1]<void>**&#x20;
2121
+
2122
+ [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
2123
+
2124
+ [2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
2125
+
2126
+ [3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
2127
+
2128
+ [4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
2129
+
2130
+ [5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
2131
+
2132
+ [6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
2133
+
2134
+ [7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
2135
+
2136
+ [8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
2137
+
2138
+ [9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp