codeceptjs 4.2.0-beta.3 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ import Locator from '../locator.js'
8
8
  import recorder from '../recorder.js'
9
9
  import store from '../store.js'
10
10
  import { checkFocusBeforeType, checkFocusBeforePressKey } from './extras/focusCheck.js'
11
+ import { CLIPBOARD_READ_TIMEOUT_MS, readClipboardScript, writeClipboardScript } from './extras/clipboard.js'
11
12
  import { includes as stringIncludes } from '../assert/include.js'
12
13
  import { urlEquals, equals } from '../assert/equal.js'
13
14
  import { empty } from '../assert/empty.js'
@@ -584,7 +585,8 @@ class Playwright extends Helper {
584
585
  // Clear popup state to ensure clean state for each test
585
586
  popupStore.clear()
586
587
 
587
- recorder.retry({
588
+ // Configure retry for this test; will clean up after test completes
589
+ this._retryConfig = {
588
590
  retries: test?.opts?.conditionalRetries || 3,
589
591
  when: err => {
590
592
  if (!err || typeof err.message !== 'string') {
@@ -593,7 +595,8 @@ class Playwright extends Helper {
593
595
  // ignore context errors
594
596
  return err.message.includes('context')
595
597
  },
596
- })
598
+ }
599
+ recorder.retry(this._retryConfig)
597
600
 
598
601
  // Start browser if needed (initial start or browser restart strategy)
599
602
  if (!this.isRunning && !this.options.manualStart) await this._startBrowser()
@@ -698,6 +701,12 @@ class Playwright extends Helper {
698
701
  }
699
702
 
700
703
  async _after() {
704
+ // Clean up our retry config to prevent accumulation
705
+ if (this._retryConfig) {
706
+ recorder.retries = recorder.retries.filter(r => r !== this._retryConfig)
707
+ this._retryConfig = null
708
+ }
709
+
701
710
  if (!this.isRunning) return
702
711
 
703
712
  // Clear popup state to prevent leakage between tests
@@ -2659,6 +2668,49 @@ class Playwright extends Helper {
2659
2668
  return this.browserContext.clearCookies()
2660
2669
  }
2661
2670
 
2671
+ /**
2672
+ * {{> seeInClipboard }}
2673
+ */
2674
+ async seeInClipboard(text) {
2675
+ const clipboard = await this.grabFromClipboard()
2676
+ stringIncludes('clipboard').assert(text, clipboard)
2677
+ }
2678
+
2679
+ /**
2680
+ * {{> seeClipboardEquals }}
2681
+ */
2682
+ async seeClipboardEquals(text) {
2683
+ const clipboard = await this.grabFromClipboard()
2684
+ return equals('clipboard').assert(clipboard, text)
2685
+ }
2686
+
2687
+ /**
2688
+ * {{> grabFromClipboard }}
2689
+ */
2690
+ async grabFromClipboard() {
2691
+ await this._grantClipboardAccess()
2692
+ const clipboard = await this.page.evaluate(readClipboardScript, CLIPBOARD_READ_TIMEOUT_MS)
2693
+ this.debugSection('Clipboard', clipboard)
2694
+ return clipboard
2695
+ }
2696
+
2697
+ /**
2698
+ * {{> clearClipboard }}
2699
+ */
2700
+ async clearClipboard() {
2701
+ await this._grantClipboardAccess()
2702
+ return this.page.evaluate(writeClipboardScript, '')
2703
+ }
2704
+
2705
+ async _grantClipboardAccess() {
2706
+ await this.page.bringToFront().catch(() => {})
2707
+ if (this.options.browser !== 'chromium') return
2708
+ await this.page
2709
+ .context()
2710
+ .grantPermissions(['clipboard-read', 'clipboard-write'])
2711
+ .catch(() => {})
2712
+ }
2713
+
2662
2714
  /**
2663
2715
  * Executes a script on the page:
2664
2716
  *
@@ -3667,8 +3719,7 @@ class Playwright extends Helper {
3667
3719
  }
3668
3720
 
3669
3721
  try {
3670
- // Always create frame locator from page to avoid nested frame paths
3671
- this.frame = await Promise.race([this.page.frameLocator(locator), new Promise((_, reject) => setTimeout(() => reject(new Error('Frame locator timeout')), 5000))])
3722
+ this.frame = this.frame ? this.frame.frameLocator(locator) : this.page.frameLocator(locator)
3672
3723
  } catch (e) {
3673
3724
  console.warn('Warning during frame locator creation:', e.message)
3674
3725
  throw new Error(`Frame ${JSON.stringify(locator)} could not be accessed`)
@@ -9,6 +9,7 @@ import Locator from '../locator.js'
9
9
  import recorder from '../recorder.js'
10
10
  import store from '../store.js'
11
11
  import { checkFocusBeforeType, checkFocusBeforePressKey } from './extras/focusCheck.js'
12
+ import { CLIPBOARD_READ_TIMEOUT_MS, readClipboardScript, writeClipboardScript } from './extras/clipboard.js'
12
13
  import { includes as stringIncludes } from '../assert/include.js'
13
14
  import { urlEquals, equals } from '../assert/equal.js'
14
15
  import { empty } from '../assert/empty.js'
@@ -354,7 +355,8 @@ class Puppeteer extends Helper {
354
355
  async _before(test) {
355
356
  this.sessionPages = {}
356
357
  this.currentRunningTest = test
357
- recorder.retry({
358
+ // Configure retry for this test; will clean up after test completes
359
+ this._retryConfig = {
358
360
  retries: test?.opts?.conditionalRetries || 3,
359
361
  when: err => {
360
362
  if (!err || typeof err.message !== 'string') {
@@ -363,13 +365,20 @@ class Puppeteer extends Helper {
363
365
  // ignore context errors
364
366
  return err.message.includes('context')
365
367
  },
366
- })
368
+ }
369
+ recorder.retry(this._retryConfig)
367
370
  if (this.options.restart && !this.options.manualStart) return this._startBrowser()
368
371
  if (!this.isRunning && !this.options.manualStart) return this._startBrowser()
369
372
  return this.browser
370
373
  }
371
374
 
372
375
  async _after() {
376
+ // Clean up our retry config to prevent accumulation
377
+ if (this._retryConfig) {
378
+ recorder.retries = recorder.retries.filter(r => r !== this._retryConfig)
379
+ this._retryConfig = null
380
+ }
381
+
373
382
  if (!this.isRunning) return
374
383
 
375
384
  // Clear popup state to prevent leakage between tests
@@ -1960,6 +1969,55 @@ class Puppeteer extends Helper {
1960
1969
  return this.page.deleteCookie(cookie[0])
1961
1970
  }
1962
1971
 
1972
+ /**
1973
+ * {{> seeInClipboard }}
1974
+ */
1975
+ async seeInClipboard(text) {
1976
+ const clipboard = await this.grabFromClipboard()
1977
+ stringIncludes('clipboard').assert(text, clipboard)
1978
+ }
1979
+
1980
+ /**
1981
+ * {{> seeClipboardEquals }}
1982
+ */
1983
+ async seeClipboardEquals(text) {
1984
+ const clipboard = await this.grabFromClipboard()
1985
+ return equals('clipboard').assert(clipboard, text)
1986
+ }
1987
+
1988
+ /**
1989
+ * {{> grabFromClipboard }}
1990
+ */
1991
+ async grabFromClipboard() {
1992
+ await this._grantClipboardAccess()
1993
+ const clipboard = await this.page.evaluate(readClipboardScript, CLIPBOARD_READ_TIMEOUT_MS)
1994
+ this.debugSection('Clipboard', clipboard)
1995
+ return clipboard
1996
+ }
1997
+
1998
+ /**
1999
+ * {{> clearClipboard }}
2000
+ */
2001
+ async clearClipboard() {
2002
+ await this._grantClipboardAccess()
2003
+ return this.page.evaluate(writeClipboardScript, '')
2004
+ }
2005
+
2006
+ async _grantClipboardAccess() {
2007
+ await this.page.bringToFront().catch(() => {})
2008
+ let origin
2009
+ try {
2010
+ origin = new URL(this.page.url()).origin
2011
+ } catch (err) {
2012
+ return
2013
+ }
2014
+ if (!origin.startsWith('http')) return
2015
+ await this.page
2016
+ .browserContext()
2017
+ .overridePermissions(origin, ['clipboard-read', 'clipboard-write', 'clipboard-sanitized-write'])
2018
+ .catch(() => {})
2019
+ }
2020
+
1963
2021
  /**
1964
2022
  * If a function returns a Promise, tt will wait for its resolution.
1965
2023
  *
@@ -3709,4 +3767,3 @@ async function proceedSelect(context, el, option) {
3709
3767
 
3710
3768
  return this._waitForAction()
3711
3769
  }
3712
-
@@ -11,6 +11,7 @@ import { includes as stringIncludes } from '../assert/include.js'
11
11
  import { urlEquals, equals } from '../assert/equal.js'
12
12
  import store from '../store.js'
13
13
  import { checkFocusBeforeType, checkFocusBeforePressKey } from './extras/focusCheck.js'
14
+ import { CLIPBOARD_READ_TIMEOUT_MS, readClipboardScript, writeClipboardScript, clipboardAsyncScript } from './extras/clipboard.js'
14
15
  import output from '../output.js'
15
16
  const { debug } = output
16
17
  import { empty } from '../assert/empty.js'
@@ -2091,6 +2092,48 @@ class WebDriver extends Helper {
2091
2092
  return cookie[0]
2092
2093
  }
2093
2094
 
2095
+ /**
2096
+ * {{> seeInClipboard }}
2097
+ */
2098
+ async seeInClipboard(text) {
2099
+ const clipboard = await this.grabFromClipboard()
2100
+ return stringIncludes('clipboard').assert(text, clipboard)
2101
+ }
2102
+
2103
+ /**
2104
+ * {{> seeClipboardEquals }}
2105
+ */
2106
+ async seeClipboardEquals(text) {
2107
+ const clipboard = await this.grabFromClipboard()
2108
+ return equals('clipboard').assert(clipboard, text)
2109
+ }
2110
+
2111
+ /**
2112
+ * {{> grabFromClipboard }}
2113
+ */
2114
+ async grabFromClipboard() {
2115
+ await this._grantClipboardAccess()
2116
+ const result = (await this.browser.executeAsync(clipboardAsyncScript(readClipboardScript), CLIPBOARD_READ_TIMEOUT_MS)) || {}
2117
+ if (result.error) throw new Error(`Could not read the clipboard: ${result.error}`)
2118
+ this.debugSection('Clipboard', result.value)
2119
+ return result.value
2120
+ }
2121
+
2122
+ /**
2123
+ * {{> clearClipboard }}
2124
+ */
2125
+ async clearClipboard() {
2126
+ await this._grantClipboardAccess()
2127
+ const result = (await this.browser.executeAsync(clipboardAsyncScript(writeClipboardScript), '')) || {}
2128
+ if (result.error) throw new Error(`Could not write to the clipboard: ${result.error}`)
2129
+ }
2130
+
2131
+ async _grantClipboardAccess() {
2132
+ if (typeof this.browser.setPermissions !== 'function') return
2133
+ await this.browser.setPermissions({ name: 'clipboard-read' }, 'granted').catch(() => {})
2134
+ await this.browser.setPermissions({ name: 'clipboard-write' }, 'granted').catch(() => {})
2135
+ }
2136
+
2094
2137
  /**
2095
2138
  * {{> waitForCookie }}
2096
2139
  */
@@ -0,0 +1,31 @@
1
+ export const CLIPBOARD_READ_TIMEOUT_MS = 5000
2
+
3
+ export function readClipboardScript(timeout) {
4
+ if (!navigator.clipboard || !navigator.clipboard.readText) {
5
+ throw new Error('Clipboard API is not available on this page, it requires a secure context (https or localhost)')
6
+ }
7
+ return Promise.race([navigator.clipboard.readText(), new Promise((resolve, reject) => setTimeout(() => reject(new Error('timed out while reading the clipboard')), timeout))])
8
+ }
9
+
10
+ export function writeClipboardScript(text) {
11
+ if (!navigator.clipboard || !navigator.clipboard.writeText) {
12
+ throw new Error('Clipboard API is not available on this page, it requires a secure context (https or localhost)')
13
+ }
14
+ return navigator.clipboard.writeText(text)
15
+ }
16
+
17
+ export function clipboardExpression(script, arg) {
18
+ return `(${script.toString()})(${JSON.stringify(arg)})`
19
+ }
20
+
21
+ export function clipboardAsyncScript(script) {
22
+ return `
23
+ var done = arguments[arguments.length - 1]
24
+ var fail = function (err) { done({ error: (err && err.message) || String(err) }) }
25
+ try {
26
+ (${script.toString()})(arguments[0]).then(function (value) { done({ value: value }) }, fail)
27
+ } catch (err) {
28
+ fail(err)
29
+ }
30
+ `
31
+ }
@@ -98,7 +98,6 @@ export default function (config) {
98
98
 
99
99
  const when = err => {
100
100
  if (!enableRetry) return
101
- if (store.debugMode) return false
102
101
  if (!store.autoRetries) return false
103
102
  if (err && err.isTerminal) return false
104
103
  if (err && err.message && (err.message.includes('ERR_ABORTED') || err.message.includes('frame was detached') || err.message.includes('Target page, context or browser has been closed'))) return false
@@ -152,7 +151,9 @@ export default function (config) {
152
151
  test.opts.stepRetryPriority = stepRetryPriority
153
152
 
154
153
  debug('applying retries = %d for test %s', config.retries, test.title)
155
- recorder.retry(config)
154
+ if (!recorder.retries.find(r => r === config)) {
155
+ recorder.retry(config)
156
+ }
156
157
  })
157
158
 
158
159
  event.dispatcher.on(event.test.started, test => {
@@ -171,4 +172,8 @@ export default function (config) {
171
172
  test.opts.conditionalRetries = test.opts.conditionalRetries || config.retries
172
173
  }
173
174
  })
175
+
176
+ event.dispatcher.on(event.test.after, () => {
177
+ recorder.retries = recorder.retries.filter(r => r !== config)
178
+ })
174
179
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "4.2.0-beta.3",
3
+ "version": "4.2.0",
4
4
  "type": "module",
5
5
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
6
6
  "keywords": [
@@ -207,7 +207,7 @@
207
207
  }
208
208
  },
209
209
  "engines": {
210
- "node": ">=16.0",
210
+ "node": ">=22.12.0",
211
211
  "npm": ">=5.6.0"
212
212
  },
213
213
  "es6": true,
@@ -770,6 +770,32 @@ 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
+ */
781
+ clearClipboard(): Promise<any>;
782
+ /**
783
+ * Grabs the text content of the system clipboard and returns it to test.
784
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
785
+ *
786
+ * ```js
787
+ * I.click('Copy to clipboard');
788
+ * let url = await I.grabFromClipboard();
789
+ * ```
790
+ *
791
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
792
+ * in Chromium-based browsers, where read access is granted automatically.
793
+ * @returns the system clipboard contents.
794
+ *
795
+ *
796
+ * Appium: support both Android and iOS
797
+ */
798
+ grabFromClipboard(): Promise<string>;
773
799
  /**
774
800
  * Appends text to a input field or textarea.
775
801
  * Field is located by name, label, CSS or XPath
@@ -2166,6 +2192,56 @@ declare namespace CodeceptJS {
2166
2192
  * @param [name = null] - (optional, `null` by default) cookie name
2167
2193
  */
2168
2194
  clearCookie(name?: string | null): Promise<void>;
2195
+ /**
2196
+ * Checks that the system clipboard contains the given text.
2197
+ *
2198
+ * ```js
2199
+ * I.click('Copy to clipboard');
2200
+ * I.seeInClipboard('https://codecept.io');
2201
+ * ```
2202
+ *
2203
+ * Reading the clipboard requires a secure context (`https` or `localhost`).
2204
+ * @param text - value to check.
2205
+ */
2206
+ seeInClipboard(text: string): Promise<void>;
2207
+ /**
2208
+ * Checks that the system clipboard is equal to the given text.
2209
+ *
2210
+ * ```js
2211
+ * I.click('Copy to clipboard');
2212
+ * I.seeClipboardEquals('https://codecept.io');
2213
+ * ```
2214
+ *
2215
+ * Reading the clipboard requires a secure context (`https` or `localhost`).
2216
+ * @param text - value to check.
2217
+ */
2218
+ seeClipboardEquals(text: string): Promise<void>;
2219
+ /**
2220
+ * Clears the system clipboard.
2221
+ *
2222
+ * ```js
2223
+ * I.clearClipboard();
2224
+ * I.seeClipboardEquals('');
2225
+ * ```
2226
+ */
2227
+ clearClipboard(): Promise<void>;
2228
+ /**
2229
+ * Grabs the text content of the system clipboard.
2230
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
2231
+ *
2232
+ * ```js
2233
+ * I.click('Copy to clipboard');
2234
+ * const url = await I.grabFromClipboard();
2235
+ * ```
2236
+ * @returns the system clipboard contents.
2237
+ */
2238
+ grabFromClipboard(): Promise<string>;
2239
+ /**
2240
+ * Brings the current target to front and grants it clipboard read/write access, so
2241
+ * `navigator.clipboard` does not reject with a permission or focus error. Failures are ignored:
2242
+ * a browser without `Browser.grantPermissions` surfaces its own error from the read instead.
2243
+ */
2244
+ protected _grantClipboardAccess(): Promise<any>;
2169
2245
  /**
2170
2246
  * Saves a screenshot to the output folder (set in codecept.conf.ts or codecept.conf.js).
2171
2247
  * Filename is relative to the output folder.
@@ -3423,6 +3499,17 @@ declare namespace CodeceptJS {
3423
3499
  * elements works, it only pins the config presets Obscura requires and manages the `obscura serve`
3424
3500
  * process lifecycle, the same way Playwright manages its own browser process.
3425
3501
  *
3502
+ * > Obscura support is experimental in CodeceptJS 4.2. Pin the browser version in CI and keep a
3503
+ * > Playwright/WebDriver job for browser-compatibility coverage.
3504
+ *
3505
+ * ## Compatibility
3506
+ *
3507
+ * | CodeceptJS | Recommended Obscura | Notes |
3508
+ * | --- | --- | --- |
3509
+ * | 4.2.x | 0.2.2 | Version used by the CodeceptJS Obscura CI workflow |
3510
+ * | 4.2.x | 0.2.x | Supported; capabilities are detected at runtime |
3511
+ * | 4.2.x | 0.1.x / `-no-render` | DOM-only mode; no layout, visibility assertions, or screenshots |
3512
+ *
3426
3513
  * ## Modes
3427
3514
  *
3428
3515
  * - **ATTACH** — `endpoint` is set explicitly in the config. The helper only connects to it; it
@@ -3440,8 +3527,20 @@ declare namespace CodeceptJS {
3440
3527
  *
3441
3528
  * ## Install
3442
3529
  *
3443
- * Download a release binary and put it on your `PATH` (or point `binaryPath`/`OBSCURA_PATH` at
3444
- * it directly) and the helper launches and tears it down for you automatically:
3530
+ * Download a release archive from [Obscura releases](https://github.com/h4ckf0r0day/obscura/releases).
3531
+ * CodeceptJS 4.2 is tested with Obscura 0.2.2. Rendering archives are available for:
3532
+ *
3533
+ * | platform | archive |
3534
+ * | --- | --- |
3535
+ * | Linux x64 | `obscura-x86_64-linux.tar.gz` |
3536
+ * | Linux ARM64 | `obscura-aarch64-linux.tar.gz` |
3537
+ * | macOS Intel | `obscura-x86_64-macos.tar.gz` |
3538
+ * | macOS Apple Silicon | `obscura-aarch64-macos.tar.gz` |
3539
+ * | Windows x64 | `obscura-x86_64-windows.zip` |
3540
+ *
3541
+ * Extract the archive and put `obscura` (`obscura.exe` on Windows) on your `PATH`, or point
3542
+ * `binaryPath`/`OBSCURA_PATH` at it. The helper then launches and tears it down automatically.
3543
+ * For example, on Linux x64:
3445
3544
  *
3446
3545
  * ```sh
3447
3546
  * curl -sL https://github.com/h4ckf0r0day/obscura/releases/download/v0.2.2/obscura-x86_64-linux.tar.gz | tar xz
@@ -5084,6 +5183,55 @@ declare namespace CodeceptJS {
5084
5183
  * @param [cookie = null] - (optional, `null` by default) cookie name
5085
5184
  */
5086
5185
  clearCookie(cookie?: string): Promise<any>;
5186
+ /**
5187
+ * Checks that the system clipboard contains the given text.
5188
+ *
5189
+ * ```js
5190
+ * I.click('Copy to clipboard');
5191
+ * I.seeInClipboard('https://codecept.io');
5192
+ * ```
5193
+ *
5194
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5195
+ * in Chromium-based browsers, where read access is granted automatically.
5196
+ * @param text - value to check.
5197
+ */
5198
+ seeInClipboard(text: string): Promise<any>;
5199
+ /**
5200
+ * Checks that the system clipboard is equal to the given text.
5201
+ *
5202
+ * ```js
5203
+ * I.click('Copy to clipboard');
5204
+ * I.seeClipboardEquals('https://codecept.io');
5205
+ * ```
5206
+ *
5207
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5208
+ * in Chromium-based browsers, where read access is granted automatically.
5209
+ * @param text - value to check.
5210
+ */
5211
+ seeClipboardEquals(text: string): Promise<any>;
5212
+ /**
5213
+ * Grabs the text content of the system clipboard and returns it to test.
5214
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
5215
+ *
5216
+ * ```js
5217
+ * I.click('Copy to clipboard');
5218
+ * let url = await I.grabFromClipboard();
5219
+ * ```
5220
+ *
5221
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
5222
+ * in Chromium-based browsers, where read access is granted automatically.
5223
+ * @returns the system clipboard contents.
5224
+ */
5225
+ grabFromClipboard(): Promise<string>;
5226
+ /**
5227
+ * Clears the system clipboard.
5228
+ *
5229
+ * ```js
5230
+ * I.clearClipboard();
5231
+ * I.seeClipboardEquals('');
5232
+ * ```
5233
+ */
5234
+ clearClipboard(): Promise<any>;
5087
5235
  /**
5088
5236
  * Executes a script on the page:
5089
5237
  *
@@ -7165,6 +7313,55 @@ declare namespace CodeceptJS {
7165
7313
  * @param [cookie = null] - (optional, `null` by default) cookie name
7166
7314
  */
7167
7315
  clearCookie(cookie?: string): Promise<any>;
7316
+ /**
7317
+ * Checks that the system clipboard contains the given text.
7318
+ *
7319
+ * ```js
7320
+ * I.click('Copy to clipboard');
7321
+ * I.seeInClipboard('https://codecept.io');
7322
+ * ```
7323
+ *
7324
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7325
+ * in Chromium-based browsers, where read access is granted automatically.
7326
+ * @param text - value to check.
7327
+ */
7328
+ seeInClipboard(text: string): Promise<any>;
7329
+ /**
7330
+ * Checks that the system clipboard is equal to the given text.
7331
+ *
7332
+ * ```js
7333
+ * I.click('Copy to clipboard');
7334
+ * I.seeClipboardEquals('https://codecept.io');
7335
+ * ```
7336
+ *
7337
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7338
+ * in Chromium-based browsers, where read access is granted automatically.
7339
+ * @param text - value to check.
7340
+ */
7341
+ seeClipboardEquals(text: string): Promise<any>;
7342
+ /**
7343
+ * Grabs the text content of the system clipboard and returns it to test.
7344
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
7345
+ *
7346
+ * ```js
7347
+ * I.click('Copy to clipboard');
7348
+ * let url = await I.grabFromClipboard();
7349
+ * ```
7350
+ *
7351
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
7352
+ * in Chromium-based browsers, where read access is granted automatically.
7353
+ * @returns the system clipboard contents.
7354
+ */
7355
+ grabFromClipboard(): Promise<string>;
7356
+ /**
7357
+ * Clears the system clipboard.
7358
+ *
7359
+ * ```js
7360
+ * I.clearClipboard();
7361
+ * I.seeClipboardEquals('');
7362
+ * ```
7363
+ */
7364
+ clearClipboard(): Promise<any>;
7168
7365
  /**
7169
7366
  * If a function returns a Promise, tt will wait for its resolution.
7170
7367
  *
@@ -9482,6 +9679,55 @@ declare namespace CodeceptJS {
9482
9679
  * @param [name = null] - cookie name.
9483
9680
  */
9484
9681
  grabCookie(name?: string): Promise<any>;
9682
+ /**
9683
+ * Checks that the system clipboard contains the given text.
9684
+ *
9685
+ * ```js
9686
+ * I.click('Copy to clipboard');
9687
+ * I.seeInClipboard('https://codecept.io');
9688
+ * ```
9689
+ *
9690
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9691
+ * in Chromium-based browsers, where read access is granted automatically.
9692
+ * @param text - value to check.
9693
+ */
9694
+ seeInClipboard(text: string): Promise<any>;
9695
+ /**
9696
+ * Checks that the system clipboard is equal to the given text.
9697
+ *
9698
+ * ```js
9699
+ * I.click('Copy to clipboard');
9700
+ * I.seeClipboardEquals('https://codecept.io');
9701
+ * ```
9702
+ *
9703
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9704
+ * in Chromium-based browsers, where read access is granted automatically.
9705
+ * @param text - value to check.
9706
+ */
9707
+ seeClipboardEquals(text: string): Promise<any>;
9708
+ /**
9709
+ * Grabs the text content of the system clipboard and returns it to test.
9710
+ * Resumes test execution, so **should be used inside async function with `await`** operator.
9711
+ *
9712
+ * ```js
9713
+ * I.click('Copy to clipboard');
9714
+ * let url = await I.grabFromClipboard();
9715
+ * ```
9716
+ *
9717
+ * Reading the clipboard requires a secure context (`https` or `localhost`) and is supported
9718
+ * in Chromium-based browsers, where read access is granted automatically.
9719
+ * @returns the system clipboard contents.
9720
+ */
9721
+ grabFromClipboard(): Promise<string>;
9722
+ /**
9723
+ * Clears the system clipboard.
9724
+ *
9725
+ * ```js
9726
+ * I.clearClipboard();
9727
+ * I.seeClipboardEquals('');
9728
+ * ```
9729
+ */
9730
+ clearClipboard(): Promise<any>;
9485
9731
  /**
9486
9732
  * Waits for the specified cookie in the cookies.
9487
9733
  *