codeceptjs 4.2.0-beta.4 → 4.2.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +2 -0
  2. package/bin/codecept.js +11 -0
  3. package/docs/agents.md +26 -1
  4. package/docs/ai.md +57 -0
  5. package/docs/alternative-browsers.md +175 -148
  6. package/docs/assertions.md +74 -0
  7. package/docs/bootstrap.md +2 -0
  8. package/docs/commands.md +45 -0
  9. package/docs/configuration.md +37 -0
  10. package/docs/debugging.md +1 -1
  11. package/docs/helpers/ApiDataFactory.md +20 -20
  12. package/docs/helpers/Appium.md +1615 -670
  13. package/docs/helpers/Decision.md +146 -0
  14. package/docs/helpers/GraphQL.md +31 -31
  15. package/docs/helpers/GraphQLDataFactory.md +20 -20
  16. package/docs/helpers/Kitesurf.md +1808 -25
  17. package/docs/helpers/Lightpanda.md +139 -0
  18. package/docs/helpers/Obscura.md +1799 -74
  19. package/docs/helpers/Playwright.md +490 -428
  20. package/docs/helpers/Puppeteer.md +317 -255
  21. package/docs/helpers/REST.md +43 -43
  22. package/docs/helpers/WebDriver.md +237 -175
  23. package/docs/installation.md +16 -0
  24. package/docs/mcp.md +7 -1
  25. package/docs/parallel.md +35 -1
  26. package/docs/plugins/pause.md +2 -1
  27. package/docs/plugins/sitemap.md +48 -0
  28. package/docs/plugins.md +4 -0
  29. package/lib/ai.js +81 -2
  30. package/lib/codecept.js +32 -2
  31. package/lib/command/init.js +22 -0
  32. package/lib/command/initAgent.js +78 -0
  33. package/lib/command/run-multiple.js +3 -0
  34. package/lib/command/run-workers.js +10 -3
  35. package/lib/command/run.js +3 -2
  36. package/lib/command/utils.js +15 -0
  37. package/lib/command/workers/runTests.js +10 -10
  38. package/lib/container.js +4 -2
  39. package/lib/effects.js +19 -1
  40. package/lib/helper/Appium.js +23 -0
  41. package/lib/helper/CDPBrowser.js +387 -1338
  42. package/lib/helper/Decision.js +256 -0
  43. package/lib/helper/Kitesurf.js +3 -21
  44. package/lib/helper/Lightpanda.js +137 -0
  45. package/lib/helper/Obscura.js +21 -238
  46. package/lib/helper/Playwright.js +50 -4
  47. package/lib/helper/Puppeteer.js +62 -8
  48. package/lib/helper/WebDriver.js +45 -1
  49. package/lib/helper/extras/clipboard.js +31 -0
  50. package/lib/listener/result.js +4 -0
  51. package/lib/mocha/bdd.js +19 -1
  52. package/lib/plugin/junitReporter.js +4 -1
  53. package/lib/plugin/pause.js +4 -1
  54. package/lib/plugin/sitemap.js +228 -0
  55. package/lib/recorder.js +19 -18
  56. package/lib/result.js +16 -0
  57. package/lib/step/base.js +12 -0
  58. package/lib/utils.js +2 -10
  59. package/lib/webServer.js +193 -0
  60. package/lib/workers.js +118 -31
  61. package/package.json +4 -2
  62. package/typings/index.d.ts +60 -7
  63. package/typings/promiseBasedTypes.d.ts +985 -814
  64. package/typings/types.d.ts +1084 -815
  65. package/docs/helpers/CDPBrowser.md +0 -2138
