@@ -18,6 +18,7 @@ import { isColorProperty, convertColorToRGBA } from '../colorUtils.js'
1818import WebElement from '../element/WebElement.js'
1919import CDPElementHandle from './extras/CDPElementHandle.js'
2020import { checkFocusBeforeType , checkFocusBeforePressKey } from './extras/focusCheck.js'
21+ import { CLIPBOARD_READ_TIMEOUT_MS , readClipboardScript , writeClipboardScript , clipboardExpression } from './extras/clipboard.js'
2122import { dontSeeTraffic , seeTraffic , grabRecordedNetworkTraffics , flushNetworkTraffics } from './network/actions.js'
2223import { assembleApng , isPng } from './extras/apngAssembler.js'
2324
@@ -1940,6 +1941,89 @@ class CDPBrowser extends Helper {
19401941 }
19411942 }
19421943
1944+ /**
1945+ * Checks that the system clipboard contains the given text.
1946+ *
1947+ * ```js
1948+ * I.click('Copy to clipboard');
1949+ * I.seeInClipboard('https://codecept.io');
1950+ * ```
1951+ *
1952+ * Reading the clipboard requires a secure context (`https` or `localhost`).
1953+ *
1954+ * @param {string } text value to check.
1955+ * @returns {Promise<void> }
1956+ */
1957+ async seeInClipboard ( text ) {
1958+ const clipboard = await this . grabFromClipboard ( )
1959+ return stringIncludes ( 'clipboard' ) . assert ( text , clipboard )
1960+ }
1961+
1962+ /**
1963+ * Checks that the system clipboard is equal to the given text.
1964+ *
1965+ * ```js
1966+ * I.click('Copy to clipboard');
1967+ * I.seeClipboardEquals('https://codecept.io');
1968+ * ```
1969+ *
1970+ * Reading the clipboard requires a secure context (`https` or `localhost`).
1971+ *
1972+ * @param {string } text value to check.
1973+ * @returns {Promise<void> }
1974+ */
1975+ async seeClipboardEquals ( text ) {
1976+ const clipboard = await this . grabFromClipboard ( )
1977+ return equals ( 'clipboard' ) . assert ( clipboard , text )
1978+ }
1979+
1980+ /**
1981+ * Clears the system clipboard.
1982+ *
1983+ * ```js
1984+ * I.clearClipboard();
1985+ * I.seeClipboardEquals('');
1986+ * ```
1987+ *
1988+ * @returns {Promise<void> }
1989+ */
1990+ async clearClipboard ( ) {
1991+ await this . _grantClipboardAccess ( )
1992+ await this . _evaluate ( clipboardExpression ( writeClipboardScript , '' ) )
1993+ }
1994+
1995+ /**
1996+ * Grabs the text content of the system clipboard.
1997+ * Resumes test execution, so **should be used inside async function with `await`** operator.
1998+ *
1999+ * ```js
2000+ * I.click('Copy to clipboard');
2001+ * const url = await I.grabFromClipboard();
2002+ * ```
2003+ *
2004+ * @returns {Promise<string> } the system clipboard contents.
2005+ */
2006+ async grabFromClipboard ( ) {
2007+ await this . _grantClipboardAccess ( )
2008+ const clipboard = await this . _evaluate ( clipboardExpression ( readClipboardScript , CLIPBOARD_READ_TIMEOUT_MS ) )
2009+ this . debugSection ( 'Clipboard' , clipboard )
2010+ return clipboard
2011+ }
2012+
2013+ /**
2014+ * Brings the current target to front and grants it clipboard read/write access, so
2015+ * `navigator.clipboard` does not reject with a permission or focus error. Failures are ignored:
2016+ * a browser without `Browser.grantPermissions` surfaces its own error from the read instead.
2017+ *
2018+ * @protected
2019+ */
2020+ async _grantClipboardAccess ( ) {
2021+ await this . cdp . send ( 'Page.bringToFront' , { } , this . sessionId ) . catch ( ( ) => null )
2022+ const origin = await this . _evaluate ( 'window.location.origin' ) . catch ( ( ) => null )
2023+ if ( ! origin || ! origin . startsWith ( 'http' ) ) return
2024+ await this . cdp . send ( 'Browser.grantPermissions' , { origin, permissions : [ 'clipboardReadWrite' , 'clipboardSanitizedWrite' ] } ) . catch ( ( ) => null )
2025+ }
2026+
19432027 /**
19442028 * Saves a screenshot to the output folder (set in codecept.conf.ts or codecept.conf.js).
19452029 * Filename is relative to the output folder.
0 commit comments