@@ -770,6 +770,36 @@ declare namespace CodeceptJS {
770
770
  * @returns Appium: support both Android and iOS
771
771
  */
772
772
  closeApp(): Promise<void>;
773
+ /**
774
+ * Clears the system clipboard.
775
+ *
776
+ * ```js
777
+ * I.clearClipboard();
778
+ * I.seeClipboardEquals('');
779
+ * ```
780
+ * @returns automatically synchronized promise through #recorder
781
+ *
782
+ *
783
+ * Appium: support both Android and iOS
784
+ */
785
+ clearClipboard(): void;
786
+ /**
787
+ * Grabs the text content of the system clipboard and returns it to test.
788
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
789
+ *
790
+ * ```js
791
+ * I.click('Copy to clipboard');
792
+ * let url = await I.grabFromClipboard();
793
+ * ```
794
+ *
795
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
796
+ * in Chromium-based browsers, where read access is granted automatically.
797
+ * @returns the system clipboard contents.
798
+ *
799
+ *
800
+ * Appium: support both Android and iOS
801
+ */
802
+ grabFromClipboard(): Promise<string>;
773
803
  /**
774
804
  * Appends text to a input field or textarea.
775
805
  * Field is located by name, label, CSS or XPath
@@ -1191,16 +1221,16 @@ declare namespace CodeceptJS {
1191
1221
  *
1192
1222
  * This helper should be configured in codecept.conf.js
1193
1223
  * @property [url = http://localhost] - base url of website to be tested.
1194
- * @property [endpoint = http://127.0.0.1:9222] - 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.
1195
- * @property [headers = {}] - headers sent with the endpoint resolution request and the WebSocket handshake. Useful for authenticated remote browser providers.
1196
- * @property [input = auto] - 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`.
1197
- * @property [xpathPolyfill = auto] - 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.
1198
- * @property [capabilities = {}] - pre-seed detected browser capabilities (`layout`, `xpath`, `screenshot`, `innerText`) to skip runtime probing. Values set here are never overwritten by `_probeCapabilities`/`_ensureClient`.
1199
- * @property [waitForTimeout = 5] - default wait* timeout in seconds, used by helpers built on top of this class.
1200
- * @property [waitForAction = 100] - 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.
1201
- * @property [pollInterval = 25] - interval in milliseconds between retries while polling for a condition (e.g. page ready state, `waitFor*`). Distinct from `waitForAction`.
1202
- * @property [getPageTimeout = 30] - 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).
1203
- * @property [waitForNavigation = load] - 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.
1224
+ * @property [endpoint = http://127.0.0.1:9222] - Chrome DevTools Protocol endpoint: an `http(s)://` address or a `ws(s)://` debugger URL.
1225
+ * @property [headers = {}] - headers sent when connecting to the endpoint, e.g. for authenticated remote browsers.
1226
+ * @property [input = auto] - how actions are dispatched: `cdp` (real mouse and keyboard events) or `synthetic` (DOM events). `auto` picks `cdp` when the browser renders layout.
1227
+ * @property [xpathPolyfill = auto] - inject an XPath polyfill for browsers with incomplete XPath support. `auto` detects when it is needed.
1228
+ * @property [capabilities = {}] - browser capabilities (`layout`, `xpath`, `screenshot`, `innerText`) to use instead of detecting them at runtime.
1229
+ * @property [waitForTimeout = 5] - default timeout for wait* actions, in seconds.
1230
+ * @property [waitForAction] - fixed delay after each action, in milliseconds. When unset, actions wait only for the navigation they trigger.
1231
+ * @property [pollInterval = 25] - interval between checks while waiting, in milliseconds.
1232
+ * @property [getPageTimeout = 30] - maximum time to wait for a page to load, in seconds.
1233
+ * @property [waitForNavigation = load] - when a navigation is considered finished: `load`, `domcontentloaded`, or `networkidle`.
1204
1234
  */
1205
1235
  type CDPBrowserConfig = {
1206
1236
  url?: string;
@@ -1224,6 +1254,8 @@ declare namespace CodeceptJS {
1224
1254
  * script evaluation, and simple in-page element interaction (installed lazily through the
1225
1255
  * `window.__codecept` client script). It does not launch a browser itself — point `endpoint` at an
1226
1256
  * already-running Chrome (or any CDP-compatible browser) started with `--remote-debugging-port`.
1257
+ * Subclasses for browsers shipped as a standalone binary opt into launching and reaping their own
1258
+ * server process through `_manageServer`.
1227
1259
  *
1228
1260
  * ## Example
1229
1261
  *
@@ -1246,419 +1278,163 @@ declare namespace CodeceptJS {
1246
1278
  class CDPBrowser {
1247
1279
  constructor(config: CDPBrowserConfig);
1248
1280
  /**
1249
- * No-op hook kept for interface parity with other browser helpers. Connecting to the CDP
1250
- * endpoint is deferred to `_before`, since a fresh target/session is opened per test.
1281
+ * Opts a subclass into managing its own browser server process. Called from a subclass
1282
+ * constructor with the raw user config and a server descriptor:
1283
+ *
1284
+ * - `name` — binary name looked up on `PATH`, also used in messages
1285
+ * - `envVar` — environment variable that may point at the binary
1286
+ * - `args(port)` — arguments the binary is spawned with to serve CDP on `port`
1287
+ * - `env` — extra environment variables for the spawned process
1288
+ * - `releases` — URL shown when no binary can be resolved
1289
+ *
1290
+ * An explicit `endpoint` in the user config always wins: the helper stays in ATTACH mode and
1291
+ * never spawns or kills anything. Otherwise the helper becomes SELF-MANAGED and the default
1292
+ * `endpoint` is cleared until `_resolveSelfManaged` sets the real one.
1293
+ * @param config - the config object the helper was constructed with.
1294
+ * @param server - the server descriptor described above.
1251
1295
  */
1252
- _init(): void;
1296
+ protected _manageServer(config: any, server: any): void;
1253
1297
  /**
1254
- * Resolves `options.endpoint` to a raw WebSocket debugger URL. If the configured endpoint is
1255
- * an `http(s)://` address, this fetches `/json/version` from it and reads `webSocketDebuggerUrl`
1256
- * from the response, matching the discovery flow exposed by Chrome's `--remote-debugging-port`.
1257
- * A `ws(s)://` endpoint is returned unchanged.
1298
+ * Resolves how to reach a SELF-MANAGED browser, trying, in order: spawn a binary
1299
+ * (`binaryPath` config, then the descriptor's `envVar`, then its `name` on `PATH`) on
1300
+ * `options.port` or a free port, courtesy-attach to `http://127.0.0.1:9222` if something already
1301
+ * answers there (never killed by this helper), or throw a loud, actionable error. Sets
1302
+ * `this.options.endpoint` as a side effect.
1258
1303
  *
1259
- * This is the subclass override point for helpers that connect through a different discovery
1260
- * mechanism (e.g. a cloud browser provider with its own session-creation API).
1261
- * @returns a `ws(s)://` debugger URL ready to be passed to `CDPConnection`.
1304
+ * A spawn failure (e.g. a bad binary) is delivered asynchronously by Node as an `error` event;
1305
+ * it is recorded on `this.serverError` and surfaced as a rejection from `_waitForServer` instead
1306
+ * of crashing the process as an uncaught exception.
1262
1307
  */
1263
- protected _resolveEndpoint(): Promise<string>;
1308
+ protected _resolveSelfManaged(): void;
1264
1309
  /**
1265
- * Resolves the CDP endpoint and opens the underlying `CDPConnection`, storing it on `this.cdp`.
1310
+ * Resolves the binary to spawn, in priority order: `options.binaryPath`, then the server
1311
+ * descriptor's environment variable, then its name on `PATH`. The `PATH` lookup walks the
1312
+ * directories itself instead of shelling out to `which`, which does not exist on Windows: on
1313
+ * Windows every `PATHEXT` suffix is tried, so a `.exe` on `PATH` is found too.
1314
+ * @returns an absolute or relative path to the binary, or null if none resolved.
1266
1315
  */
1267
- protected _connect(): void;
1268
- /**
1269
- * Hook executed before each test. Ensures a live `CDPConnection` exists (connecting lazily on
1270
- * first use, and reconnecting if a previous connection was closed), then creates a fresh
1271
- * `about:blank` target and attaches to it with `Target.attachToTarget`, storing `this.targetId`
1272
- * and `this.sessionId`. `Page` and `Runtime` domains are enabled on the new session, and engine
1273
- * capabilities are probed here (against `about:blank`, uncontended) rather than only lazily on
1274
- * the first real page — see `_probeCapabilities`.
1275
- *
1276
- * Also resets `_navStartWaiters` and `_lastMainFrameNav`: both are scoped to a single
1277
- * `sessionId`/`targetId`, which are about to change, so anything left over from the previous test
1278
- * (e.g. an action-settle waiter still armed because its test threw between arming and settling)
1279
- * can never legitimately resolve against the new session — better to drop it here than leave it
1280
- * waiting for the rest of the run.
1281
- */
1282
- protected _before(): void;
1283
- /**
1284
- * Lazily installs a single, persistent `Page.lifecycleEvent` listener on the underlying
1285
- * `CDPConnection` and drains it into whichever `_waitForLoadEvent` calls are currently pending,
1286
- * matched by `loaderId`. Installed once per helper instance (the connection outlives individual
1287
- * tests), never removed — `CDPConnection` has no listener-removal API, so a single persistent
1288
- * dispatcher (rather than one listener per navigation) is what keeps this leak-free.
1289
- *
1290
- * Also, for the main frame (`params.frameId === this.targetId`, which holds for a page target's
1291
- * own top-level frame) only:
1292
- * - Drains `_navStartWaiters` (armed by `_armActionSettle`, before an action, for `_waitForAction`'s
1293
- * event-aware settle) on an `'init'` event — confirmed via a raw probe (against both Obscura and
1294
- * Chrome, through the actual CLI path) to be the earliest signal CDP emits when a new top-level
1295
- * navigation begins. Arming happens *before* the action is dispatched, not after: the same probe
1296
- * found `'init'` can arrive while the action's own CDP round trip is still in flight, sometimes
1297
- * only a millisecond or two after it started — a listener installed only once the action's
1298
- * promise resolves can already be too late, not merely unlucky.
1299
- * - Maintains `_lastMainFrameNav`, a rolling `{loaderId, events}` record of every lifecycle event
1300
- * name seen for the current main-frame navigation (reset whenever `loaderId` changes). On a
1301
- * fast/local navigation, the same raw probe found the *entire* sequence — `init` through
1302
- * `networkIdle` — arriving as one batch while the triggering action's own round trip was still
1303
- * in flight. Without this cache, `_waitForAction` would correctly detect that a navigation
1304
- * started, then arm a *fresh* wait for the `load` event specifically — which, in that common
1305
- * case, had already fired and will never fire again, paying the full grace-window-plus-poll cost
1306
- * of `_waitForPageLoad` on every single navigating action instead of settling immediately.
1307
- */
1308
- protected _ensureLifecycleListener(): void;
1309
- /**
1310
- * Starts waiting for a `Page.lifecycleEvent` named `eventName` for the given `loaderId` on the
1311
- * current session. `loaderId` (from the `Page.navigate` response) discriminates the awaited
1312
- * navigation from any other in-flight or stale lifecycle events (e.g. the `about:blank` target
1313
- * created in `_before`), which is essential since Chrome emits the target's initial `about:blank`
1314
- * lifecycle sequence asynchronously, sometimes after this listener is already installed.
1315
- *
1316
- * Returns a `{promise, cancel}` pair rather than a bare promise: `_waitForPageLoad` races this
1317
- * against a readyState poll, and whichever side loses must be actively torn down (not just have
1318
- * its rejection swallowed) — an abandoned-but-still-pending wait would sit in `_pageLoadWaiters`
1319
- * for the full timeout on every single navigation, for no purpose.
1320
- * @param loaderId - the loader id of the navigation to wait for, from `Page.navigate`'s response.
1321
- * @param eventName - the `Page.lifecycleEvent` name to wait for (e.g. `load`, `DOMContentLoaded`, `networkIdle`).
1322
- * @param timeoutSec - maximum time to wait, in seconds.
1323
- */
1324
- protected _waitForLoadEvent(loaderId: string, eventName: string, timeoutSec: number): any;
1325
- /**
1326
- * Arms the event-aware settle's navigation-start listener. Must be called *before* the action
1327
- * that might trigger a navigation is dispatched, not after — see `_ensureLifecycleListener` for
1328
- * why. Returns `null` when `options.waitForAction` was set explicitly, since `_waitForAction`
1329
- * ignores the armed listener entirely in that case (a literal fixed sleep, as before this round).
1330
- *
1331
- * No timeout here: `_waitForAction` applies the grace window itself, starting from when *it*
1332
- * runs (after the action's own dispatch already resolved), racing this already-armed listener
1333
- * against a fresh timer instead of one that started ticking before the action even began.
1334
- */
1335
- protected _armActionSettle(): any | null;
1336
- /**
1337
- * Waits for a page to finish loading after `Page.navigate`/`Page.reload`, per `options.waitForNavigation`.
1338
- *
1339
- * Purely event-driven for the first `PAGE_LOAD_GRACE_MS`: only the push-based
1340
- * `Page.lifecycleEvent` signal (matched by `loaderId`) is awaited, issuing zero `_evaluate` calls
1341
- * — this matters because an `_evaluate` sent while the page's own JavaScript is still busy (e.g.
1342
- * a real-world page doing post-load hydration/analytics work) can queue behind it for hundreds of
1343
- * ms to multiple seconds, measured directly against a JS-heavy page. Only if the grace window
1344
- * elapses without the event (an engine that doesn't emit it, or a genuinely slow navigation) does
1345
- * the `document.readyState` poll (via `_poll`) start, racing the still-pending lifecycle wait —
1346
- * both bounded by the same `options.getPageTimeout`, so a lifecycle-less engine costs at most
1347
- * `PAGE_LOAD_GRACE_MS` more than the poll alone would have, never double the timeout. No
1348
- * `loaderId` (e.g. from `Page.reload`, which returns none) skips straight to the poll.
1349
- *
1350
- * Whichever side ultimately loses is actively cancelled, not merely abandoned — an abandoned poll
1351
- * or lifecycle wait would otherwise keep running (issuing readyState `_evaluate` calls every
1352
- * `pollInterval`, or holding a `_pageLoadWaiters` entry) for up to the full timeout on every
1353
- * navigation, competing for the same CDP connection with real work.
1354
- * @param loaderId - loader id from the triggering `Page.navigate` response, if any.
1355
- * @param timeoutMessage - error message used if the readyState poll times out.
1356
- */
1357
- protected _waitForPageLoad(loaderId: string | null, timeoutMessage: string): Promise<void>;
1358
- /**
1359
- * Hook executed after each test. Closes the target opened in `_before` via `Target.closeTarget`
1360
- * and clears `this.targetId`/`this.sessionId`. The underlying `CDPConnection` is left open so it
1361
- * can be reused by the next test.
1362
- */
1363
- protected _after(): void;
1316
+ protected _resolveBinary(): string | null;
1364
1317
  /**
1365
- * Hook executed after all tests are run. Closes the underlying `CDPConnection` (and its
1366
- * WebSocket) and clears `this.cdp`. Must leave no open sockets or pending timers behind, so the
1367
- * process can exit on its own.
1318
+ * Picks a free TCP port on 127.0.0.1 by briefly listening on port 0 and reading back the
1319
+ * OS-assigned port. Used when `options.port` isn't explicitly set, so multiple `run-workers`
1320
+ * workers never collide on the same port.
1321
+ * @returns a free port.
1368
1322
  */
1369
- protected _finishTest(): void;
1323
+ protected _findFreePort(): Promise<number>;
1370
1324
  /**
1371
- * Evaluates a JavaScript expression in the page attached to the current session via
1372
- * `Runtime.evaluate`, awaiting any returned promise and returning the value by reference
1373
- * (`returnByValue: true`). If the expression throws, the browser-side exception description
1374
- * (or fallback text) is re-thrown as a JS `Error`.
1375
- * @param expression - a JavaScript expression (or IIFE) to run in the page context.
1376
- * @returns the evaluated value, or `undefined` if the expression has no result.
1377
- */
1378
- protected _evaluate(expression: string): Promise<any>;
1379
- /**
1380
- * Ensures the in-page client (`window.__codecept`, installed from `cdpBrowserClient.js`) is
1381
- * present on the current page, installing it (and the XPath polyfill, if needed) exactly once.
1382
- * Safe to call repeatedly; it is a no-op once the client is detected.
1383
- */
1384
- protected _ensureClient(): void;
1385
- /**
1386
- * Installs the in-page client unconditionally — no `typeof window.__codecept` presence check.
1387
- * Used by callers that already know, from a sentinel value returned alongside a failed action,
1388
- * that the client is missing on the current page, so re-checking would just be a redundant
1389
- * contended round trip.
1390
- *
1391
- * The 171KB XPath polyfill is only injected alongside the client when `needsXPath` is true (the
1392
- * default, for callers without candidate information) *and* the engine actually needs it
1393
- * (`capabilities.xpath === 'polyfill'`, cached from `_before`'s probe). Callers that know their
1394
- * candidates never resolve to an `xpath` strategy (e.g. `_runSelected`, once it has inspected
1395
- * `candidates`/`within`) can pass `false` to skip that inject — the client is still told, via the
1396
- * `xpathNeedsPolyfill` flag baked in at install time, that the *engine* will eventually need it,
1397
- * so a later call that does hit an xpath candidate gets a clean `'__NO_XPATH__'` miss signal
1398
- * (from `window.__codecept.run`) instead of silently falling through to a broken native
1399
- * `document.evaluate` — `_runSelected` reacts to that sentinel by injecting the polyfill and
1400
- * retrying once, mirroring the `'__NO_CLIENT__'` handling right next to it.
1401
- */
1402
- protected _installClient(needsXPath?: boolean): void;
1403
- /**
1404
- * Whether any candidate strategy — in `candidates` itself, or in any of the `within` scoping
1405
- * `layers` searched before it — is an `xpath` locator. Used to decide, before the client is even
1406
- * installed, whether the XPath polyfill needs to be bundled into that install or can be deferred.
1407
- */
1408
- protected _candidatesNeedXPath(candidates: { type: string; value: string; }[], layers: { type: string; value: string; }[][]): boolean;
1409
- /**
1410
- * Determines whether the bundled XPath polyfill must be injected before the in-page client is
1411
- * installed. Honors an explicit `options.xpathPolyfill` boolean; otherwise reuses a previously
1412
- * probed `capabilities.xpath`, or probes the page's native `document.evaluate`. The probe appends
1413
- * two throwaway elements distinguished only by text content and asserts that a text-value XPath
1414
- * predicate (`normalize-space(string(.))=...`, the basis of every fuzzy/clickable locator) resolves
1415
- * to exactly the matching one — merely checking that `document.evaluate` runs without throwing is
1416
- * not enough, since some engines execute a text-value predicate without actually filtering by it,
1417
- * silently returning every candidate node instead of none or one. The result is cached on
1418
- * `capabilities.xpath` (`'native'` or `'polyfill'`).
1419
- * @returns `true` if the polyfill should be injected.
1420
- */
1421
- protected _needsXPathPolyfill(): Promise<boolean>;
1422
- /**
1423
- * Determines whether `see`/`dontSee`/`waitForText` should read whole-page text through the
1424
- * client's own visibility-aware `visibleText()` walker instead of the native
1425
- * `document.body.innerText`. Probes once per page by appending a `display:none` element and a
1426
- * `<script>` element, each with distinguishing text, and checking that native `innerText`
1427
- * excludes both — some engines return an `innerText` that does not honor computed visibility or
1428
- * exclude script/style content, even when `getComputedStyle`/layout are otherwise reliable. The
1429
- * result is cached on `capabilities.innerText` (`'native'` or `'computed'`).
1430
- * @returns `true` if the `visibleText()` fallback should be used.
1431
- */
1432
- protected _needsVisibleTextFallback(): Promise<boolean>;
1433
- /**
1434
- * Probes and caches capabilities that depend on the actual browser *engine* rather than any
1435
- * particular page's content: `capabilities.layout` (via `getComputedStyle`), `capabilities.screenshot`
1436
- * (inferred from `layout`), `capabilities.xpath` (via `_needsXPathPolyfill`), and
1437
- * `capabilities.innerText` (via `_needsVisibleTextFallback`). Already-known capabilities
1438
- * (pre-seeded through `options.capabilities`, or probed earlier) are never re-probed — so, across
1439
- * a whole run, this issues a handful of `_evaluate` calls exactly once and is a no-op afterward.
1440
- *
1441
- * Called from `_before`, against the fresh `about:blank` target created there, specifically so
1442
- * these probes run before any real navigation — measured directly (a full stall ledger against
1443
- * `github.com`) that running them on the first *real* page instead can cost seconds each, since
1444
- * every one is an `_evaluate` competing with that page's own JavaScript for the V8 isolate.
1445
- * `about:blank` has no such competition. Also called (cheaply, already cached by then) from
1446
- * `amOnPage`, so a helper that skips `_before` for some reason still probes correctly.
1447
- *
1448
- * The `xpath`/`innerText` probes determine *whether* their respective fallback is needed; they
1449
- * do not install anything — injection stays deferred to `_ensureClient`'s reactive install and
1450
- * `_textSource`'s own read, matching `amOnPage` no longer eagerly installing the client.
1451
- */
1452
- protected _probeCapabilities(): void;
1453
- /**
1454
- * Delegates a find-and-act call to `window.__codecept.run(candidates, action, payload)`. This is
1455
- * the primary extension point used by helpers built on top of this class for element queries and
1456
- * interactions.
1457
- *
1458
- * A per-call `context` locator, when given, is resolved and layered on top of any active
1459
- * `within` block (searched inside it, not instead of it), so `context` narrows the search
1460
- * without breaking out of a surrounding `within`.
1461
- * @param candidates - locator strategies to try, in order, until one matches at least one element.
1462
- * @param action - name of the action to run against the matched elements (e.g. `count`, `click`, `fill`).
1463
- * @param [payload] - extra data the action needs (e.g. `{ value }` for `fill`).
1464
- * @param [context = null] - element to search in, narrowing the candidates below it.
1465
- * @returns number of matched elements and the action's result.
1466
- */
1467
- protected _run(candidates: { type: 'css' | 'xpath'; value: string; }[], action: string, payload?: any, context?: CodeceptJS.LocatorOrString): Promise<{ found: number; result: any; }>;
1468
- /**
1469
- * Same as `_run`, but takes an explicit selection descriptor instead of reading one from
1470
- * `store.currentStep`/`options.strict`. Used internally by `CDPElementHandle` to address one
1471
- * specific element out of a candidate set by its 1-based index.
1472
- *
1473
- * The in-page client's presence is checked in the same round-trip as the action itself: the
1474
- * evaluated expression resolves to a sentinel string when `window.__codecept` is missing (e.g.
1475
- * right after a navigation the registered script didn't reach), in which case the client is
1476
- * installed and the call is retried exactly once. Separately, if the client is already present
1477
- * but reports (via its own `'__NO_XPATH__'` sentinel) that this call needs the XPath polyfill and
1478
- * it was not bundled into that earlier install, the polyfill is injected and the call is retried
1479
- * once more — see `_installClient`.
1480
- * @param selection - `{index}` or `{strict: true}`, mirroring `_selectionDescriptor`.
1481
- */
1482
- protected _runSelected(candidates: { type: 'css' | 'xpath'; value: string; }[], action: string, payload: any | null, selection: any | null, context?: CodeceptJS.LocatorOrString): Promise<{ found: number; result: any; }>;
1483
- /**
1484
- * Builds the `{index, strict}` element-selection descriptor from the current step's options
1485
- * (`store.currentStep.opts`) and `options.strict`, mirroring the semantics of
1486
- * `lib/helper/extras/elementSelection.js` (used by Puppeteer/WebDriver): a per-step
1487
- * `elementIndex` (numeric, or the `'first'`/`'last'` aliases) always takes precedence and
1488
- * disables strict mode for that step; otherwise `exact`/`strictMode` per-step options
1489
- * override `options.strict` to enable or cancel strict mode.
1490
- * @returns descriptor with optional `index` and `strict` keys, or `null` when neither applies.
1491
- */
1492
- protected _selectionDescriptor(): any | null;
1493
- /**
1494
- * A short, human-readable label built from `candidates`, used in `_run`'s elementIndex/strict
1495
- * error messages when no locator string is otherwise available.
1496
- */
1497
- protected _candidatesLabel(candidates: { type: 'css' | 'xpath'; value: string; }[]): string;
1498
- /**
1499
- * Starts a `within` block, scoping every subsequent `_run` call (and therefore every element
1500
- * lookup performed by this helper) to the descendants of the element matched by `locator`.
1501
- * Verifies the element exists (against the full document, i.e. unscoped) before narrowing.
1502
- * @param locator - element located by CSS|XPath|strict locator.
1325
+ * Probes a `/json/version`-style URL with a short timeout, used for the courtesy-attach check.
1326
+ * @returns true if the URL answered.
1503
1327
  */
1504
- _withinBegin(locator: CodeceptJS.LocatorOrString): Promise<void>;
1328
+ protected _probeUp(url: string): Promise<boolean>;
1505
1329
  /**
1506
- * Ends the current `within` block, restoring unscoped element lookups.
1330
+ * Polls `http://127.0.0.1:<port>/json/version` until the spawned server responds,
1331
+ * `this.serverError` is set by the process' `error` event, or `options.serverStartTimeout`
1332
+ * elapses. The process typically comes up within tens of milliseconds — a 20ms retry interval
1333
+ * keeps the wasted tail after the server is actually ready small, since this cost is paid once
1334
+ * per run and counts directly toward real-world startup latency.
1507
1335
  */
1508
- _withinEnd(): Promise<void>;
1336
+ protected _waitForServer(): void;
1509
1337
  /**
1510
- * Repeatedly calls `fn` until it returns a truthy value or `timeoutSec` elapses, checking
1511
- * immediately and waiting `options.pollInterval` milliseconds between subsequent attempts.
1512
- * @param fn - the condition to poll; should resolve to a truthy value once satisfied.
1513
- * @param timeoutSec - maximum time to poll, in seconds.
1514
- * @param message - error message used when the timeout is reached.
1515
- * @param [cancelToken] - 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.
1516
- * @returns the truthy value returned by `fn`.
1338
+ * In SELF-MANAGED mode, resolves and spawns the browser server (or courtesy-attaches to an
1339
+ * already-running one on :9222) exactly once via `_resolveSelfManaged`. Then resolves the CDP
1340
+ * endpoint and opens the underlying `CDPConnection`, storing it on `this.cdp`.
1517
1341
  */
1518
- protected _poll(fn: (...params: any[]) => any, timeoutSec: number, message: string, cancelToken?: any): Promise<any>;
1342
+ protected _connect(): void;
1519
1343
  /**
1520
- * Resolves a path against `options.url`. Absolute URLs (matching `scheme://`) are returned
1521
- * unchanged; anything else is appended to `options.url` with its trailing slash stripped.
1522
- * @param path - an absolute URL or a path relative to `options.url`.
1523
- * @returns the resolved, absolute URL.
1344
+ * Hook executed after all tests are run. Closes the underlying `CDPConnection` (and its
1345
+ * WebSocket) and clears `this.cdp`, then kills the server process spawned by
1346
+ * `_resolveSelfManaged`, if any (`this.serverProcess` is never set when attaching). Must leave no
1347
+ * open sockets, pending timers or child processes behind, so the process can exit on its own.
1348
+ *
1349
+ * The kill runs in a `finally` so the process is always reaped even if closing the CDP
1350
+ * connection throws. It sends `SIGTERM` first and waits for the process to exit; a process that
1351
+ * ignores `SIGTERM` is escalated to `SIGKILL` after 5s. The promise only resolves once the child
1352
+ * has actually exited (confirmed via the `exit` event, not merely once `SIGKILL` was sent — the
1353
+ * kernel needs a moment to reap it), with a final safety-net timeout so a stuck child can never
1354
+ * keep the event loop alive even if that confirmation is somehow lost.
1524
1355
  */
1525
- protected _url(path: string): string;
1356
+ protected _finishTest(): void;
1526
1357
  /**
1527
- * Opens a web page in the current session.
1358
+ * Opens a web page in a browser. Requires relative or absolute url.
1359
+ * If url starts with `/`, opens a web page of a site defined in `url` config parameter.
1528
1360
  *
1529
1361
  * ```js
1530
1362
  * I.amOnPage('/'); // opens main page of website
1531
1363
  * I.amOnPage('https://github.com'); // opens github
1532
1364
  * I.amOnPage('/login'); // opens a login page
1533
1365
  * ```
1534
- *
1535
- * Navigates via `Page.navigate`, then waits (up to `options.getPageTimeout` seconds) for the page
1536
- * to finish loading, preferring the push-based `Page.lifecycleEvent` signal (per
1537
- * `options.waitForNavigation`) over polling `document.readyState`. Capabilities are (re-)probed
1538
- * (a no-op after the first page, since they're cached for the helper's lifetime).
1539
- *
1540
- * The in-page client is deliberately *not* eagerly (re-)installed here — navigation discards any
1541
- * previously injected script, but installing it is deferred to the first actual action after
1542
- * this call, via `_runSelected`'s sentinel-and-retry. This keeps `amOnPage` itself down to the
1543
- * navigate command plus the push-based wait: no `_evaluate` call is issued on this hot path,
1544
- * which matters most right when the page's own JavaScript may still be busy (measured directly:
1545
- * an `_evaluate` sent in that window can queue behind it for hundreds of ms to multiple seconds
1546
- * on a JS-heavy real-world page, regardless of how small the evaluated expression is).
1547
1366
  * @param url - url path or global url.
1367
+ * @returns automatically synchronized promise through #recorder
1548
1368
  */
1549
- amOnPage(url: string): Promise<void>;
1369
+ amOnPage(url: string): void;
1550
1370
  /**
1551
- * Reloads the current page.
1371
+ * Reload the current page.
1552
1372
  *
1553
1373
  * ```js
1554
1374
  * I.refreshPage();
1555
1375
  * ```
1556
- *
1557
- * Triggers `Page.reload` and waits (up to `options.getPageTimeout` seconds) for
1558
- * `document.readyState` to reach `'complete'`.
1376
+ * @returns automatically synchronized promise through #recorder
1559
1377
  */
1560
- refreshPage(): Promise<void>;
1378
+ refreshPage(): void;
1561
1379
  /**
1562
- * Executes a JavaScript function in the browser context and returns its result.
1380
+ * Executes sync script on a page.
1381
+ * Pass arguments to function as additional parameters.
1382
+ * Will return execution result to a test.
1383
+ * In this case you should use async function and await to receive results.
1563
1384
  *
1564
- * If a function is passed, it is serialized with `Function.prototype.toString()`, so it must
1565
- * not reference variables from the outer (Node.js) scope — pass any needed data as arguments
1566
- * instead. A string is evaluated as-is.
1385
+ * Example with jQuery DatePicker:
1567
1386
  *
1568
1387
  * ```js
1569
- * let title = await I.executeScript(() => document.title);
1570
- * let sum = await I.executeScript((a, b) => a + b, 2, 3);
1388
+ * // change date of jQuery DatePicker
1389
+ * I.executeScript(function() {
1390
+ * // now we are inside browser context
1391
+ * $('date').datetimepicker('setDate', new Date());
1392
+ * });
1571
1393
  * ```
1394
+ * Can return values. Don't forget to use `await` to get them.
1572
1395
  *
1573
- * If the function returns a promise, `executeScript` waits for it to resolve.
1574
- * @param fn - a JavaScript function to be executed in the browser context, or a string expression.
1575
- * @param args - arguments to pass into the function.
1576
- * @returns the value returned (or resolved) by the function.
1396
+ * ```js
1397
+ * let date = await I.executeScript(function(el) {
1398
+ * // only basic types can be returned
1399
+ * return $(el).datetimepicker('getDate').toString();
1400
+ * }, '#date'); // passing jquery selector
1401
+ * ```
1402
+ * @param fn - function to be executed in browser context.
1403
+ * @param args - to be passed to function.
1404
+ * @returns script return value
1577
1405
  */
1578
1406
  executeScript(fn: string | ((...params: any[]) => any), ...args: any[]): Promise<any>;
1579
1407
  /**
1580
- * Retrieves the page URL of the current page.
1408
+ * Get current URL from browser.
1409
+ * Resumes test execution, so should be used inside an async function.
1581
1410
  *
1582
1411
  * ```js
1583
1412
  * let url = await I.grabCurrentUrl();
1584
1413
  * console.log(`Current URL is [${url}]`);
1585
1414
  * ```
1586
- * @returns current URL.
1415
+ * @returns current URL
1587
1416
  */
1588
1417
  grabCurrentUrl(): Promise<string>;
1589
1418
  /**
1590
- * Retrieves a page title.
1419
+ * Retrieves a page title and returns it to test.
1420
+ * Resumes test execution, so **should be used inside async with `await`** operator.
1591
1421
  *
1592
1422
  * ```js
1593
1423
  * let title = await I.grabTitle();
1594
1424
  * ```
1595
- * @returns title of the page.
1425
+ * @returns title
1596
1426
  */
1597
1427
  grabTitle(): Promise<string>;
1598
1428
  /**
1599
- * Retrieves the source code of the current page.
1429
+ * Retrieves page source and returns it to test.
1430
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
1600
1431
  *
1601
1432
  * ```js
1602
1433
  * let pageSource = await I.grabSource();
1603
1434
  * ```
1604
- * @returns source code of the current page (the outer HTML of `<html>`).
1435
+ * @returns source code
1605
1436
  */
1606
1437
  grabSource(): Promise<string>;
1607
- /**
1608
- * Builds the list of `{type, value}` candidates `_run` should try, in order, for a given
1609
- * locator and `kind`. A strict locator (CSS/XPath/object form) resolves to a single candidate.
1610
- * A fuzzy (plain-text) locator is expanded into a strategy-specific list of XPath expressions
1611
- * mirroring the click/field/checkbox matching used by other browser helpers (matching by
1612
- * visible text, label, name, placeholder, ARIA attributes, etc.), falling back to treating the
1613
- * raw text as a CSS selector.
1614
- *
1615
- * A role locator (`{role, text, exact}`) resolves to a single `role`-type candidate, resolved
1616
- * in-page by the client's implicit ARIA role mapping (native elements) plus explicit `role`
1617
- * attributes, filtered by accessible name/text when `text` is given.
1618
- * @param locator - element located by CSS|XPath|strict locator, or plain fuzzy text.
1619
- * @param [kind = 'element'] - matching strategy to use when `locator` is fuzzy.
1620
- * @returns candidates to pass to `_run`.
1621
- */
1622
- protected _candidates(locator: CodeceptJS.LocatorOrString, kind?: 'element' | 'clickable' | 'field' | 'checkable'): { type: 'css' | 'xpath' | 'role'; value: string | object; }[];
1623
- /**
1624
- * Resolves the text to search `see`/`dontSee`/`waitForText` against, when no explicit `context`
1625
- * locator is given. An explicit `context` is always resolved through `_run`, so it is implicitly
1626
- * scoped to the active `within` block, if any. Without a `context`, this reads the `within` root's
1627
- * text when a `within` block is active, or the whole page's text otherwise — via native
1628
- * `document.body.innerText`, or the client's `visibleText()` walker when
1629
- * `_needsVisibleTextFallback` determines native `innerText` is not trustworthy.
1630
- */
1631
- protected _textSource(context: CodeceptJS.LocatorOrString): Promise<string>;
1632
- /**
1633
- * Runs the in-page `containsText` check against the whole page (no `context`/`within` scoping —
1634
- * those stay on `_textSource`'s per-element path, already small). Returns only `{found, snippet}`
1635
- * instead of the full haystack: on a page with a large body, serializing that whole string across
1636
- * the CDP wire (and, on engines where `capabilities.innerText` requires the `visibleText()`
1637
- * walker, holding it in memory) is avoidable work `see`/`dontSee`/`waitForText` don't actually
1638
- * need on their common, non-throwing path.
1639
- *
1640
- * Also folds the client's install into the very same round trip when it is still missing, instead
1641
- * of a separate presence-check evaluate followed by an install evaluate before the check itself
1642
- * can even run — mirroring `_runSelected`'s sentinel-retry design, but collapsed into one evaluate
1643
- * since the install source itself is known and cacheable up front. That install is client-only,
1644
- * never the 171KB XPath polyfill: `containsText` never calls `document.evaluate`, so bundling it
1645
- * here would be pure waste for a scenario that never resolves an xpath locator. The client is
1646
- * still told, via `installCodeceptClient`'s `xpathNeedsPolyfill` flag, whether the *engine*
1647
- * (`capabilities.xpath`, cached by `_before`'s `about:blank` probe) will eventually need it, so a
1648
- * later xpath-resolving action on the same page gets a clean `'__NO_XPATH__'` miss signal from
1649
- * `window.__codecept.run` instead of silently hitting a broken native `document.evaluate` —
1650
- * `_runSelected` reacts to that sentinel already. The bootstrap source is built once and reused
1651
- * for the life of the instance, since whether the engine needs the polyfill never changes.
1652
- */
1653
- protected _runTextCheck(text: string, opts: any): Promise<{ found: boolean; snippet: string | null; }>;
1654
- /**
1655
- * Shared implementation for `see`/`dontSee`. Without a `context` locator and outside any `within`
1656
- * block, checks presence via `_runTextCheck`'s fast, boolean-only round trip; the full haystack is
1657
- * only fetched (one extra, rare evaluate) when the assertion is about to fail, to build the same
1658
- * `stringIncludes` error as before this optimization. With a `context` or inside `within`, this is
1659
- * unchanged from before — already a small, per-element read, not the identified cost.
1660
- */
1661
- protected _checkText(text: string, context: CodeceptJS.LocatorOrString, negate: boolean): Promise<void>;
1662
1438
  /**
1663
1439
  * Checks that a page contains a visible text.
1664
1440
  * Use context parameter to narrow down the search.
@@ -1670,8 +1446,9 @@ declare namespace CodeceptJS {
1670
1446
  * ```
1671
1447
  * @param text - expected on page.
1672
1448
  * @param [context = null] - (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
1449
+ * @returns automatically synchronized promise through #recorder
1673
1450
  */
1674
- see(text: string, context?: CodeceptJS.LocatorOrString): Promise<void>;
1451
+ see(text: string, context?: CodeceptJS.LocatorOrString): void;
1675
1452
  /**
1676
1453
  * Opposite to `see`. Checks that a text is not present on a page.
1677
1454
  * Use context parameter to narrow down the search.
@@ -1681,9 +1458,10 @@ declare namespace CodeceptJS {
1681
1458
  * I.dontSee('Login', '.nav'); // no login inside .nav element
1682
1459
  * ```
1683
1460
  * @param text - which is not present.
1684
- * @param [context = null] - (optional) element located by CSS|XPath|strict locator in which to perform search.
1461
+ * @param [context = null] - (optional) element located by CSS|XPath|strict locator in which to perfrom search.
1462
+ * @returns automatically synchronized promise through #recorder
1685
1463
  */
1686
- dontSee(text: string, context?: CodeceptJS.LocatorOrString): Promise<void>;
1464
+ dontSee(text: string, context?: CodeceptJS.LocatorOrString): void;
1687
1465
  /**
1688
1466
  * Checks that the current page contains the given string in its raw source code.
1689
1467
  *
@@ -1691,13 +1469,19 @@ declare namespace CodeceptJS {
1691
1469
  * I.seeInSource('<h1>Green eggs &amp; ham</h1>');
1692
1470
  * ```
1693
1471
  * @param text - value to check.
1472
+ * @returns automatically synchronized promise through #recorder
1694
1473
  */
1695
- seeInSource(text: string): Promise<void>;
1474
+ seeInSource(text: string): void;
1696
1475
  /**
1697
- * Checks that the current page does not contain the given string in its raw source code.
1698
- * @param text - value to check.
1476
+ * Checks that the current page does not contains the given string in its raw source code.
1477
+ *
1478
+ * ```js
1479
+ * I.dontSeeInSource('<!--'); // no comments in source
1480
+ * ```
1481
+ * @param value - to check.
1482
+ * @returns automatically synchronized promise through #recorder
1699
1483
  */
1700
- dontSeeInSource(text: string): Promise<void>;
1484
+ dontSeeInSource(value: string): void;
1701
1485
  /**
1702
1486
  * Checks that current url contains a provided fragment.
1703
1487
  *
@@ -1705,13 +1489,15 @@ declare namespace CodeceptJS {
1705
1489
  * I.seeInCurrentUrl('/register'); // we are on registration page
1706
1490
  * ```
1707
1491
  * @param url - a fragment to check
1492
+ * @returns automatically synchronized promise through #recorder
1708
1493
  */
1709
- seeInCurrentUrl(url: string): Promise<void>;
1494
+ seeInCurrentUrl(url: string): void;
1710
1495
  /**
1711
1496
  * Checks that current url does not contain a provided fragment.
1712
1497
  * @param url - value to check.
1498
+ * @returns automatically synchronized promise through #recorder
1713
1499
  */
1714
- dontSeeInCurrentUrl(url: string): Promise<void>;
1500
+ dontSeeInCurrentUrl(url: string): void;
1715
1501
  /**
1716
1502
  * Checks that title contains text.
1717
1503
  *
@@ -1719,54 +1505,63 @@ declare namespace CodeceptJS {
1719
1505
  * I.seeInTitle('Home Page');
1720
1506
  * ```
1721
1507
  * @param text - text value to check.
1508
+ * @returns automatically synchronized promise through #recorder
1722
1509
  */
1723
- seeInTitle(text: string): Promise<void>;
1510
+ seeInTitle(text: string): void;
1724
1511
  /**
1725
- * Checks that a given Element is present in the DOM.
1512
+ * Checks that a given Element is present in the DOM
1726
1513
  * Element is located by CSS or XPath.
1727
1514
  *
1728
1515
  * ```js
1729
1516
  * I.seeElementInDOM('#modal');
1730
1517
  * ```
1731
1518
  * @param locator - element located by CSS|XPath|strict locator.
1519
+ * @returns automatically synchronized promise through #recorder
1732
1520
  */
1733
- seeElementInDOM(locator: CodeceptJS.LocatorOrString): Promise<void>;
1521
+ seeElementInDOM(locator: CodeceptJS.LocatorOrString): void;
1734
1522
  /**
1735
1523
  * Opposite to `seeElementInDOM`. Checks that element is not on page.
1736
1524
  *
1737
1525
  * ```js
1738
1526
  * I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
1739
1527
  * ```
1740
- * @param locator - located by CSS|XPath|strict locator.
1741
- */
1742
- dontSeeElementInDOM(locator: CodeceptJS.LocatorOrString): Promise<void>;
1743
- /**
1744
- * Throws if the current page has no real layout engine (`capabilities.layout === 'none'`),
1745
- * used to guard visibility-dependent assertions that cannot be evaluated without one.
1746
- * @param action - name of the calling assertion, used in the error message.
1528
+ * @param locator - located by CSS|XPath|Strict locator.
1529
+ * @returns automatically synchronized promise through #recorder
1747
1530
  */
1748
- protected _assertLayoutSupported(action: string): void;
1531
+ dontSeeElementInDOM(locator: CodeceptJS.LocatorOrString): void;
1749
1532
  /**
1750
- * Checks that a given Element is visible.
1533
+ * Checks that a given Element is visible
1751
1534
  * Element is located by CSS or XPath.
1752
1535
  *
1536
+ * The second parameter is a context (CSS or XPath locator) to narrow the search.
1537
+ *
1753
1538
  * ```js
1754
1539
  * I.seeElement('#modal');
1540
+ * I.seeElement('#modal', '#container');
1541
+ * // using ARIA role locator
1542
+ * I.seeElement({role: 'dialog'});
1755
1543
  * ```
1544
+ *
1545
+ * > ℹ️ ARIA role locators (`{role, name}`) match elements the way assistive technology does and survive markup refactors. See [Locators](/locators#aria-locators).
1756
1546
  * @param locator - located by CSS|XPath|strict locator.
1757
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1547
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1548
+ * @returns automatically synchronized promise through #recorder
1758
1549
  */
1759
- seeElement(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1550
+ seeElement(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
1760
1551
  /**
1761
- * Opposite to `seeElement`. Checks that element is not visible.
1552
+ * Opposite to `seeElement`. Checks that element is not visible (or in DOM)
1553
+ *
1554
+ * The second parameter is a context (CSS or XPath locator) to narrow the search.
1762
1555
  *
1763
1556
  * ```js
1764
1557
  * I.dontSeeElement('.modal'); // modal is not shown
1558
+ * I.dontSeeElement('.modal', '#container');
1765
1559
  * ```
1766
- * @param locator - located by CSS|XPath|strict locator.
1767
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1560
+ * @param locator - located by CSS|XPath|Strict locator.
1561
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1562
+ * @returns automatically synchronized promise through #recorder
1768
1563
  */
1769
- dontSeeElement(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1564
+ dontSeeElement(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
1770
1565
  /**
1771
1566
  * Verifies that the specified checkbox is checked.
1772
1567
  *
@@ -1775,19 +1570,22 @@ declare namespace CodeceptJS {
1775
1570
  * I.seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms
1776
1571
  * I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
1777
1572
  * ```
1778
- * @param locator - located by label|name|CSS|XPath|strict locator.
1573
+ * @param field - located by label|name|CSS|XPath|strict locator.
1574
+ * @returns automatically synchronized promise through #recorder
1779
1575
  */
1780
- seeCheckboxIsChecked(locator: CodeceptJS.LocatorOrString): Promise<void>;
1576
+ seeCheckboxIsChecked(field: CodeceptJS.LocatorOrString): void;
1781
1577
  /**
1782
1578
  * Verifies that the specified checkbox is not checked.
1783
1579
  *
1784
1580
  * ```js
1785
1581
  * I.dontSeeCheckboxIsChecked('#agree'); // located by ID
1786
1582
  * I.dontSeeCheckboxIsChecked('I agree to terms'); // located by label
1583
+ * I.dontSeeCheckboxIsChecked('agree'); // located by name
1787
1584
  * ```
1788
- * @param locator - located by label|name|CSS|XPath|strict locator.
1585
+ * @param field - located by label|name|CSS|XPath|strict locator.
1586
+ * @returns automatically synchronized promise through #recorder
1789
1587
  */
1790
- dontSeeCheckboxIsChecked(locator: CodeceptJS.LocatorOrString): Promise<void>;
1588
+ dontSeeCheckboxIsChecked(field: CodeceptJS.LocatorOrString): void;
1791
1589
  /**
1792
1590
  * Retrieves a text from an element located by CSS or XPath and returns it to test.
1793
1591
  * Resumes test execution, so **should be used inside async with `await`** operator.
@@ -1797,49 +1595,42 @@ declare namespace CodeceptJS {
1797
1595
  * ```
1798
1596
  * If multiple elements found returns first element.
1799
1597
  * @param locator - element located by CSS|XPath|strict locator.
1800
- * @returns text value
1598
+ * @returns attribute value
1801
1599
  */
1802
1600
  grabTextFrom(locator: CodeceptJS.LocatorOrString): Promise<string>;
1803
1601
  /**
1804
- * Retrieves all texts from elements located by CSS or XPath and returns it to test.
1602
+ * Retrieves all texts from an element located by CSS or XPath and returns it to test.
1805
1603
  * Resumes test execution, so **should be used inside async with `await`** operator.
1806
1604
  *
1807
1605
  * ```js
1808
1606
  * let pins = await I.grabTextFromAll('#pin li');
1809
1607
  * ```
1810
1608
  * @param locator - element located by CSS|XPath|strict locator.
1811
- * @returns array of text values
1609
+ * @returns attribute value
1812
1610
  */
1813
1611
  grabTextFromAll(locator: CodeceptJS.LocatorOrString): Promise<string[]>;
1814
1612
  /**
1815
- * Retrieves an array of `WebElement`s matching a locator (`lib/element/WebElement.js`,
1816
- * wrapping a `CDPElementHandle`). Element handles are re-resolved on demand by re-running
1817
- * `candidates` and picking the matching index, since `CDPBrowser` never keeps a persistent
1818
- * handle to a DOM node on the Node side.
1613
+ * Grab WebElements for given locator
1614
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
1819
1615
  *
1820
1616
  * ```js
1821
- * const buttons = await I.grabWebElements({ role: 'button' });
1617
+ * const webElements = await I.grabWebElements('#button');
1822
1618
  * ```
1823
1619
  * @param locator - element located by CSS|XPath|strict locator.
1824
- * @returns array of WebElement instances.
1620
+ * @returns WebElement of being used Web helper
1825
1621
  */
1826
- grabWebElements(locator: CodeceptJS.LocatorOrString): Promise<object[]>;
1622
+ grabWebElements(locator: CodeceptJS.LocatorOrString): Promise<any>;
1827
1623
  /**
1828
- * Retrieves the first `WebElement` matching a locator.
1624
+ * Grab WebElement for given locator
1625
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
1829
1626
  *
1830
1627
  * ```js
1831
- * const button = await I.grabWebElement({ role: 'button', text: 'Submit' });
1628
+ * const webElement = await I.grabWebElement('#button');
1832
1629
  * ```
1833
1630
  * @param locator - element located by CSS|XPath|strict locator.
1834
- * @returns a WebElement instance.
1835
- */
1836
- grabWebElement(locator: CodeceptJS.LocatorOrString): Promise<object>;
1837
- /**
1838
- * Resolves whether the `texts` action should read via the client's `visibleText()` walker
1839
- * (probed once via `_needsVisibleTextFallback` and cached on `capabilities.innerText`) instead
1840
- * of each element's native `innerText`, then runs it.
1631
+ * @returns WebElement of being used Web helper
1841
1632
  */
1842
- protected _texts(candidates: { type: string; value: string | object; }[]): Promise<{ found: number; result: any; }>;
1633
+ grabWebElement(locator: CodeceptJS.LocatorOrString): Promise<any>;
1843
1634
  /**
1844
1635
  * Retrieves a value from a form element located by CSS or XPath and returns it to test.
1845
1636
  * Resumes test execution, so **should be used inside async function with `await`** operator.
@@ -1853,14 +1644,14 @@ declare namespace CodeceptJS {
1853
1644
  */
1854
1645
  grabValueFrom(locator: CodeceptJS.LocatorOrString): Promise<string>;
1855
1646
  /**
1856
- * Retrieves an array of values from fields located by CSS or XPath and returns it to test.
1647
+ * Retrieves an array of value from a form located by CSS or XPath and returns it to test.
1857
1648
  * Resumes test execution, so **should be used inside async function with `await`** operator.
1858
1649
  *
1859
1650
  * ```js
1860
1651
  * let inputs = await I.grabValueFromAll('//form/input');
1861
1652
  * ```
1862
1653
  * @param locator - field located by label|name|CSS|XPath|strict locator.
1863
- * @returns array of attribute values
1654
+ * @returns attribute value
1864
1655
  */
1865
1656
  grabValueFromAll(locator: CodeceptJS.LocatorOrString): Promise<string[]>;
1866
1657
  /**
@@ -1885,7 +1676,7 @@ declare namespace CodeceptJS {
1885
1676
  * ```
1886
1677
  * @param locator - element located by CSS|XPath|strict locator.
1887
1678
  * @param attr - attribute name.
1888
- * @returns array of attribute values
1679
+ * @returns attribute value
1889
1680
  */
1890
1681
  grabAttributeFromAll(locator: CodeceptJS.LocatorOrString, attr: string): Promise<string[]>;
1891
1682
  /**
@@ -1905,13 +1696,13 @@ declare namespace CodeceptJS {
1905
1696
  * For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
1906
1697
  * For images, the "alt" attribute and inner text of any parent links are searched.
1907
1698
  *
1908
- * When `options.input` is `'cdp'`, the click is dispatched as real `Input.dispatchMouseEvent` mouse events
1909
- * (`mouseMoved` / `mousePressed` / `mouseReleased`) at the center of the element's bounding box, so it
1910
- * exercises the same input pipeline a real user would. Otherwise it delegates to `forceClick`. A matched
1911
- * element with a zero-size bounding box (e.g. `display: none`) has no valid coordinate to click and throws;
1912
- * use `forceClick` to dispatch a synthetic click on such elements instead.
1699
+ * If no locator is provided, defaults to clicking the body element (`'//body'`).
1700
+ *
1701
+ * The second parameter is a context (CSS or XPath locator) to narrow the search.
1913
1702
  *
1914
1703
  * ```js
1704
+ * // click body element (default)
1705
+ * I.click();
1915
1706
  * // simple link
1916
1707
  * I.click('Logout');
1917
1708
  * // button of form
@@ -1920,22 +1711,31 @@ declare namespace CodeceptJS {
1920
1711
  * I.click('#form input[type=submit]');
1921
1712
  * // XPath
1922
1713
  * I.click('//form/*[@type=submit]');
1714
+ * // link in context
1715
+ * I.click('Logout', '#nav');
1923
1716
  * // using strict locator
1924
1717
  * I.click({css: 'nav a.login'});
1718
+ * // using ARIA role locator
1719
+ * I.click({role: 'button', name: 'Submit'});
1925
1720
  * ```
1926
- * @param locator - clickable link or button located by text, or any element located by CSS|XPath|strict locator.
1721
+ *
1722
+ * > ℹ️ ARIA role locators (`{role, name}`) match elements the way assistive technology does and survive markup refactors. See [Locators](/locators#aria-locators).
1723
+ * @param [locator = '//body'] - (optional, `'//body'` by default) clickable link or button located by text, or any element located by CSS|XPath|strict locator.
1927
1724
  * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1725
+ * @returns automatically synchronized promise through #recorder
1928
1726
  */
1929
- click(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1727
+ click(locator?: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString | null): void;
1930
1728
  /**
1931
1729
  * Perform an emulated click on a link or a button, given by a locator.
1932
- * Unlike `click`, this always dispatches a synthetic in-page `el.click()` instead of sending native
1933
- * CDP input events. This works on hidden, animated or inactive elements as well.
1730
+ * Unlike normal click instead of sending native event, emulates a click with JavaScript.
1731
+ * This works on hidden, animated or inactive elements as well.
1934
1732
  *
1935
1733
  * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
1936
1734
  * For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
1937
1735
  * For images, the "alt" attribute and inner text of any parent links are searched.
1938
1736
  *
1737
+ * The second parameter is a context (CSS or XPath locator) to narrow the search.
1738
+ *
1939
1739
  * ```js
1940
1740
  * // simple link
1941
1741
  * I.forceClick('Logout');
@@ -1945,46 +1745,22 @@ declare namespace CodeceptJS {
1945
1745
  * I.forceClick('#form input[type=submit]');
1946
1746
  * // XPath
1947
1747
  * I.forceClick('//form/*[@type=submit]');
1748
+ * // link in context
1749
+ * I.forceClick('Logout', '#nav');
1948
1750
  * // using strict locator
1949
1751
  * I.forceClick({css: 'nav a.login'});
1950
1752
  * ```
1951
1753
  * @param locator - clickable link or button located by text, or any element located by CSS|XPath|strict locator.
1952
1754
  * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1755
+ * @returns automatically synchronized promise through #recorder
1953
1756
  */
1954
- forceClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1955
- /**
1956
- * Settles after an interaction (click, key press, etc.) before the next step runs, using the
1957
- * listener `_armActionSettle` started *before* the interaction was dispatched (`armed`; a fresh
1958
- * one is armed here too, as a safety net, if a call site forgot to — but arming this late can
1959
- * only miss a navigation that already started during the action's own dispatch, exactly the race
1960
- * this design exists to avoid, so every call site should pass its own pre-armed `armed`, not rely
1961
- * on this fallback).
1962
- *
1963
- * If `options.waitForAction` was set explicitly in the config, honors it literally as a fixed
1964
- * pacing sleep, exactly as before this round — an explicit value is a deliberate choice
1965
- * (slow-motion debugging, a known-slow app) this never second-guesses.
1966
- *
1967
- * Otherwise, event-aware: races the armed listener against a *fresh* `ACTION_SETTLE_GRACE_MS`
1968
- * window (started now, not when it was armed — the action's own dispatch already ran concurrently
1969
- * with the arm, so this is genuinely bounded extra time, not a guess). If nothing declares a
1970
- * navigation, returns immediately once the window elapses — the common case for most actions
1971
- * (typing, toggling a checkbox, focusing a field) — instead of a fixed `options.waitForAction`
1972
- * (100ms by default) sleep on every single action regardless of whether anything is happening.
1973
- *
1974
- * If a navigation *did* start, `_lastMainFrameNav` (see `_ensureLifecycleListener`) is checked
1975
- * first: on a fast/local page, the entire lifecycle sequence through the target event has
1976
- * typically already arrived in the same batch that announced the navigation started, in which
1977
- * case this returns immediately. Only a navigation still genuinely in flight falls through to
1978
- * `_waitForPageLoad` (the same mechanism `amOnPage`/`refreshPage` use) — which waits for it to
1979
- * actually finish, rather than a fixed sleep that has no relationship to how long the navigation
1980
- * actually takes: strictly more correct for a slow navigation, not just faster for a fast one.
1981
- * @param [armed] - from `_armActionSettle`, called before the action.
1982
- */
1983
- protected _waitForAction(armed?: any | null): Promise<void>;
1757
+ forceClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
1984
1758
  /**
1985
1759
  * Fills a text field or textarea, after clearing its value, with the given string.
1986
1760
  * Field is located by name, label, CSS, or XPath.
1987
1761
  *
1762
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
1763
+ *
1988
1764
  * ```js
1989
1765
  * // by label
1990
1766
  * I.fillField('Email', 'hello@world.com');
@@ -1994,43 +1770,62 @@ declare namespace CodeceptJS {
1994
1770
  * I.fillField('form#login input[name=username]', 'John');
1995
1771
  * // or by strict locator
1996
1772
  * I.fillField({css: 'form#login input[name=username]'}, 'John');
1773
+ * // by ARIA role locator
1774
+ * I.fillField({role: 'textbox', name: 'Email'}, 'hello@world.com');
1775
+ * // within a context
1776
+ * I.fillField('Name', 'John', '#section2');
1997
1777
  * ```
1778
+ *
1779
+ * > ℹ️ ARIA role locators (`{role, name}`) match fields by their accessible name and survive markup refactors. See [Locators](/locators#aria-locators).
1998
1780
  * @param field - located by label|name|CSS|XPath|strict locator.
1999
1781
  * @param value - text value to fill.
2000
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1782
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1783
+ * @returns automatically synchronized promise through #recorder
2001
1784
  */
2002
- fillField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): Promise<void>;
1785
+ fillField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): void;
2003
1786
  /**
2004
1787
  * Appends text to a input field or textarea.
2005
1788
  * Field is located by name, label, CSS or XPath
2006
1789
  *
1790
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
1791
+ *
2007
1792
  * ```js
2008
1793
  * I.appendField('#myTextField', 'appended');
2009
1794
  * // typing secret
2010
1795
  * I.appendField('password', secret('123456'));
1796
+ * // within a context
1797
+ * I.appendField('name', 'John', '.form-container');
2011
1798
  * ```
2012
1799
  * @param field - located by label|name|CSS|XPath|strict locator
2013
1800
  * @param value - text value to append.
2014
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1801
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1802
+ * @returns automatically synchronized promise through #recorder
2015
1803
  */
2016
- appendField(field: CodeceptJS.LocatorOrString, value: string, context?: CodeceptJS.LocatorOrString): Promise<void>;
1804
+ appendField(field: CodeceptJS.LocatorOrString, value: string, context?: CodeceptJS.LocatorOrString): void;
2017
1805
  /**
2018
1806
  * Clears a `<textarea>` or text `<input>` element's value.
2019
1807
  *
1808
+ * The second parameter is an optional context (CSS or XPath locator) to narrow the search.
1809
+ *
2020
1810
  * ```js
2021
1811
  * I.clearField('Email');
2022
1812
  * I.clearField('user[email]');
2023
1813
  * I.clearField('#email');
1814
+ * // within a context
1815
+ * I.clearField('Email', '.form-container');
2024
1816
  * ```
2025
- * @param field - editable field located by label|name|CSS|XPath|strict locator.
2026
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1817
+ * @param editable - field located by label|name|CSS|XPath|strict locator.
1818
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1819
+ * @returns automatically synchronized promise through #recorder.
2027
1820
  */
2028
- clearField(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1821
+ clearField(editable: LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
2029
1822
  /**
2030
1823
  * Selects an option in a drop-down select.
2031
1824
  * Field is searched by label | name | CSS | XPath.
2032
1825
  * Option is selected by visible text or by value.
2033
1826
  *
1827
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
1828
+ *
2034
1829
  * ```js
2035
1830
  * I.selectOption('Choose Plan', 'Monthly'); // select by label
2036
1831
  * I.selectOption('subscription', 'Monthly'); // match option by text
@@ -2038,16 +1833,27 @@ declare namespace CodeceptJS {
2038
1833
  * I.selectOption('//form/select[@name=account]','Premium');
2039
1834
  * I.selectOption('form select[name=account]', 'Premium');
2040
1835
  * I.selectOption({css: 'form select[name=account]'}, 'Premium');
1836
+ * // within a context
1837
+ * I.selectOption('age', '21-60', '#section2');
1838
+ * ```
1839
+ *
1840
+ * Provide an array for the second argument to select multiple options.
1841
+ *
1842
+ * ```js
1843
+ * I.selectOption('Which OS do you use?', ['Android', 'iOS']);
2041
1844
  * ```
2042
1845
  * @param select - field located by label|name|CSS|XPath|strict locator.
2043
- * @param option - visible text or value of option, or an array of them for a multi-select.
2044
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1846
+ * @param option - visible text or value of option.
1847
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1848
+ * @returns automatically synchronized promise through #recorder
2045
1849
  */
2046
- selectOption(select: CodeceptJS.LocatorOrString, option: string | string[], context?: CodeceptJS.LocatorOrString): Promise<void>;
1850
+ selectOption(select: LocatorOrString, option: string | any[], context?: CodeceptJS.LocatorOrString): void;
2047
1851
  /**
2048
1852
  * Selects a checkbox or radio button.
2049
1853
  * Element is located by label or name or CSS or XPath.
2050
1854
  *
1855
+ * The second parameter is an optional context (CSS or XPath locator) to narrow the search.
1856
+ *
2051
1857
  * ```js
2052
1858
  * I.checkOption('#agree');
2053
1859
  * I.checkOption('I Agree to Terms and Conditions');
@@ -2055,12 +1861,15 @@ declare namespace CodeceptJS {
2055
1861
  * ```
2056
1862
  * @param field - checkbox located by label | name | CSS | XPath | strict locator.
2057
1863
  * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1864
+ * @returns automatically synchronized promise through #recorder
2058
1865
  */
2059
- checkOption(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1866
+ checkOption(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
2060
1867
  /**
2061
1868
  * Unselects a checkbox or radio button.
2062
1869
  * Element is located by label or name or CSS or XPath.
2063
1870
  *
1871
+ * The second parameter is an optional context (CSS or XPath locator) to narrow the search.
1872
+ *
2064
1873
  * ```js
2065
1874
  * I.uncheckOption('#agree');
2066
1875
  * I.uncheckOption('I Agree to Terms and Conditions');
@@ -2068,32 +1877,37 @@ declare namespace CodeceptJS {
2068
1877
  * ```
2069
1878
  * @param field - checkbox located by label | name | CSS | XPath | strict locator.
2070
1879
  * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1880
+ * @returns automatically synchronized promise through #recorder
2071
1881
  */
2072
- uncheckOption(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
1882
+ uncheckOption(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
2073
1883
  /**
2074
- * Attaches a file to a file input field, or drops it onto a drag-and-drop dropzone element,
2075
- * resolved by label|name|CSS|XPath|strict locator. `pathToFile` is resolved relative to
2076
- * `codecept_dir` (matching Puppeteer/WebDriver). Since `CDPBrowser` never brings element handles
2077
- * back to Node, the resolved element is marked with a throwaway `data-codecept-upload` attribute
2078
- * in-page (respecting `context`/`within`/elementIndex exactly like every other action). A real
2079
- * `<input type="file">` is then addressed by that attribute through the CDP `DOM` domain, which
2080
- * `CDPBrowser` otherwise never uses, to call `DOM.setFileInputFiles`; any other element (a
2081
- * drag-and-drop dropzone) instead gets a synthetic `dragenter`/`dragover`/`drop` sequence with a
2082
- * `DataTransfer` built from the file's contents, entirely in-page. The marker is removed again in
2083
- * a `finally`.
1884
+ * Attaches a file to element located by label, name, CSS or XPath
1885
+ * Path to file is relative current codecept directory (where codecept.conf.ts or codecept.conf.js is located).
1886
+ * File will be uploaded to remote system (if tests are running remotely).
1887
+ *
1888
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
2084
1889
  *
2085
1890
  * ```js
2086
1891
  * I.attachFile('Avatar', 'data/avatar.jpg');
2087
- * I.attachFile('#file', 'data/avatar.jpg');
1892
+ * I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
1893
+ * // within a context
1894
+ * I.attachFile('Avatar', 'data/avatar.jpg', '.form-container');
1895
+ * ```
1896
+ *
1897
+ * If the locator points to a non-file-input element (e.g., a dropzone area),
1898
+ * the file will be dropped onto that element using drag-and-drop events.
1899
+ *
1900
+ * ```js
2088
1901
  * I.attachFile('#dropzone', 'data/avatar.jpg');
2089
1902
  * ```
2090
- * @param field - located by label|name|CSS|XPath|strict locator.
2091
- * @param pathToFile - path to file, relative to `codecept_dir`.
2092
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
1903
+ * @param locator - field located by label|name|CSS|XPath|strict locator.
1904
+ * @param pathToFile - local file path relative to codecept.conf.ts or codecept.conf.js config file.
1905
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
1906
+ * @returns automatically synchronized promise through #recorder
2093
1907
  */
2094
- attachFile(field: CodeceptJS.LocatorOrString, pathToFile: string, context?: CodeceptJS.LocatorOrString): Promise<void>;
1908
+ attachFile(locator: CodeceptJS.LocatorOrString, pathToFile: string, context?: CodeceptJS.LocatorOrString): void;
2095
1909
  /**
2096
- * Waits for element to be present on page (by default waits for `options.waitForTimeout` seconds).
1910
+ * Waits for element to be present on page (by default waits for 1sec).
2097
1911
  * Element can be located by CSS or XPath.
2098
1912
  *
2099
1913
  * ```js
@@ -2101,11 +1915,12 @@ declare namespace CodeceptJS {
2101
1915
  * I.waitForElement('.btn.continue', 5); // wait for 5 secs
2102
1916
  * ```
2103
1917
  * @param locator - element located by CSS|XPath|strict locator.
2104
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
1918
+ * @param [sec = null] - (optional, `1` by default) time in seconds to wait
1919
+ * @returns automatically synchronized promise through #recorder
2105
1920
  */
2106
- waitForElement(locator: CodeceptJS.LocatorOrString, sec?: number): Promise<void>;
1921
+ waitForElement(locator: CodeceptJS.LocatorOrString, sec?: number): void;
2107
1922
  /**
2108
- * Waits for a text to appear (by default waits for `options.waitForTimeout` seconds).
1923
+ * Waits for a text to appear (by default waits for 1sec).
2109
1924
  * Element can be located by CSS or XPath.
2110
1925
  * Narrow down search results by providing context.
2111
1926
  *
@@ -2114,10 +1929,11 @@ declare namespace CodeceptJS {
2114
1929
  * I.waitForText('Thank you, form has been submitted', 5, '#modal');
2115
1930
  * ```
2116
1931
  * @param text - to wait for.
2117
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
1932
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2118
1933
  * @param [context = null] - (optional) element located by CSS|XPath|strict locator.
1934
+ * @returns automatically synchronized promise through #recorder
2119
1935
  */
2120
- waitForText(text: string, sec?: number, context?: CodeceptJS.LocatorOrString): Promise<void>;
1936
+ waitForText(text: string, sec?: number, context?: CodeceptJS.LocatorOrString): void;
2121
1937
  /**
2122
1938
  * Waiting for the part of the URL to match the expected. Useful for SPA to understand that page was changed.
2123
1939
  *
@@ -2125,23 +1941,29 @@ declare namespace CodeceptJS {
2125
1941
  * I.waitInUrl('/info', 2);
2126
1942
  * ```
2127
1943
  * @param urlPart - value to check.
2128
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
1944
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
1945
+ * @returns automatically synchronized promise through #recorder
2129
1946
  */
2130
- waitInUrl(urlPart: string, sec?: number): Promise<void>;
1947
+ waitInUrl(urlPart: string, sec?: number): void;
2131
1948
  /**
2132
- * Waits for a function to return true (waits for `options.waitForTimeout` seconds by default).
1949
+ * Waits for a function to return true (waits for 1 sec by default).
2133
1950
  * Running in browser context.
2134
1951
  *
2135
1952
  * ```js
1953
+ * I.waitForFunction(fn[, [args[, timeout]])
1954
+ * ```
1955
+ *
1956
+ * ```js
2136
1957
  * I.waitForFunction(() => window.requests == 0);
2137
1958
  * I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec
2138
1959
  * I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec
2139
1960
  * ```
2140
1961
  * @param fn - to be executed in browser context.
2141
- * @param [argsOrSec = null] - (optional) arguments for function or, if a number, seconds to wait.
2142
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
1962
+ * @param [argsOrSec = null] - (optional, `1` by default) arguments for function or seconds.
1963
+ * @param [sec = null] - (optional, `1` by default) time in seconds to wait
1964
+ * @returns automatically synchronized promise through #recorder
2143
1965
  */
2144
- waitForFunction(fn: string | ((...params: any[]) => any), argsOrSec?: any[] | number, sec?: number): Promise<void>;
1966
+ waitForFunction(fn: string | ((...params: any[]) => any), argsOrSec?: any[] | number, sec?: number): void;
2145
1967
  /**
2146
1968
  * Sets cookie(s).
2147
1969
  *
@@ -2157,8 +1979,9 @@ declare namespace CodeceptJS {
2157
1979
  * ]);
2158
1980
  * ```
2159
1981
  * @param cookie - a cookie object or array of cookie objects.
1982
+ * @returns automatically synchronized promise through #recorder
2160
1983
  */
2161
- setCookie(cookie: CodeceptJS.Cookie | CodeceptJS.Cookie[]): Promise<void>;
1984
+ setCookie(cookie: Cookie | Cookie[]): void;
2162
1985
  /**
2163
1986
  * Retrieves all cookies visible to the current page.
2164
1987
  * Resumes test execution, so **should be used inside async function with `await`** operator.
@@ -2179,9 +2002,9 @@ declare namespace CodeceptJS {
2179
2002
  * assert(cookie.value, '123456');
2180
2003
  * ```
2181
2004
  * @param [name = null] - cookie name.
2182
- * @returns a cookie object, or an array of all cookies when `name` is not provided.
2005
+ * @returns attribute value
2183
2006
  */
2184
- grabCookie(name?: string | null): Promise<CodeceptJS.Cookie | CodeceptJS.Cookie[]>;
2007
+ grabCookie(name?: string): any;
2185
2008
  /**
2186
2009
  * Clears a cookie by name,
2187
2010
  * if none provided clears all cookies.
@@ -2190,9 +2013,61 @@ declare namespace CodeceptJS {
2190
2013
  * I.clearCookie();
2191
2014
  * I.clearCookie('test');
2192
2015
  * ```
2193
- * @param [name = null] - (optional, `null` by default) cookie name
2016
+ * @param [cookie = null] - (optional, `null` by default) cookie name
2017
+ */
2018
+ clearCookie(cookie?: string): void;
2019
+ /**
2020
+ * Checks that the system clipboard contains the given text.
2021
+ *
2022
+ * ```js
2023
+ * I.click('Copy to clipboard');
2024
+ * I.seeInClipboard('https://codecept.io');
2025
+ * ```
2026
+ *
2027
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
2028
+ * in Chromium-based browsers, where read access is granted automatically.
2029
+ * @param text - value to check.
2030
+ * @returns automatically synchronized promise through #recorder
2031
+ */
2032
+ seeInClipboard(text: string): void;
2033
+ /**
2034
+ * Checks that the system clipboard is equal to the given text.
2035
+ *
2036
+ * ```js
2037
+ * I.click('Copy to clipboard');
2038
+ * I.seeClipboardEquals('https://codecept.io');
2039
+ * ```
2040
+ *
2041
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
2042
+ * in Chromium-based browsers, where read access is granted automatically.
2043
+ * @param text - value to check.
2044
+ * @returns automatically synchronized promise through #recorder
2045
+ */
2046
+ seeClipboardEquals(text: string): void;
2047
+ /**
2048
+ * Clears the system clipboard.
2049
+ *
2050
+ * ```js
2051
+ * I.clearClipboard();
2052
+ * I.seeClipboardEquals('');
2053
+ * ```
2054
+ * @returns automatically synchronized promise through #recorder
2194
2055
  */
2195
- clearCookie(name?: string | null): Promise<void>;
2056
+ clearClipboard(): void;
2057
+ /**
2058
+ * Grabs the text content of the system clipboard and returns it to test.
2059
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
2060
+ *
2061
+ * ```js
2062
+ * I.click('Copy to clipboard');
2063
+ * let url = await I.grabFromClipboard();
2064
+ * ```
2065
+ *
2066
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
2067
+ * in Chromium-based browsers, where read access is granted automatically.
2068
+ * @returns the system clipboard contents.
2069
+ */
2070
+ grabFromClipboard(): Promise<string>;
2196
2071
  /**
2197
2072
  * Saves a screenshot to the output folder (set in codecept.conf.ts or codecept.conf.js).
2198
2073
  * Filename is relative to the output folder.
@@ -2201,169 +2076,220 @@ declare namespace CodeceptJS {
2201
2076
  * I.saveScreenshot('debug.png');
2202
2077
  * ```
2203
2078
  * @param fileName - file name to save.
2079
+ * @returns automatically synchronized promise through #recorder
2204
2080
  */
2205
- saveScreenshot(fileName: string): Promise<void>;
2081
+ saveScreenshot(fileName: string): void;
2206
2082
  /**
2207
- * Saves a screenshot of a single element to the output folder.
2083
+ * Saves screenshot of the specified locator to ouput folder (set in codecept.conf.ts or codecept.conf.js).
2084
+ * Filename is relative to output folder.
2208
2085
  *
2209
2086
  * ```js
2210
- * I.saveElementScreenshot('#logo', 'logo.png');
2087
+ * I.saveElementScreenshot(`#submit`,'debug.png');
2211
2088
  * ```
2212
2089
  * @param locator - element located by CSS|XPath|strict locator.
2213
2090
  * @param fileName - file name to save.
2091
+ * @returns automatically synchronized promise through #recorder
2214
2092
  */
2215
- saveElementScreenshot(locator: CodeceptJS.LocatorOrString, fileName: string): Promise<void>;
2093
+ saveElementScreenshot(locator: CodeceptJS.LocatorOrString, fileName: string): void;
2216
2094
  /**
2217
2095
  * Pauses execution for a number of seconds.
2218
2096
  *
2219
2097
  * ```js
2220
- * I.wait(2); // waits 2 secs
2098
+ * I.wait(2); // wait 2 secs
2221
2099
  * ```
2222
- * @param sec - number of seconds to wait.
2100
+ * @param sec - number of second to wait.
2101
+ * @returns automatically synchronized promise through #recorder
2223
2102
  */
2224
- wait(sec: number): Promise<void>;
2103
+ wait(sec: number): void;
2225
2104
  /**
2226
2105
  * Checks that title does not contain text.
2106
+ *
2107
+ * ```js
2108
+ * I.dontSeeInTitle('Error');
2109
+ * ```
2227
2110
  * @param text - value to check.
2111
+ * @returns automatically synchronized promise through #recorder
2228
2112
  */
2229
- dontSeeInTitle(text: string): Promise<void>;
2113
+ dontSeeInTitle(text: string): void;
2230
2114
  /**
2231
2115
  * Checks that current url is equal to provided one.
2232
- * Unlike `seeInCurrentUrl` performs a strict comparison.
2116
+ * If a relative url provided, a configured url will be prepended to it.
2117
+ * So both examples will work:
2233
2118
  *
2234
2119
  * ```js
2235
2120
  * I.seeCurrentUrlEquals('/register');
2121
+ * I.seeCurrentUrlEquals('http://my.site.com/register');
2236
2122
  * ```
2237
2123
  * @param url - value to check.
2124
+ * @returns automatically synchronized promise through #recorder
2238
2125
  */
2239
- seeCurrentUrlEquals(url: string): Promise<void>;
2126
+ seeCurrentUrlEquals(url: string): void;
2240
2127
  /**
2241
2128
  * Checks that current url is not equal to provided one.
2242
- * Unlike `dontSeeInCurrentUrl` performs a strict comparison.
2129
+ * If a relative url provided, a configured url will be prepended to it.
2130
+ *
2131
+ * ```js
2132
+ * I.dontSeeCurrentUrlEquals('/login'); // relative url are ok
2133
+ * I.dontSeeCurrentUrlEquals('http://mysite.com/login'); // absolute urls are also ok
2134
+ * ```
2243
2135
  * @param url - value to check.
2136
+ * @returns automatically synchronized promise through #recorder
2244
2137
  */
2245
- dontSeeCurrentUrlEquals(url: string): Promise<void>;
2246
- /**
2247
- * Resolves the current page URL to a `pathname`, ignoring the origin, query string, and hash.
2248
- * @returns the pathname of the current page.
2249
- */
2250
- protected _grabCurrentPath(): Promise<string>;
2138
+ dontSeeCurrentUrlEquals(url: string): void;
2251
2139
  /**
2252
- * Checks that current url path (ignoring query string and hash) equals to provided one.
2140
+ * Checks that current URL path matches the expected path.
2141
+ * Query strings and URL fragments are ignored.
2253
2142
  *
2254
2143
  * ```js
2255
- * I.seeCurrentPathEquals('/info');
2144
+ * I.seeCurrentPathEquals('/info'); // passes for '/info', '/info?user=1', '/info#section'
2145
+ * I.seeCurrentPathEquals('/'); // passes for '/', '/?user=ok', '/#top'
2256
2146
  * ```
2257
2147
  * @param path - value to check.
2148
+ * @returns automatically synchronized promise through #recorder
2258
2149
  */
2259
- seeCurrentPathEquals(path: string): Promise<void>;
2150
+ seeCurrentPathEquals(path: string): void;
2260
2151
  /**
2261
- * Opposite to `seeCurrentPathEquals`.
2152
+ * Checks that current URL path does NOT match the expected path.
2153
+ * Query strings and URL fragments are ignored.
2154
+ *
2155
+ * ```js
2156
+ * I.dontSeeCurrentPathEquals('/form'); // fails for '/form', '/form?user=1', '/form#section'
2157
+ * I.dontSeeCurrentPathEquals('/'); // fails for '/', '/?user=ok', '/#top'
2158
+ * ```
2262
2159
  * @param path - value to check.
2160
+ * @returns automatically synchronized promise through #recorder
2263
2161
  */
2264
- dontSeeCurrentPathEquals(path: string): Promise<void>;
2162
+ dontSeeCurrentPathEquals(path: string): void;
2265
2163
  /**
2266
- * Waits for the entire URL to match the expected (by default waits for `options.waitForTimeout` seconds).
2164
+ * Waits for the entire URL to match the expected
2267
2165
  *
2268
2166
  * ```js
2269
2167
  * I.waitUrlEquals('/info', 2);
2168
+ * I.waitUrlEquals('http://127.0.0.1:8000/info');
2270
2169
  * ```
2271
2170
  * @param urlPart - value to check.
2272
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2171
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2172
+ * @returns automatically synchronized promise through #recorder
2273
2173
  */
2274
- waitUrlEquals(urlPart: string, sec?: number): Promise<void>;
2174
+ waitUrlEquals(urlPart: string, sec?: number): void;
2275
2175
  /**
2276
- * Waits for current url path (ignoring query string and hash) to equal to the expected.
2176
+ * Waits for the current URL path to match the expected path.
2177
+ * Query strings and URL fragments are ignored.
2277
2178
  *
2278
2179
  * ```js
2279
- * I.waitCurrentPathEquals('/info', 2);
2180
+ * I.waitCurrentPathEquals('/info', 5);
2280
2181
  * ```
2281
2182
  * @param path - value to check.
2282
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2183
+ * @param [sec = null] - (optional, `waitForTimeout` by default) time in seconds to wait
2184
+ * @returns automatically synchronized promise through #recorder
2283
2185
  */
2284
- waitCurrentPathEquals(path: string, sec?: number): Promise<void>;
2186
+ waitCurrentPathEquals(path: string, sec?: number): void;
2285
2187
  /**
2286
- * Checks that the given input field or textarea equals (contains) the given value.
2287
- * For fuzzy locators, the field is searched by label|name|CSS|XPath|strict locator.
2188
+ * Checks that the given input field or textarea equals to given value.
2189
+ * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath.
2190
+ *
2191
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
2288
2192
  *
2289
2193
  * ```js
2290
2194
  * I.seeInField('Username', 'davert');
2195
+ * I.seeInField({css: 'form textarea'},'Type your comment here');
2196
+ * I.seeInField('form input[type=hidden]','hidden_value');
2197
+ * I.seeInField('#searchform input','Search');
2198
+ * // within a context
2199
+ * I.seeInField('Name', 'John', '.form-container');
2291
2200
  * ```
2292
2201
  * @param field - located by label|name|CSS|XPath|strict locator.
2293
2202
  * @param value - value to check.
2294
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
2203
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
2204
+ * @returns automatically synchronized promise through #recorder
2295
2205
  */
2296
- seeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): Promise<void>;
2206
+ seeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): void;
2297
2207
  /**
2208
+ * Checks that value of input field or textarea doesn't equal to given value
2298
2209
  * Opposite to `seeInField`.
2210
+ *
2211
+ * The third parameter is an optional context (CSS or XPath locator) to narrow the search.
2212
+ *
2213
+ * ```js
2214
+ * I.dontSeeInField('email', 'user@user.com'); // field by name
2215
+ * I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
2216
+ * // within a context
2217
+ * I.dontSeeInField('Name', 'old_value', '.form-container');
2218
+ * ```
2299
2219
  * @param field - located by label|name|CSS|XPath|strict locator.
2300
2220
  * @param value - value to check.
2301
- * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
2302
- */
2303
- dontSeeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): Promise<void>;
2304
- /**
2305
- * Shared implementation for `seeInField`/`dontSeeInField`.
2221
+ * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator.
2222
+ * @returns automatically synchronized promise through #recorder
2306
2223
  */
2307
- protected _seeInField(assertType: 'assert' | 'negate', field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): Promise<void>;
2224
+ dontSeeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret, context?: CodeceptJS.LocatorOrString): void;
2308
2225
  /**
2309
2226
  * Grab number of visible elements by locator.
2227
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
2310
2228
  *
2311
2229
  * ```js
2312
- * let numOfVisibleElements = await I.grabNumberOfVisibleElements('p');
2230
+ * let numOfElements = await I.grabNumberOfVisibleElements('p');
2313
2231
  * ```
2314
2232
  * @param locator - located by CSS|XPath|strict locator.
2315
- * @returns number of visible matched elements.
2233
+ * @returns number of visible elements
2316
2234
  */
2317
2235
  grabNumberOfVisibleElements(locator: CodeceptJS.LocatorOrString): Promise<number>;
2318
2236
  /**
2319
- * Asserts that an element appears a given number of times on the page, and that all matching elements are visible.
2237
+ * Asserts that an element is visible a given number of times.
2238
+ * Element is located by CSS or XPath.
2320
2239
  *
2321
2240
  * ```js
2322
2241
  * I.seeNumberOfVisibleElements('.buttons', 3);
2323
2242
  * ```
2324
- * @param locator - located by CSS|XPath|strict locator.
2325
- * @param num - expected number of elements.
2243
+ * @param locator - element located by CSS|XPath|strict locator.
2244
+ * @param num - number of elements.
2245
+ * @returns automatically synchronized promise through #recorder
2326
2246
  */
2327
- seeNumberOfVisibleElements(locator: CodeceptJS.LocatorOrString, num: number): Promise<void>;
2247
+ seeNumberOfVisibleElements(locator: CodeceptJS.LocatorOrString, num: number): void;
2328
2248
  /**
2329
- * Retrieves the current page scroll position.
2249
+ * Retrieves a page scroll position and returns it to test.
2250
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
2330
2251
  *
2331
2252
  * ```js
2332
2253
  * let { x, y } = await I.grabPageScrollPosition();
2333
2254
  * ```
2334
- * @returns scroll position.
2255
+ * @returns scroll position
2335
2256
  */
2336
- grabPageScrollPosition(): Promise<{ x: number; y: number; }>;
2257
+ grabPageScrollPosition(): Promise<PageScrollPosition>;
2337
2258
  /**
2338
- * Scrolls to the top of the page.
2259
+ * Scroll page to the top.
2339
2260
  *
2340
2261
  * ```js
2341
2262
  * I.scrollPageToTop();
2342
2263
  * ```
2264
+ * @returns automatically synchronized promise through #recorder
2343
2265
  */
2344
- scrollPageToTop(): Promise<void>;
2266
+ scrollPageToTop(): void;
2345
2267
  /**
2346
- * Scrolls to the bottom of the page.
2268
+ * Scroll page to the bottom.
2347
2269
  *
2348
2270
  * ```js
2349
2271
  * I.scrollPageToBottom();
2350
2272
  * ```
2273
+ * @returns automatically synchronized promise through #recorder
2351
2274
  */
2352
- scrollPageToBottom(): Promise<void>;
2275
+ scrollPageToBottom(): void;
2353
2276
  /**
2354
- * Scrolls to the element matched by locator, or to given coordinates.
2277
+ * Scrolls to element matched by locator.
2278
+ * Extra shift can be set with offsetX and offsetY options.
2355
2279
  *
2356
2280
  * ```js
2357
- * I.scrollTo('#submit');
2358
- * I.scrollTo(100, 200);
2281
+ * I.scrollTo('footer');
2282
+ * I.scrollTo('#submit', 5, 5);
2359
2283
  * ```
2360
- * @param locator - element to scroll to, or an X coordinate if no element.
2361
- * @param [offsetX = 0] - X offset, or Y coordinate if `locator` is a number.
2362
- * @param [offsetY = 0] - Y offset applied when scrolling to an element.
2284
+ * @param locator - located by CSS|XPath|strict locator.
2285
+ * @param [offsetX = 0] - (optional, `0` by default) X-axis offset.
2286
+ * @param [offsetY = 0] - (optional, `0` by default) Y-axis offset.
2287
+ * @returns automatically synchronized promise through #recorder
2363
2288
  */
2364
- scrollTo(locator: CodeceptJS.LocatorOrString | number, offsetX?: number, offsetY?: number): Promise<void>;
2289
+ scrollTo(locator: CodeceptJS.LocatorOrString, offsetX?: number, offsetY?: number): void;
2365
2290
  /**
2366
- * Retrieves a CSS property from an element located by CSS or XPath.
2291
+ * Grab CSS property for given locator
2292
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
2367
2293
  * If more than one element is found - value of first element is returned.
2368
2294
  *
2369
2295
  * ```js
@@ -2375,251 +2301,299 @@ declare namespace CodeceptJS {
2375
2301
  */
2376
2302
  grabCssPropertyFrom(locator: CodeceptJS.LocatorOrString, cssProperty: string): Promise<string>;
2377
2303
  /**
2378
- * Retrieves an array of CSS properties from elements located by CSS or XPath.
2304
+ * Grab array of CSS properties for given locator
2305
+ * Resumes test execution, so **should be used inside an async function with `await`** operator.
2379
2306
  *
2380
2307
  * ```js
2381
2308
  * const values = await I.grabCssPropertyFromAll('h3', 'font-weight');
2382
2309
  * ```
2383
2310
  * @param locator - element located by CSS|XPath|strict locator.
2384
2311
  * @param cssProperty - CSS property name.
2385
- * @returns array of CSS values
2312
+ * @returns CSS value
2386
2313
  */
2387
2314
  grabCssPropertyFromAll(locator: CodeceptJS.LocatorOrString, cssProperty: string): Promise<string[]>;
2388
2315
  /**
2389
- * Checks that all elements matched by locator have the given CSS properties.
2316
+ * Checks that all elements with given locator have given CSS properties.
2390
2317
  *
2391
2318
  * ```js
2392
- * I.seeCssPropertiesOnElements('h3', { 'font-weight': 'bold', display: 'block' });
2319
+ * I.seeCssPropertiesOnElements('h3', { 'font-weight': "bold"});
2393
2320
  * ```
2394
- * @param locator - element located by CSS|XPath|strict locator.
2321
+ * @param locator - located by CSS|XPath|strict locator.
2395
2322
  * @param cssProperties - object with CSS properties and their values to check.
2323
+ * @returns automatically synchronized promise through #recorder
2396
2324
  */
2397
- seeCssPropertiesOnElements(locator: CodeceptJS.LocatorOrString, cssProperties: any): Promise<void>;
2325
+ seeCssPropertiesOnElements(locator: CodeceptJS.LocatorOrString, cssProperties: any): void;
2398
2326
  /**
2399
- * Checks that all elements matched by locator have the given attribute values.
2400
- * An expected value is matched either as an exact match or as a regular expression against the actual value.
2327
+ * Checks that all elements with given locator have given attributes.
2401
2328
  *
2402
2329
  * ```js
2403
- * I.seeAttributesOnElements('//form', { method: 'post' });
2330
+ * I.seeAttributesOnElements('//form', { method: "post"});
2404
2331
  * ```
2405
- * @param locator - element located by CSS|XPath|strict locator.
2406
- * @param attributes - object with attribute names and expected values.
2332
+ * @param locator - located by CSS|XPath|strict locator.
2333
+ * @param attributes - attributes and their values to check.
2334
+ * @returns automatically synchronized promise through #recorder
2407
2335
  */
2408
- seeAttributesOnElements(locator: CodeceptJS.LocatorOrString, attributes: any): Promise<void>;
2336
+ seeAttributesOnElements(locator: CodeceptJS.LocatorOrString, attributes: any): void;
2409
2337
  /**
2410
- * Focuses a given element.
2338
+ * Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the matching element.
2339
+ *
2340
+ * Examples:
2411
2341
  *
2412
2342
  * ```js
2413
- * I.focus('#name');
2343
+ * I.dontSee('#add-to-cart-btn');
2344
+ * I.focus('#product-tile')
2345
+ * I.see('#add-to-cart-bnt');
2414
2346
  * ```
2415
- * @param locator - element located by CSS|XPath|strict locator.
2347
+ * @param locator - field located by label|name|CSS|XPath|strict locator.
2348
+ * @param [options] - Playwright only: [Additional options](https://playwright.dev/docs/api/class-locator#locator-focus) for available options object as 2nd argument.
2349
+ * @returns automatically synchronized promise through #recorder
2416
2350
  */
2417
- focus(locator: CodeceptJS.LocatorOrString): Promise<void>;
2351
+ focus(locator: CodeceptJS.LocatorOrString, options?: any): void;
2418
2352
  /**
2419
- * Removes focus from a given element.
2353
+ * Remove focus from a text input, button, etc.
2354
+ * Calls [blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element.
2355
+ *
2356
+ * Examples:
2420
2357
  *
2421
2358
  * ```js
2422
- * I.blur('#name');
2359
+ * I.blur('.text-area')
2423
2360
  * ```
2424
- * @param locator - element located by CSS|XPath|strict locator.
2361
+ * ```js
2362
+ * //element `#product-tile` is focused
2363
+ * I.see('#add-to-cart-btn');
2364
+ * I.blur('#product-tile')
2365
+ * I.dontSee('#add-to-cart-btn');
2366
+ * ```
2367
+ * @param locator - field located by label|name|CSS|XPath|strict locator.
2368
+ * @param [options] - Playwright only: [Additional options](https://playwright.dev/docs/api/class-locator#locator-blur) for available options object as 2nd argument.
2369
+ * @returns automatically synchronized promise through #recorder
2425
2370
  */
2426
- blur(locator: CodeceptJS.LocatorOrString): Promise<void>;
2371
+ blur(locator: CodeceptJS.LocatorOrString, options?: any): void;
2427
2372
  /**
2428
- * Types characters into the currently focused element (as set by `click`, `focus`, etc). Each
2429
- * character dispatches a real `keydown` → `keypress` → (value mutated) → `input` → `keyup`
2430
- * sequence, and mutates a `contenteditable` host's `textContent` instead of `.value`, so this
2431
- * works on rich-text/contenteditable targets as well as `input`/`textarea`. Mirrors Puppeteer's
2432
- * `type(text, options)` semantics.
2433
- *
2434
- * Without a `delay`, every character is dispatched in a single round-trip to the page. With a
2435
- * `delay`, characters are dispatched one round-trip at a time so the requested pause actually
2436
- * elapses between key presses.
2373
+ * Types out the given text into an active field.
2374
+ * To slow down typing use a second parameter, to set interval between key presses.
2375
+ * _Note:_ Should be used when [`fillField`](#fillfield) is not an option.
2437
2376
  *
2438
2377
  * ```js
2439
- * I.click('Name');
2440
- * I.type('CodeceptJS');
2441
- * I.type(['C', 'o', 'd', 'e']);
2378
+ * // passing in a string
2379
+ * I.type('Type this out.');
2380
+ *
2381
+ * // typing values with a 100ms interval
2382
+ * I.type('4141555311111111', 100);
2383
+ *
2384
+ * // passing in an array
2385
+ * I.type(['T', 'E', 'X', 'T']);
2386
+ *
2387
+ * // passing a secret
2388
+ * I.type(secret('123456'));
2442
2389
  * ```
2443
- * @param keys - characters to type, either as a string or an array of characters.
2444
- * @param [delay = null] - (optional) delay in milliseconds between key presses.
2390
+ * @param key - or array of keys to type.
2391
+ * @param [delay = null] - (optional) delay in ms between key presses
2392
+ * @returns automatically synchronized promise through #recorder
2445
2393
  */
2446
- type(keys: string | string[], delay?: number): Promise<void>;
2394
+ type(key: string | string[], delay?: number): void;
2447
2395
  /**
2448
- * Presses a key or key combination on the currently focused element.
2449
- * Under `options.strict`, a modifier+editing-key combination (e.g. `Ctrl+A`) dispatched with no
2450
- * element focused throws `NonFocusedType`, mirroring `focusCheck.js`'s behavior on other helpers.
2396
+ * Presses a key or a key combination on the focused element.
2451
2397
  *
2452
2398
  * ```js
2453
2399
  * I.pressKey('Enter');
2454
2400
  * I.pressKey(['Control', 'a']);
2455
2401
  * ```
2456
2402
  * @param key - a key or an array of keys to combine (modifiers first).
2403
+ * @returns automatically synchronized promise through #recorder
2457
2404
  */
2458
- pressKey(key: string | string[]): Promise<void>;
2405
+ pressKey(key: string | string[]): void;
2459
2406
  /**
2460
- * Resizes the browser viewport.
2461
- *
2462
- * ```js
2463
- * I.resizeWindow(1024, 768);
2464
- * ```
2465
- * @param width - window width, or `'maximize'`.
2466
- * @param [height] - window height.
2407
+ * Resize the current window to provided width and height.
2408
+ * First parameter can be set to `maximize`.
2409
+ * @param width - width in pixels or `maximize`.
2410
+ * @param height - height in pixels.
2411
+ * @returns automatically synchronized promise through #recorder
2467
2412
  */
2468
- resizeWindow(width: number | 'maximize', height?: number): Promise<void>;
2413
+ resizeWindow(width: number, height: number): void;
2469
2414
  /**
2470
- * Performs a double-click on an element matched by locator.
2415
+ * Performs a double-click on an element matched by link|button|label|CSS or XPath.
2416
+ * Context can be specified as second parameter to narrow search.
2471
2417
  *
2472
2418
  * ```js
2473
2419
  * I.doubleClick('Edit');
2420
+ * I.doubleClick('Edit', '.actions');
2421
+ * I.doubleClick({css: 'button.accept'});
2422
+ * I.doubleClick('.btn.edit');
2474
2423
  * ```
2475
- * @param locator - clickable element located by text, or any element located by CSS|XPath|strict locator.
2476
- * @param [context = null] - (optional, `null` by default, currently ignored by this helper).
2424
+ * @param locator - clickable link or button located by text, or any element located by CSS|XPath|strict locator.
2425
+ * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator.
2426
+ * @returns automatically synchronized promise through #recorder
2477
2427
  */
2478
- doubleClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
2428
+ doubleClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
2479
2429
  /**
2480
- * Performs a right-click on an element matched by locator.
2430
+ * Performs right click on a clickable element matched by semantic locator, CSS or XPath.
2481
2431
  *
2482
2432
  * ```js
2483
- * I.rightClick('Menu');
2433
+ * // right click element with id el
2434
+ * I.rightClick('#el');
2435
+ * // right click link or button with text "Click me"
2436
+ * I.rightClick('Click me');
2437
+ * // right click button with text "Click me" inside .context
2438
+ * I.rightClick('Click me', '.context');
2484
2439
  * ```
2485
- * @param locator - clickable element located by text, or any element located by CSS|XPath|strict locator.
2486
- * @param [context = null] - (optional, `null` by default, currently ignored by this helper).
2440
+ * @param locator - clickable element located by CSS|XPath|strict locator.
2441
+ * @param [context = null] - (optional, `null` by default) element located by CSS|XPath|strict locator.
2442
+ * @returns automatically synchronized promise through #recorder
2487
2443
  */
2488
- rightClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): Promise<void>;
2444
+ rightClick(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void;
2489
2445
  /**
2490
- * Clicks at global page coordinates, or at coordinates relative to an element.
2491
- * Dispatches a real CDP mouse click and therefore requires a real layout engine.
2446
+ * Clicks at page coordinates, or at coordinates relative to an element.
2447
+ * Requires a browser that renders layout.
2492
2448
  *
2493
2449
  * ```js
2494
- * I.clickXY(100, 200); // global coordinates
2450
+ * I.clickXY(100, 200); // page coordinates
2495
2451
  * I.clickXY('#area', 50, 30); // relative to #area
2496
2452
  * ```
2497
- * @param locator - element to click relative to, or a global X coordinate.
2498
- * @param [x] - X coordinate relative to element, or global Y coordinate if `locator` is a number.
2499
- * @param [y] - Y coordinate relative to element.
2453
+ * @param locator - element to click relative to, or the X page coordinate.
2454
+ * @param [x] - X coordinate relative to the element, or the Y page coordinate if `locator` is a number.
2455
+ * @param [y] - Y coordinate relative to the element.
2456
+ * @returns automatically synchronized promise through #recorder
2500
2457
  */
2501
- clickXY(locator: CodeceptJS.LocatorOrString | number, x?: number, y?: number): Promise<void>;
2458
+ clickXY(locator: CodeceptJS.LocatorOrString | number, x?: number, y?: number): void;
2502
2459
  /**
2503
- * Waits for an element to become visible (by default waits for `options.waitForTimeout` seconds).
2460
+ * Waits for an element to become visible on a page (by default waits for 1sec).
2461
+ * Element can be located by CSS or XPath.
2504
2462
  *
2505
2463
  * ```js
2506
- * I.waitForVisible('#popup', 5);
2464
+ * I.waitForVisible('#popup');
2507
2465
  * ```
2508
2466
  * @param locator - element located by CSS|XPath|strict locator.
2509
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2467
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2468
+ * @returns automatically synchronized promise through #recorder
2510
2469
  */
2511
- waitForVisible(locator: CodeceptJS.LocatorOrString, sec?: number): Promise<void>;
2470
+ waitForVisible(locator: CodeceptJS.LocatorOrString, sec?: number): void;
2512
2471
  /**
2513
- * Waits for an element to become invisible (by default waits for `options.waitForTimeout` seconds).
2472
+ * Waits for an element to be removed or become invisible on a page (by default waits for 1sec).
2473
+ * Element can be located by CSS or XPath.
2514
2474
  *
2515
2475
  * ```js
2516
- * I.waitForInvisible('#popup', 5);
2476
+ * I.waitForInvisible('#popup');
2517
2477
  * ```
2518
2478
  * @param locator - element located by CSS|XPath|strict locator.
2519
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2479
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2480
+ * @returns automatically synchronized promise through #recorder
2520
2481
  */
2521
- waitForInvisible(locator: CodeceptJS.LocatorOrString, sec?: number): Promise<void>;
2482
+ waitForInvisible(locator: CodeceptJS.LocatorOrString, sec?: number): void;
2522
2483
  /**
2523
- * Waits for an element to be hidden. Alias of `waitForInvisible`.
2484
+ * Waits for an element to hide (by default waits for 1sec).
2485
+ * Element can be located by CSS or XPath.
2486
+ *
2487
+ * ```js
2488
+ * I.waitToHide('#popup');
2489
+ * ```
2524
2490
  * @param locator - element located by CSS|XPath|strict locator.
2525
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2491
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2492
+ * @returns automatically synchronized promise through #recorder
2526
2493
  */
2527
- waitToHide(locator: CodeceptJS.LocatorOrString, sec?: number): Promise<void>;
2494
+ waitToHide(locator: CodeceptJS.LocatorOrString, sec?: number): void;
2528
2495
  /**
2529
- * Waits for an element to be removed from the DOM (by default waits for `options.waitForTimeout` seconds).
2496
+ * Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
2497
+ * Element can be located by CSS or XPath.
2530
2498
  *
2531
2499
  * ```js
2532
- * I.waitForDetached('#popup', 5);
2500
+ * I.waitForDetached('#popup');
2533
2501
  * ```
2534
2502
  * @param locator - element located by CSS|XPath|strict locator.
2535
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2503
+ * @param [sec = 1] - (optional, `1` by default) time in seconds to wait
2504
+ * @returns automatically synchronized promise through #recorder
2536
2505
  */
2537
- waitForDetached(locator: CodeceptJS.LocatorOrString, sec?: number): Promise<void>;
2506
+ waitForDetached(locator: CodeceptJS.LocatorOrString, sec?: number): void;
2538
2507
  /**
2539
- * Checks that a cookie with the given name is set.
2508
+ * Checks that cookie with given name exists.
2509
+ *
2510
+ * ```js
2511
+ * I.seeCookie('Auth');
2512
+ * ```
2540
2513
  * @param name - cookie name.
2514
+ * @returns automatically synchronized promise through #recorder
2541
2515
  */
2542
- seeCookie(name: string): Promise<void>;
2516
+ seeCookie(name: string): void;
2543
2517
  /**
2544
- * Checks that a cookie with the given name is not set.
2518
+ * Checks that cookie with given name does not exist.
2519
+ *
2520
+ * ```js
2521
+ * I.dontSeeCookie('auth'); // no auth cookie
2522
+ * ```
2545
2523
  * @param name - cookie name.
2524
+ * @returns automatically synchronized promise through #recorder
2546
2525
  */
2547
- dontSeeCookie(name: string): Promise<void>;
2526
+ dontSeeCookie(name: string): void;
2548
2527
  /**
2549
- * Waits for a cookie with the given name to be set (by default waits for `options.waitForTimeout` seconds).
2528
+ * Waits for the specified cookie in the cookies.
2550
2529
  *
2551
2530
  * ```js
2552
- * I.waitForCookie('auth', 5);
2531
+ * I.waitForCookie("token");
2553
2532
  * ```
2554
- * @param name - cookie name.
2555
- * @param [sec = null] - (optional, `options.waitForTimeout` by default) time in seconds to wait
2533
+ * @param name - expected cookie name.
2534
+ * @param [sec = 3] - (optional, `3` by default) time in seconds to wait
2535
+ * @returns automatically synchronized promise through #recorder
2556
2536
  */
2557
- waitForCookie(name: string, sec?: number): Promise<void>;
2537
+ waitForCookie(name: string, sec?: number): void;
2558
2538
  /**
2559
- * Retrieves the inner HTML from an element located by CSS or XPath.
2539
+ * Retrieves the innerHTML from an element located by CSS or XPath and returns it to test.
2540
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
2560
2541
  * If more than one element is found - HTML of first element is returned.
2561
2542
  *
2562
2543
  * ```js
2563
2544
  * let postHTML = await I.grabHTMLFrom('#post');
2564
2545
  * ```
2565
- * @param locator - element located by CSS|XPath|strict locator.
2546
+ * @param element - located by CSS|XPath|strict locator.
2566
2547
  * @returns HTML code for an element
2567
2548
  */
2568
- grabHTMLFrom(locator: CodeceptJS.LocatorOrString): Promise<string>;
2549
+ grabHTMLFrom(element: CodeceptJS.LocatorOrString): Promise<string>;
2569
2550
  /**
2570
- * Retrieves the inner HTML from elements located by CSS or XPath.
2551
+ * Retrieves all the innerHTML from elements located by CSS or XPath and returns it to test.
2552
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
2571
2553
  *
2572
2554
  * ```js
2573
2555
  * let postHTMLs = await I.grabHTMLFromAll('.post');
2574
2556
  * ```
2575
- * @param locator - element located by CSS|XPath|strict locator.
2576
- * @returns HTML code for matched elements
2557
+ * @param element - located by CSS|XPath|strict locator.
2558
+ * @returns HTML code for an element
2577
2559
  */
2578
- grabHTMLFromAll(locator: CodeceptJS.LocatorOrString): Promise<string[]>;
2560
+ grabHTMLFromAll(element: CodeceptJS.LocatorOrString): Promise<string[]>;
2579
2561
  /**
2580
- * Executes an asynchronous script (callback-style, in the same way `window.setTimeout` works)
2581
- * in the browser context and returns the value passed to `done`.
2562
+ * Executes async script on page.
2563
+ * Provided function should execute a passed callback (as first argument) to signal it is finished.
2564
+ *
2565
+ * Example: In Vue.js to make components completely rendered we are waiting for [nextTick](https://vuejs.org/v2/api/#Vue-nextTick).
2582
2566
  *
2583
2567
  * ```js
2584
- * const val = await I.executeAsyncScript(function(val, done) {
2585
- * setTimeout(() => done(val + 1), 100)
2586
- * }, 5)
2568
+ * I.executeAsyncScript(function(done) {
2569
+ * Vue.nextTick(done); // waiting for next tick
2570
+ * });
2571
+ * ```
2572
+ *
2573
+ * By passing value to `done()` function you can return values.
2574
+ * Additional arguments can be passed as well, while `done` function is always last parameter in arguments list.
2575
+ *
2576
+ * ```js
2577
+ * let val = await I.executeAsyncScript(function(url, done) {
2578
+ * // in browser context
2579
+ * $.ajax(url, { success: (data) => done(data); }
2580
+ * }, 'http://ajax.callback.url/');
2587
2581
  * ```
2588
- * @param fn - an asynchronous function to be executed in the browser context; its last argument is a `done` callback.
2589
- * @param args - arguments to pass into the function (before `done`).
2590
- * @returns the value passed to `done`.
2582
+ * @param fn - function to be executed in browser context.
2583
+ * @param args - to be passed to function.
2584
+ * @returns script return value
2591
2585
  */
2592
- executeAsyncScript(fn: (...params: any[]) => any, ...args: any[]): Promise<any>;
2586
+ executeAsyncScript(fn: string | ((...params: any[]) => any), ...args: any[]): Promise<any>;
2593
2587
  /**
2594
- * Starts recording network traffic via CDP's `Network.requestWillBeSent`/`responseReceived`
2595
- * events, in the same shape (`{url, method, requestHeaders, requestPostData, response}` per
2596
- * request, `response` a promise of `{url(), status(), statusText(), body()}`) the shared
2597
- * `lib/helper/network` actions expect from Puppeteer/Playwright. The CDP listeners are
2598
- * installed once (lazily) and left in place afterwards, since `CDPConnection` has no listener
2599
- * removal and `this.cdp` is reused across tests; they filter by `this.sessionId`, so only the
2600
- * currently active test/page's requests are recorded.
2588
+ * Starts recording the network traffics.
2589
+ * This also resets recorded network requests.
2601
2590
  *
2602
2591
  * ```js
2603
2592
  * I.startRecordingTraffic();
2604
2593
  * ```
2594
+ * @returns automatically synchronized promise through #recorder
2605
2595
  */
2606
- startRecordingTraffic(): Promise<void>;
2607
- /**
2608
- * `Network.requestWillBeSent` handler, pushed into `this.requests` when it belongs to the
2609
- * currently active session and recording is on.
2610
- */
2611
- protected _onTrafficRequest(): void;
2612
- /**
2613
- * `Network.responseReceived` handler, resolving the matching pending `response` promise pushed
2614
- * by `_onTrafficRequest` with a Puppeteer-`HTTPResponse`-like object.
2615
- */
2616
- protected _onTrafficResponse(): void;
2617
- /**
2618
- * `Network.loadingFailed` handler, resolving a still-pending `response` promise to `null`
2619
- * (matching Puppeteer's `request.response()` for a failed request) so `grabRecordedNetworkTraffics`
2620
- * never awaits a promise that would otherwise never settle.
2621
- */
2622
- protected _onTrafficLoadingFailed(): void;
2596
+ startRecordingTraffic(): void;
2623
2597
  /**
2624
2598
  * Grab the recording network traffics
2625
2599
  *
@@ -2695,8 +2669,7 @@ declare namespace CodeceptJS {
2695
2669
  url: string | RegExp;
2696
2670
  }): void;
2697
2671
  /**
2698
- * Stops recording network traffic started by `startRecordingTraffic`. Already-recorded requests
2699
- * in `this.requests` are kept; only new requests stop being appended.
2672
+ * Stops recording of network traffic. Recorded traffic is not flashed.
2700
2673
  *
2701
2674
  * ```js
2702
2675
  * I.stopRecordingTraffic();
@@ -2712,46 +2685,135 @@ declare namespace CodeceptJS {
2712
2685
  */
2713
2686
  flushNetworkTraffics(): void;
2714
2687
  /**
2715
- * Starts recording a CDP `Page.startScreencast` session for the current test's target: frames
2716
- * arrive as `Page.screencastFrame` events, are acknowledged immediately (`Page.screencastFrameAck`,
2717
- * required or the browser stops sending more), and buffered in `this._screencastFrames`. The
2718
- * underlying `Page.screencastFrame` listener is installed once (lazily) and left in place, like
2719
- * `startRecordingTraffic`'s listeners, since `CDPConnection` has no listener-removal API; it
2720
- * filters by `this.sessionId` so only the currently active test's frames are buffered. Call
2721
- * `stopScreencast` to end the capture and assemble the buffered frames into an APNG.
2688
+ * Starts recording a video of the page. Stop it with `stopScreencast`.
2689
+ * Usually enabled through the `screencast` plugin rather than called directly.
2722
2690
  *
2723
2691
  * ```js
2724
2692
  * I.startScreencast();
2725
2693
  * ```
2726
- * @param [options] - {maxWidth: number, maxHeight: number, quality: number, everyNthFrame: number} — CDP `Page.startScreencast` pass-throughs. `format` is always `'png'`.
2694
+ * @param [options] - `{ maxWidth, maxHeight, quality, everyNthFrame }`
2695
+ * @returns automatically synchronized promise through #recorder
2696
+ */
2697
+ startScreencast(options?: any): void;
2698
+ /**
2699
+ * Stops the recording started by `startScreencast` and returns it as an animated PNG.
2700
+ *
2701
+ * ```js
2702
+ * const video = await I.stopScreencast();
2703
+ * ```
2704
+ * @param [options] - `{ lastFrameDelayMs }`: how long the last frame is shown, in milliseconds (1000 by default).
2705
+ * @returns APNG data, or `null` if no frames were recorded.
2727
2706
  */
2728
- startScreencast(options?: any): Promise<void>;
2707
+ stopScreencast(options?: any): Promise<Buffer | null>;
2708
+ }
2709
+ /**
2710
+ * Asserts statements about the current page with a decision model.
2711
+ *
2712
+ * Decision models (like [Jev](https://openrouter.ai/typesafe/jev-1.13) or [Clef](https://openrouter.ai/cloudflare/clef))
2713
+ * do not generate text. They read the page state and return the probability that a statement is true.
2714
+ * A statement passes when its probability reaches the configured `confidence`.
2715
+ *
2716
+ * ```js
2717
+ * I.decide('top level navigation is available');
2718
+ * I.decide([
2719
+ * 'checkout form has all required fields',
2720
+ * 'success message is shown',
2721
+ * 'submit button enabled',
2722
+ * 'cancel button present',
2723
+ * ]);
2724
+ * I.decideVisually('sidebar is shown');
2725
+ * ```
2726
+ *
2727
+ * The model receives the page URL, title and ARIA snapshot.
2728
+ * Helpers without ARIA snapshots (anything but Playwright) send minified HTML instead.
2729
+ * `decideVisually` also sends a screenshot, so it requires a model with image input.
2730
+ *
2731
+ * This helper must be enabled together with a web helper (Playwright, Puppeteer, WebDriver).
2732
+ *
2733
+ * ## Configuration
2734
+ *
2735
+ * Decision model is created with the OpenRouter provider from `@openrouter/ai-sdk-provider`
2736
+ * and configured in the `ai.decisionModel` section of the config:
2737
+ *
2738
+ * ```js
2739
+ * import { createOpenRouter } from '@openrouter/ai-sdk-provider'
2740
+ *
2741
+ * const openrouter = createOpenRouter({
2742
+ * apiKey: process.env.OPENROUTER_API_KEY,
2743
+ * })
2744
+ *
2745
+ * export default {
2746
+ * ai: {
2747
+ * decisionModel: {
2748
+ * model: openrouter.evaluationModel('typesafe/jev-1.13'),
2749
+ * confidence: 0.8,
2750
+ * },
2751
+ * },
2752
+ * helpers: {
2753
+ * Playwright: { url: 'http://localhost' },
2754
+ * Decision: {},
2755
+ * },
2756
+ * }
2757
+ * ```
2758
+ *
2759
+ * * `model` - decision model used by `decide`.
2760
+ * * `confidence` (default: `0.7`) - minimal probability, between 0 and 1, for a statement to pass.
2761
+ * * `timeout` (default: `15000`) - request timeout in ms.
2762
+ * * `maxLength` (default: `12000`) - maximal length of ARIA snapshot or HTML sent to the model.
2763
+ *
2764
+ * `decideVisually` uses a separate decision model with image input, configured as `visualModel`:
2765
+ *
2766
+ * ```js
2767
+ * decisionModel: {
2768
+ * model: openrouter.evaluationModel('typesafe/jev-1.13'),
2769
+ * visualModel: openrouter.evaluationModel('cloudflare/clef'),
2770
+ * },
2771
+ * ```
2772
+ *
2773
+ * The helper has one option:
2774
+ *
2775
+ * * `mode` (default: `assert`) - how decisions are executed:
2776
+ * * `assert` - request the model and fail the step when a statement is not confirmed.
2777
+ * * `report` - request the model but never fail, even on API errors. Results and errors are added to the step as a comment.
2778
+ * * `skip` - do not request the model, every decision passes.
2779
+ *
2780
+ * ```js
2781
+ * Decision: { mode: process.env.CI ? 'assert' : 'skip' }
2782
+ * ```
2783
+ *
2784
+ * Decisions work without the `--ai` flag.
2785
+ * Browse all decision models at [OpenRouter](https://openrouter.ai/models?output_modalities=decisions).
2786
+ *
2787
+ * ## Methods
2788
+ */
2789
+ class Decision {
2729
2790
  /**
2730
- * `Page.screencastFrame` handler: ignores frames from a session other than the currently active
2731
- * one (stale frames from a previous test, since the listener is never removed), acknowledges the
2732
- * frame so the browser keeps sending more, and buffers `{data, timestamp}` for `stopScreencast`
2733
- * to assemble.
2791
+ * Asserts that a statement (or each of statements) is true for the current page.
2792
+ * The decision model receives page URL, title and ARIA snapshot.
2793
+ * Multiple statements are checked in a single request and all of them must pass.
2794
+ *
2795
+ * ```js
2796
+ * I.decide('user is logged in');
2797
+ * I.decide(['submit button enabled', 'cancel button present']);
2798
+ * const probability = await I.decide('cart is empty');
2799
+ * ```
2800
+ * @param statements - statement or list of statements to verify.
2801
+ * @returns probability of each statement, `undefined` in `skip` mode.
2734
2802
  */
2735
- protected _onScreencastFrame(): void;
2803
+ decide(statements: string | string[]): Promise<number | number[] | undefined>;
2736
2804
  /**
2737
- * Stops the screencast started by `startScreencast` and assembles the buffered frames into a
2738
- * single APNG (Animated PNG) file, returned as a Buffer. Frame delays are derived from the CDP
2739
- * frame metadata's `timestamp` deltas (frame arrival is activity-driven — Obscura and Chrome both
2740
- * only emit a frame on damage — so this reproduces the actual pacing of what happened, not a
2741
- * fixed frame rate); the last frame is held for `options.lastFrameDelayMs` (default 1000ms) since
2742
- * it has no "next" frame to derive a delay from. Every frame is checked for the PNG signature
2743
- * before assembly — CDP's `format: 'png'` is honored by both Chrome and Obscura (verified
2744
- * directly), but if some other engine ever sends a different format regardless, this reports it
2745
- * via `debugSection` and returns `null` instead of muxing a broken file. Returns `null` if no
2746
- * frames were captured (screencast never started, or stopped immediately after starting).
2805
+ * Asserts that a statement (or each of statements) is true for the current page using a screenshot.
2806
+ * The decision model receives page URL, title, ARIA snapshot and a screenshot.
2807
+ * Requires `visualModel` with image input. Experimental.
2747
2808
  *
2748
2809
  * ```js
2749
- * const apngBuffer = await I.stopScreencast();
2810
+ * I.decideVisually('sidebar is shown');
2811
+ * I.decideVisually(['logo is in the header', 'page uses dark theme']);
2750
2812
  * ```
2751
- * @param [options] - {lastFrameDelayMs: number} — hold time in milliseconds for the final frame (default 1000).
2752
- * @returns a Buffer with the assembled APNG, or null if there was nothing to assemble.
2813
+ * @param statements - statement or list of statements to verify.
2814
+ * @returns probability of each statement, `undefined` in `skip` mode.
2753
2815
  */
2754
- stopScreencast(options?: any): Promise<object>;
2816
+ decideVisually(statements: string | string[]): Promise<number | number[] | undefined>;
2755
2817
  }
2756
2818
  /**
2757
2819
  * Helper for testing filesystem.
@@ -3331,15 +3393,14 @@ declare namespace CodeceptJS {
3331
3393
  /**
3332
3394
  * ## Configuration
3333
3395
  *
3334
- * This helper should be configured in codecept.conf.js. It accepts everything `CDPBrowser`
3335
- * accepts (see its config table), plus:
3396
+ * This helper should be configured in codecept.conf.js
3336
3397
  * @property [url = http://localhost] - base URL for tests
3337
3398
  * @property [accountId] - Cloudflare account ID; defaults to CF_ACCOUNT_ID env var
3338
3399
  * @property [apiToken] - Cloudflare API token; defaults to CF_API_TOKEN env var
3339
3400
  * @property [keepAlive = 240000] - session keep-alive time in milliseconds
3340
3401
  * @property [apiBase = https://api.cloudflare.com/client/v4] - Cloudflare API base URL
3341
- * @property [input = cdp] - input method for user actions; defaults to 'cdp' for Kitesurf's real layout engine, but can be overridden
3342
- * @property [capabilities] - pre-configured capabilities; Kitesurf uses { layout: 'real', screenshot: true }
3402
+ * @property [input = cdp] - how actions are dispatched: `cdp` (real mouse and keyboard events) or `synthetic` (DOM events).
3403
+ * @property [capabilities] - browser capabilities; Kitesurf sets `{ layout: 'real', screenshot: true }`.
3343
3404
  */
3344
3405
  type KitesurfConfig = {
3345
3406
  url?: string;
@@ -3406,55 +3467,146 @@ declare namespace CodeceptJS {
3406
3467
  */
3407
3468
  class Kitesurf {
3408
3469
  constructor(config: KitesurfConfig);
3409
- /**
3410
- * Acquires a Kitesurf browser session from the Cloudflare Browser Run API and resolves it to
3411
- * the `wss://` debugger URL `CDPConnection` connects to. Overrides `CDPBrowser._resolveEndpoint`,
3412
- * which resolves a fixed local endpoint instead of provisioning a cloud session per test.
3413
- * @returns a `wss://` debugger URL ready to be passed to `CDPConnection`.
3414
- */
3415
- protected _resolveEndpoint(): Promise<string>;
3416
- /**
3417
- * Closes the target as `CDPBrowser._finishTest` does, then releases the cloud session acquired
3418
- * in `_resolveEndpoint` via the Cloudflare API so it does not linger for the full `keepAlive`
3419
- * window. The release runs in a `finally` so a rejection while closing the CDP connection still
3420
- * frees the cloud session instead of leaving the browser alive until `keepAlive` expires; the
3421
- * session id is cleared before the request, so a repeated call never releases it twice.
3422
- */
3423
- protected _finishTest(): void;
3424
3470
  }
3425
3471
  /**
3426
3472
  * ## Configuration
3427
3473
  *
3428
- * This helper should be configured in codecept.conf.js. It accepts everything `CDPBrowser`
3429
- * accepts (see its config table), plus:
3474
+ * This helper should be configured in codecept.conf.js
3430
3475
  * @property [endpoint] - explicit CDP endpoint. Setting this switches the helper to ATTACH
3431
3476
  * mode: it only connects, and never spawns or kills a process, no matter what else is configured.
3432
3477
  * Leave it unset for SELF-MANAGED mode (see below).
3433
- * @property [binaryPath] - path to the `obscura` executable, used in SELF-MANAGED mode
3434
- * (`endpoint` unset). Checked before `OBSCURA_PATH` and `PATH`.
3435
- * @property [port] - port `obscura serve` listens on, in SELF-MANAGED mode. When unset, a
3478
+ * @property [binaryPath] - path to the `lightpanda` executable, used in SELF-MANAGED mode
3479
+ * (`endpoint` unset). Checked before `LIGHTPANDA_PATH` and `PATH`.
3480
+ * @property [port] - port `lightpanda serve` listens on, in SELF-MANAGED mode. When unset, a
3436
3481
  * free port is picked automatically, which is what makes `run-workers` collision-free — every
3437
3482
  * worker gets its own instance on its own port with zero config.
3438
- * @property [serverStartTimeout = 15000] - milliseconds to wait for a spawned `obscura serve`
3483
+ * @property [serverStartTimeout = 15000] - milliseconds to wait for a spawned `lightpanda serve`
3439
3484
  * to answer `/json/version` before `_connect` gives up.
3440
3485
  */
3441
- type ObscuraConfig = {
3486
+ type LightpandaConfig = {
3442
3487
  endpoint?: string;
3443
3488
  binaryPath?: string;
3444
3489
  port?: number;
3445
3490
  serverStartTimeout?: number;
3446
3491
  };
3447
3492
  /**
3448
- * Obscura drives [Obscura](https://github.com/h4ckf0r0day/obscura), a minimal headless
3449
- * browser exposed over the Chrome DevTools Protocol. From v0.2.0, default release builds ship a
3450
- * real rendering engine (layout, paint, screenshots); `-no-render` variants and v0.1.x builds keep
3451
- * the original single-V8-isolate, nothing-rendered mode. This helper does not hardcode which mode a
3452
- * given binary is in — `CDPBrowser._probeCapabilities` detects `layout`/`screenshot` per binary at
3453
- * runtime, so the same helper works against either.
3493
+ * Lightpanda drives [Lightpanda](https://lightpanda.io), a headless browser written from scratch
3494
+ * for automation, exposed over the Chrome DevTools Protocol. It executes real JavaScript in V8 and
3495
+ * implements the DOM and Web APIs, but has no graphical rendering engine: nothing is ever painted,
3496
+ * so there are no screenshots.
3454
3497
  *
3455
3498
  * This helper is a thin `CDPBrowser` subclass: it changes nothing about how locating or acting on
3456
- * elements works, it only pins the config presets Obscura requires and manages the `obscura serve`
3457
- * process lifecycle, the same way Playwright manages its own browser process.
3499
+ * elements works, it only pins the config presets Lightpanda requires and manages the
3500
+ * `lightpanda serve` process lifecycle, the same way Playwright manages its own browser process.
3501
+ *
3502
+ * > Lightpanda support is experimental. Pin the browser version in CI and keep a
3503
+ * > Playwright/WebDriver job for browser-compatibility coverage.
3504
+ *
3505
+ * ## Modes
3506
+ *
3507
+ * - **ATTACH** — `endpoint` is set explicitly in the config. The helper only connects to it; it
3508
+ * never spawns or kills anything, no matter what `binaryPath`/`port` are set to.
3509
+ * - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
3510
+ * the config, then the `LIGHTPANDA_PATH` environment variable, then `lightpanda` on `PATH`. The
3511
+ * helper spawns `lightpanda serve --host 127.0.0.1 --port <port>` (`port` from the config, or a
3512
+ * free port picked automatically), waits for it to answer, connects, and kills it in
3513
+ * `_finishTest`.
3514
+ * - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
3515
+ * answers `http://127.0.0.1:9222/json/version` (e.g. `lightpanda serve` started by hand, or the
3516
+ * `lightpanda/browser` Docker image). The helper attaches to it and never kills it. If neither a
3517
+ * binary nor a running server on :9222 can be found, the helper throws a loud, actionable error.
3518
+ *
3519
+ * ## Install
3520
+ *
3521
+ * Follow the [official installation instructions](https://lightpanda.io/docs/open-source/installation),
3522
+ * then put `lightpanda` on your `PATH`, or point `binaryPath`/`LIGHTPANDA_PATH` at it. The helper
3523
+ * then launches and tears it down automatically.
3524
+ *
3525
+ * Lightpanda sends usage telemetry by default. This helper always spawns it with
3526
+ * `LIGHTPANDA_DISABLE_TELEMETRY=true`; set that variable yourself when you start the server by hand.
3527
+ *
3528
+ * Lightpanda is licensed under AGPL-3.0. It runs as a separate process that CodeceptJS talks to
3529
+ * over a WebSocket, so it does not change the license of CodeceptJS or of your tests.
3530
+ *
3531
+ * ## Config presets
3532
+ *
3533
+ * These are set automatically and only need overriding for unusual setups:
3534
+ *
3535
+ * | option | value | why |
3536
+ * | --- | --- | --- |
3537
+ * | `input` | `synthetic` | nothing is painted, so coordinates are not hit-tested; `click` always takes the `forceClick` path |
3538
+ * | `xpathPolyfill` | `auto` | probed per binary/page |
3539
+ * | `capabilities.layout` | `real` | Lightpanda computes visibility-related styles and element boxes without painting, which is enough for `seeElement` and the `waitForVisible` family; it is pinned because the runtime layout probe cannot run on Lightpanda's `about:blank` |
3540
+ * | `capabilities.screenshot` | `false` | there is no rendering engine |
3541
+ *
3542
+ * ## Limitations
3543
+ *
3544
+ * - No screenshots and no screencast: `saveScreenshot` throws.
3545
+ * - No frames or popups.
3546
+ * - No scrolling: scroll positions always stay at 0.
3547
+ * - Computed styles cover what visibility checks need (`display`, `visibility`, `opacity`,
3548
+ * `pointer-events`); `grabCssPropertyFrom` and `seeCssPropertiesOnElements` are unreliable for
3549
+ * other properties.
3550
+ * - No coordinate-based input (`clickXY`).
3551
+ * - No clipboard access.
3552
+ * - Some rich text editors (TinyMCE, Trix, Monaco) never finish initialising.
3553
+ *
3554
+ * <!-- configuration -->
3555
+ *
3556
+ * ## Example
3557
+ *
3558
+ * ```js
3559
+ * // inside codecept.conf.js — SELF-LAUNCH mode (recommended): the helper finds/starts/stops
3560
+ * // lightpanda serve on its own, on a free port. Ideal for run-workers: every worker gets its
3561
+ * // own instance with no config.
3562
+ * {
3563
+ * helpers: {
3564
+ * Lightpanda: {
3565
+ * url: 'http://localhost',
3566
+ * }
3567
+ * }
3568
+ * }
3569
+ * ```
3570
+ *
3571
+ * ```js
3572
+ * // ATTACH mode — connect to a Lightpanda instance you manage yourself (remote host, container, etc.)
3573
+ * {
3574
+ * helpers: {
3575
+ * Lightpanda: {
3576
+ * url: 'http://localhost',
3577
+ * endpoint: 'http://127.0.0.1:9222',
3578
+ * }
3579
+ * }
3580
+ * }
3581
+ * ```
3582
+ *
3583
+ * ## Methods
3584
+ */
3585
+ class Lightpanda {
3586
+ constructor(config: LightpandaConfig);
3587
+ }
3588
+ /**
3589
+ * ## Configuration
3590
+ *
3591
+ * This helper should be configured in codecept.conf.js
3592
+ * @property [endpoint] - connect to a running Obscura instead of starting one (ATTACH mode).
3593
+ * @property [binaryPath] - path to the `obscura` executable. Checked before `OBSCURA_PATH` and `PATH`.
3594
+ * @property [port] - port for `obscura serve`. A free port is picked when unset, so parallel workers never collide.
3595
+ * @property [serverStartTimeout = 15000] - how long to wait for `obscura serve` to start, in milliseconds.
3596
+ */
3597
+ type ObscuraConfig = {
3598
+ endpoint?: string;
3599
+ binaryPath?: string;
3600
+ port?: number;
3601
+ serverStartTimeout?: number;
3602
+ };
3603
+ /**
3604
+ * Obscura drives [Obscura](https://github.com/h4ckf0r0day/obscura), a lightweight headless
3605
+ * browser controlled over the Chrome DevTools Protocol. Default builds from v0.2.0 render pages
3606
+ * (layout, screenshots); `-no-render` builds and v0.1.x run JavaScript and the DOM only. The helper
3607
+ * detects which build it runs against, so the same config works for both.
3608
+ *
3609
+ * The helper starts and stops `obscura serve` for you, the same way Playwright manages its browser.
3458
3610
  *
3459
3611
  * > Obscura support is experimental in CodeceptJS 4.2. Pin the browser version in CI and keep a
3460
3612
  * > Playwright/WebDriver job for browser-compatibility coverage.
@@ -3474,8 +3626,8 @@ declare namespace CodeceptJS {
3474
3626
  * - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
3475
3627
  * the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
3476
3628
  * spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
3477
- * the config, or a free port picked automatically), waits for it to answer, connects, and kills
3478
- * it in `_finishTest`.
3629
+ * the config, or a free port picked automatically), waits for it to answer, connects, and stops
3630
+ * it when tests finish.
3479
3631
  * - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
3480
3632
  * answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
3481
3633
  * before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -3514,13 +3666,11 @@ declare namespace CodeceptJS {
3514
3666
  *
3515
3667
  * | option | value | why |
3516
3668
  * | --- | --- | --- |
3517
- * | `input` | `synthetic` | coordinate-click navigation is unreliable over CDP on Obscura even on rendering builds (no `frameNavigated` event, stale `page.url()`); `click` always takes the `forceClick` path — on Obscura, `click` and `forceClick` are the same thing |
3518
- * | `xpathPolyfill` | `auto` | probed per binary/page: Obscura's native `document.evaluate` still doesn't support attribute selection or `not()`, so the polyfill is used until that lands |
3669
+ * | `input` | `synthetic` | clicks that navigate are unreliable in Obscura, so `click` behaves like `forceClick` |
3670
+ * | `xpathPolyfill` | `auto` | Obscura's XPath lacks attribute selection and `not()`, so the polyfill is used when needed |
3519
3671
  *
3520
- * `capabilities.layout`/`capabilities.screenshot`/`capabilities.xpath` are intentionally left
3521
- * unset here — `CDPBrowser._probeCapabilities` detects them at runtime from the actual binary
3522
- * (`'real'`/`true` on v0.2.0+ default builds, `'none'`/`false` on `-no-render` builds and v0.1.x).
3523
- * Set them explicitly in your own config to skip probing or to force a mode.
3672
+ * `capabilities` are detected at runtime from the Obscura build. Set them in your config to skip
3673
+ * detection or to force a mode.
3524
3674
  *
3525
3675
  * ## Limitations
3526
3676
  *
@@ -3567,63 +3717,6 @@ declare namespace CodeceptJS {
3567
3717
  */
3568
3718
  class Obscura {
3569
3719
  constructor(config: ObscuraConfig);
3570
- /**
3571
- * In ATTACH mode, connects exactly as `CDPBrowser._connect` would. In SELF-MANAGED mode,
3572
- * resolves and spawns `obscura serve` (or courtesy-attaches to an already-running one on
3573
- * :9222) exactly once via `_resolveSelfManaged`, then connects.
3574
- *
3575
- * A spawn failure (e.g. a bad binary) is delivered asynchronously by Node as an `error`
3576
- * event; it is recorded on `this.serverError` and surfaced as a rejection from `_waitForServer`
3577
- * instead of crashing the process as an uncaught exception.
3578
- */
3579
- protected _connect(): void;
3580
- /**
3581
- * Resolves how to reach Obscura when no explicit `endpoint` was configured, trying, in order:
3582
- * spawn a binary (`binaryPath` config, then `OBSCURA_PATH` env, then `obscura` on `PATH`),
3583
- * courtesy-attach to `http://127.0.0.1:9222` if something already answers there, or throw a
3584
- * loud, actionable error. Sets `this.options.endpoint` as a side effect.
3585
- */
3586
- protected _resolveSelfManaged(): void;
3587
- /**
3588
- * Resolves the `obscura` binary to spawn, in priority order: `options.binaryPath`, then the
3589
- * `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The `PATH` lookup walks the
3590
- * directories itself instead of shelling out to `which`, which does not exist on Windows: on
3591
- * Windows every `PATHEXT` suffix is tried, so an `obscura.exe` on `PATH` is found too.
3592
- * @returns an absolute or relative path to the binary, or null if none resolved.
3593
- */
3594
- protected _resolveBinary(): string | null;
3595
- /**
3596
- * Picks a free TCP port on 127.0.0.1 by briefly listening on port 0 and reading back the OS-assigned
3597
- * port. Used as the SELF-LAUNCH default when `options.port` isn't explicitly set, so multiple
3598
- * `run-workers` workers never collide on the same port.
3599
- * @returns a free port.
3600
- */
3601
- protected _findFreePort(): Promise<number>;
3602
- /**
3603
- * Probes a `/json/version`-style URL with a short timeout, used for the COURTESY-ATTACH check.
3604
- * @returns true if the URL answered.
3605
- */
3606
- protected _probeUp(url: string): Promise<boolean>;
3607
- /**
3608
- * Polls `http://127.0.0.1:<port>/json/version` until `obscura serve` responds, `this.serverError`
3609
- * is set by the spawned process' `error` event, or `options.serverStartTimeout` elapses. The
3610
- * process typically comes up within tens of milliseconds — a 20ms retry interval (down from a
3611
- * previous 200ms) keeps the wasted tail after the server is actually ready small, since this cost
3612
- * is paid once per run and counts directly toward real-world startup latency.
3613
- */
3614
- protected _waitForServer(): void;
3615
- /**
3616
- * Closes the CDP connection (via `CDPBrowser._finishTest`), then kills the `obscura serve`
3617
- * process spawned by `_connect`, if any (never runs in ATTACH or COURTESY-ATTACH mode, since
3618
- * `this.serverProcess` is only ever set in SELF-LAUNCH mode). Runs in a `finally` so the process
3619
- * is always reaped even if closing the CDP connection throws. Sends `SIGTERM` first and waits for
3620
- * the process to exit; a process that ignores `SIGTERM` is escalated to `SIGKILL` after 5s. The
3621
- * promise only resolves once the child has actually exited (confirmed via the `exit` event, not
3622
- * merely once `SIGKILL` was sent — the kernel needs a moment to reap it), with a final safety-net
3623
- * timeout so a stuck child can never keep the event loop alive even if that confirmation is
3624
- * somehow lost.
3625
- */
3626
- protected _finishTest(): void;
3627
3720
  }
3628
3721
  /**
3629
3722
  * ## Configuration
@@ -5196,6 +5289,58 @@ declare namespace CodeceptJS {
5196
5289
  * @param [cookie = null] - (optional, `null` by default) cookie name
5197
5290
  */
5198
5291
  clearCookie(cookie?: string): void;
5292
+ /**
5293
+ * Checks that the system clipboard contains the given text.
5294
+ *
5295
+ * ```js
5296
+ * I.click('Copy to clipboard');
5297
+ * I.seeInClipboard('https://codecept.io');
5298
+ * ```
5299
+ *
5300
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5301
+ * in Chromium-based browsers, where read access is granted automatically.
5302
+ * @param text - value to check.
5303
+ * @returns automatically synchronized promise through #recorder
5304
+ */
5305
+ seeInClipboard(text: string): void;
5306
+ /**
5307
+ * Checks that the system clipboard is equal to the given text.
5308
+ *
5309
+ * ```js
5310
+ * I.click('Copy to clipboard');
5311
+ * I.seeClipboardEquals('https://codecept.io');
5312
+ * ```
5313
+ *
5314
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5315
+ * in Chromium-based browsers, where read access is granted automatically.
5316
+ * @param text - value to check.
5317
+ * @returns automatically synchronized promise through #recorder
5318
+ */
5319
+ seeClipboardEquals(text: string): void;
5320
+ /**
5321
+ * Grabs the text content of the system clipboard and returns it to test.
5322
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
5323
+ *
5324
+ * ```js
5325
+ * I.click('Copy to clipboard');
5326
+ * let url = await I.grabFromClipboard();
5327
+ * ```
5328
+ *
5329
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5330
+ * in Chromium-based browsers, where read access is granted automatically.
5331
+ * @returns the system clipboard contents.
5332
+ */
5333
+ grabFromClipboard(): Promise<string>;
5334
+ /**
5335
+ * Clears the system clipboard.
5336
+ *
5337
+ * ```js
5338
+ * I.clearClipboard();
5339
+ * I.seeClipboardEquals('');
5340
+ * ```
5341
+ * @returns automatically synchronized promise through #recorder
5342
+ */
5343
+ clearClipboard(): void;
5199
5344
  /**
5200
5345
  * Executes a script on the page:
5201
5346
  *
@@ -7366,6 +7511,58 @@ declare namespace CodeceptJS {
7366
7511
  * @param [cookie = null] - (optional, `null` by default) cookie name
7367
7512
  */
7368
7513
  clearCookie(cookie?: string): void;
7514
+ /**
7515
+ * Checks that the system clipboard contains the given text.
7516
+ *
7517
+ * ```js
7518
+ * I.click('Copy to clipboard');
7519
+ * I.seeInClipboard('https://codecept.io');
7520
+ * ```
7521
+ *
7522
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7523
+ * in Chromium-based browsers, where read access is granted automatically.
7524
+ * @param text - value to check.
7525
+ * @returns automatically synchronized promise through #recorder
7526
+ */
7527
+ seeInClipboard(text: string): void;
7528
+ /**
7529
+ * Checks that the system clipboard is equal to the given text.
7530
+ *
7531
+ * ```js
7532
+ * I.click('Copy to clipboard');
7533
+ * I.seeClipboardEquals('https://codecept.io');
7534
+ * ```
7535
+ *
7536
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7537
+ * in Chromium-based browsers, where read access is granted automatically.
7538
+ * @param text - value to check.
7539
+ * @returns automatically synchronized promise through #recorder
7540
+ */
7541
+ seeClipboardEquals(text: string): void;
7542
+ /**
7543
+ * Grabs the text content of the system clipboard and returns it to test.
7544
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
7545
+ *
7546
+ * ```js
7547
+ * I.click('Copy to clipboard');
7548
+ * let url = await I.grabFromClipboard();
7549
+ * ```
7550
+ *
7551
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7552
+ * in Chromium-based browsers, where read access is granted automatically.
7553
+ * @returns the system clipboard contents.
7554
+ */
7555
+ grabFromClipboard(): Promise<string>;
7556
+ /**
7557
+ * Clears the system clipboard.
7558
+ *
7559
+ * ```js
7560
+ * I.clearClipboard();
7561
+ * I.seeClipboardEquals('');
7562
+ * ```
7563
+ * @returns automatically synchronized promise through #recorder
7564
+ */
7565
+ clearClipboard(): void;
7369
7566
  /**
7370
7567
  * If a function returns a Promise, tt will wait for its resolution.
7371
7568
  *
@@ -9761,6 +9958,58 @@ declare namespace CodeceptJS {
9761
9958
  * @returns attribute value
9762
9959
  */
9763
9960
  grabCookie(name?: string): any;
9961
+ /**
9962
+ * Checks that the system clipboard contains the given text.
9963
+ *
9964
+ * ```js
9965
+ * I.click('Copy to clipboard');
9966
+ * I.seeInClipboard('https://codecept.io');
9967
+ * ```
9968
+ *
9969
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9970
+ * in Chromium-based browsers, where read access is granted automatically.
9971
+ * @param text - value to check.
9972
+ * @returns automatically synchronized promise through #recorder
9973
+ */
9974
+ seeInClipboard(text: string): void;
9975
+ /**
9976
+ * Checks that the system clipboard is equal to the given text.
9977
+ *
9978
+ * ```js
9979
+ * I.click('Copy to clipboard');
9980
+ * I.seeClipboardEquals('https://codecept.io');
9981
+ * ```
9982
+ *
9983
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9984
+ * in Chromium-based browsers, where read access is granted automatically.
9985
+ * @param text - value to check.
9986
+ * @returns automatically synchronized promise through #recorder
9987
+ */
9988
+ seeClipboardEquals(text: string): void;
9989
+ /**
9990
+ * Grabs the text content of the system clipboard and returns it to test.
9991
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
9992
+ *
9993
+ * ```js
9994
+ * I.click('Copy to clipboard');
9995
+ * let url = await I.grabFromClipboard();
9996
+ * ```
9997
+ *
9998
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9999
+ * in Chromium-based browsers, where read access is granted automatically.
10000
+ * @returns the system clipboard contents.
10001
+ */
10002
+ grabFromClipboard(): Promise<string>;
10003
+ /**
10004
+ * Clears the system clipboard.
10005
+ *
10006
+ * ```js
10007
+ * I.clearClipboard();
10008
+ * I.seeClipboardEquals('');
10009
+ * ```
10010
+ * @returns automatically synchronized promise through #recorder
10011
+ */
10012
+ clearClipboard(): void;
9764
10013
  /**
9765
10014
  * Waits for the specified cookie in the cookies.
9766
10015
  *
@@ -10394,6 +10643,11 @@ declare namespace CodeceptJS {
10394
10643
  * @returns - Filtered array of test files for this shard
10395
10644
  */
10396
10645
  _applySharding(testFiles: string[], shardConfig: string): string[];
10646
+ /**
10647
+ * Keeps only tests that failed in the previous run when `--last-failed` is set.
10648
+ * @param mocha - Mocha instance with loaded tests
10649
+ */
10650
+ filterLastFailedTests(mocha: any): void;
10397
10651
  /**
10398
10652
  * Run a specific test or all loaded tests.
10399
10653
  */
@@ -10564,6 +10818,13 @@ declare namespace CodeceptJS {
10564
10818
  * @param [fileName] - Path to the JSON file, relative to `output_dir`. Defaults to "result.json".
10565
10819
  */
10566
10820
  save(fileName?: string): void;
10821
+ /**
10822
+ * Loads tests that failed in a result saved by a previous run.
10823
+ * @param [outputDir] - Directory containing the saved result. Defaults to `output_dir`.
10824
+ * @param [fileName = result.json] - Path to the JSON file, relative to `outputDir`. Defaults to "result.json".
10825
+ * @returns Serialized failed tests.
10826
+ */
10827
+ static loadFailedTests(outputDir?: string, fileName?: string): { uid: string; title: string; state: string; }[];
10567
10828
  /**
10568
10829
  * Adds stats to this result.
10569
10830
  */
@@ -10678,6 +10939,10 @@ declare namespace CodeceptJS {
10678
10939
  */
10679
10940
  transpose(): void;
10680
10941
  }
10942
+ /**
10943
+ * Returns true while steps are executed inside tryTo or a retryTo attempt that will be retried
10944
+ */
10945
+ function isEffectActive(): boolean;
10681
10946
  function within(context: CodeceptJS.LocatorOrString, fn: (...params: any[]) => any): Promise<any> | undefined;
10682
10947
  /**
10683
10948
  * - Designed for use in CodeceptJS tests as a "soft assertion."
@@ -11132,6 +11397,10 @@ declare namespace CodeceptJS {
11132
11397
  stack: string;
11133
11398
  helper: any;
11134
11399
  helperMethod: string;
11400
+ /**
11401
+ * Alias of `title`, the name of the helper method this step executes
11402
+ */
11403
+ name: string;
11135
11404
  timeout: any;
11136
11405
  /**
11137
11406
  * @param timeout - timeout in milliseconds or 0 if no timeout