diff --git a/docs/helpers/WebDriver.md b/docs/helpers/WebDriver.md index 7417312a5..19d6f8bfa 100644 --- a/docs/helpers/WebDriver.md +++ b/docs/helpers/WebDriver.md @@ -37,24 +37,23 @@ Type: [object][17] - `browser` **[string][18]** Browser in which to perform testing. - `basicAuth` **[string][18]?** (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'} - `host` **[string][18]?** WebDriver host to connect. -- `port` **[number][24]?** WebDriver port to connect. +- `port` **[number][23]?** WebDriver port to connect. - `protocol` **[string][18]?** protocol for WebDriver server. - `path` **[string][18]?** path to WebDriver server. -- `restart` **[boolean][34]?** restart browser between tests. -- `smartWait` **([boolean][34] | [number][24])?** **enables [SmartWait][38]**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000. -- `disableScreenshots` **[boolean][34]?** don't save screenshots on failure. -- `fullPageScreenshots` **[boolean][34]?** (optional - make full page screenshots on failure. -- `uniqueScreenshotNames` **[boolean][34]?** option to prevent screenshot override if you have scenarios with the same name in different suites. -- `keepBrowserState` **[boolean][34]?** keep browser state between tests when `restart` is set to false. -- `keepCookies` **[boolean][34]?** keep cookies between tests when `restart` set to false. +- `restart` **[boolean][33]?** restart browser between tests. +- `smartWait` **([boolean][33] | [number][23])?** **enables [SmartWait][37]**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000. +- `disableScreenshots` **[boolean][33]?** don't save screenshots on failure. +- `fullPageScreenshots` **[boolean][33]?** (optional - make full page screenshots on failure. +- `uniqueScreenshotNames` **[boolean][33]?** option to prevent screenshot override if you have scenarios with the same name in different suites. +- `keepBrowserState` **[boolean][33]?** keep browser state between tests when `restart` is set to false. +- `keepCookies` **[boolean][33]?** keep cookies between tests when `restart` set to false. - `windowSize` **[string][18]?** default window size. Set to `maximize` or a dimension in the format `640x480`. -- `waitForTimeout` **[number][24]?** sets default wait time in _ms_ for all `wait*` functions. +- `waitForTimeout` **[number][23]?** sets default wait time in _ms_ for all `wait*` functions. - `desiredCapabilities` **[object][17]?** Selenium's [desired capabilities][7]. -- `manualStart` **[boolean][34]?** do not start browser before a test, start it manually inside a helper with `this.helpers["WebDriver"]._startBrowser()`. -- `timeouts` **[object][17]?** [WebDriver timeouts][39] defined as hash. -- `highlightElement` **[boolean][34]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). -- `logLevel` **[string][18]?** level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: [https://webdriver.io/docs/configuration/#loglevel][40] -- `devtoolsProtocol` **[boolean][34]?** enable devtools protocol. Default: false. More info: [https://webdriver.io/docs/automationProtocols/#devtools-protocol][41]. +- `manualStart` **[boolean][33]?** do not start browser before a test, start it manually inside a helper with `this.helpers["WebDriver"]._startBrowser()`. +- `timeouts` **[object][17]?** [WebDriver timeouts][38] defined as hash. +- `highlightElement` **[boolean][33]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). +- `logLevel` **[string][18]?** level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: [https://webdriver.io/docs/configuration/#loglevel][39] @@ -147,7 +146,6 @@ website][4]. WebDriver : { url: "http://localhost", browser: "chrome", - devtoolsProtocol: true, desiredCapabilities: { chromeOptions: { args: [ "--headless", "--disable-gpu", "--no-sandbox" ] @@ -856,27 +854,6 @@ I.dontSeeInTitle('Error'); Returns **void** automatically synchronized promise through #recorder -### dontSeeTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Verifies that a certain request is not part of network traffic. - -Examples: - -```js -I.dontSeeTraffic({ name: 'Unexpected API Call', url: 'https://api.example.com' }); -I.dontSeeTraffic({ name: 'Unexpected API Call of "user" endpoint', url: /api.example.com.*user/ }); -``` - -#### Parameters - -- `opts` **[Object][17]** options when checking the traffic network. - - `opts.name` **[string][18]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail. - - `opts.url` **([string][18] | [RegExp][23])** Expected URL of request in network traffic. Can be a string or a regular expression. - -Returns **void** automatically synchronized promise through #recorder - ### doubleClick Performs a double-click on an element matched by link|button|label|CSS or XPath. @@ -929,7 +906,7 @@ I.dragSlider('#slider', -70); #### Parameters - `locator` **([string][18] | [object][17])** located by label|name|CSS|XPath|strict locator. -- `offsetX` **[number][24]** position to drag. +- `offsetX` **[number][23]** position to drag. Returns **void** automatically synchronized promise through #recorder @@ -938,7 +915,7 @@ Returns **void** automatically synchronized promise through #recorder Executes async script on page. Provided function should execute a passed callback (as first argument) to signal it is finished. -Example: In Vue.js to make components completely rendered we are waiting for [nextTick][25]. +Example: In Vue.js to make components completely rendered we are waiting for [nextTick][24]. ```js I.executeAsyncScript(function(done) { @@ -959,13 +936,13 @@ let val = await I.executeAsyncScript(function(url, done) { #### Parameters - `args` **...any** to be passed to function. -- `fn` **([string][18] | [function][26])** function to be executed in browser context. +- `fn` **([string][18] | [function][25])** function to be executed in browser context. -Returns **[Promise][27]<any>** script return value +Returns **[Promise][26]<any>** script return value ### executeScript -Wraps [execute][28] command. +Wraps [execute][27] command. Executes sync script on a page. Pass arguments to function as additional parameters. @@ -994,9 +971,9 @@ let date = await I.executeScript(function(el) { #### Parameters - `args` **...any** to be passed to function. -- `fn` **([string][18] | [function][26])** function to be executed in browser context. +- `fn` **([string][18] | [function][25])** function to be executed in browser context. -Returns **[Promise][27]<any>** script return value +Returns **[Promise][26]<any>** script return value ### fillField @@ -1026,16 +1003,6 @@ This action supports [React locators](https://codecept.io/react#locators) {{ custom }} -### flushNetworkTraffics - -_Note:_ Only works when devtoolsProtocol is enabled. - -Resets all recorded network requests. - -```js -I.flushNetworkTraffics(); -``` - ### focus Calls [focus][20] on the matching element. @@ -1051,7 +1018,7 @@ I.see('#add-to-cart-bnt'); #### Parameters - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -- `options` **any?** Playwright only: [Additional options][29] for available options object as 2nd argument. +- `options` **any?** Playwright only: [Additional options][28] for available options object as 2nd argument. Returns **void** automatically synchronized promise through #recorder @@ -1130,7 +1097,7 @@ Useful for referencing a specific handle when calling `I.switchToWindow(handle)` const windows = await I.grabAllWindowHandles(); ``` -Returns **[Promise][27]<[Array][30]<[string][18]>>** +Returns **[Promise][26]<[Array][29]<[string][18]>>** ### grabAttributeFrom @@ -1147,7 +1114,7 @@ let hint = await I.grabAttributeFrom('#tooltip', 'title'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `attr` **[string][18]** attribute name. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabAttributeFromAll @@ -1163,7 +1130,7 @@ let hints = await I.grabAttributeFromAll('.tooltip', 'title'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `attr` **[string][18]** attribute name. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabBrowserLogs @@ -1175,7 +1142,7 @@ let logs = await I.grabBrowserLogs(); console.log(JSON.stringify(logs)) ``` -Returns **([Promise][27]<[Array][30]<[object][17]>> | [undefined][31])** all browser logs +Returns **([Promise][26]<[Array][29]<[object][17]>> | [undefined][30])** all browser logs ### grabCookie @@ -1209,7 +1176,7 @@ const value = await I.grabCssPropertyFrom('h3', 'font-weight'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `cssProperty` **[string][18]** CSS property name. -Returns **[Promise][27]<[string][18]>** CSS value +Returns **[Promise][26]<[string][18]>** CSS value ### grabCssPropertyFromAll @@ -1225,7 +1192,7 @@ const values = await I.grabCssPropertyFromAll('h3', 'font-weight'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `cssProperty` **[string][18]** CSS property name. -Returns **[Promise][27]<[Array][30]<[string][18]>>** CSS value +Returns **[Promise][26]<[Array][29]<[string][18]>>** CSS value ### grabCurrentUrl @@ -1237,7 +1204,7 @@ let url = await I.grabCurrentUrl(); console.log(`Current URL is [${url}]`); ``` -Returns **[Promise][27]<[string][18]>** current URL +Returns **[Promise][26]<[string][18]>** current URL ### grabCurrentWindowHandle @@ -1248,7 +1215,7 @@ Useful for referencing it when calling `I.switchToWindow(handle)` const window = await I.grabCurrentWindowHandle(); ``` -Returns **[Promise][27]<[string][18]>** +Returns **[Promise][26]<[string][18]>** ### grabElementBoundingRect @@ -1276,20 +1243,7 @@ const width = await I.grabElementBoundingRect('h3', 'width'); - `prop` - `elementSize` **[string][18]?** x, y, width or height of the given element. -Returns **([Promise][27]<DOMRect> | [Promise][27]<[number][24]>)** Element bounding rectangle - -### grabGeoLocation - -This method is **deprecated**. - -Return the current geo location -Resumes test execution, so **should be used inside async function with `await`** operator. - -```js -let geoLocation = await I.grabGeoLocation(); -``` - -Returns **[Promise][27]<{latitude: [number][24], longitude: [number][24], altitude: [number][24]}>** +Returns **([Promise][26]<DOMRect> | [Promise][26]<[number][23]>)** Element bounding rectangle ### grabHTMLFrom @@ -1306,7 +1260,7 @@ let postHTML = await I.grabHTMLFrom('#post'); - `locator` - `element` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** HTML code for an element +Returns **[Promise][26]<[string][18]>** HTML code for an element ### grabHTMLFromAll @@ -1322,7 +1276,7 @@ let postHTMLs = await I.grabHTMLFromAll('.post'); - `locator` - `element` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** HTML code for an element +Returns **[Promise][26]<[Array][29]<[string][18]>>** HTML code for an element ### grabNumberOfOpenTabs @@ -1333,7 +1287,7 @@ Resumes test execution, so **should be used inside async function with `await`** let tabs = await I.grabNumberOfOpenTabs(); ``` -Returns **[Promise][27]<[number][24]>** number of open tabs +Returns **[Promise][26]<[number][23]>** number of open tabs ### grabNumberOfVisibleElements @@ -1348,7 +1302,7 @@ let numOfElements = await I.grabNumberOfVisibleElements('p'); - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[number][24]>** number of visible elements +Returns **[Promise][26]<[number][23]>** number of visible elements ### grabPageScrollPosition @@ -1359,7 +1313,7 @@ Resumes test execution, so **should be used inside an async function with `await let { x, y } = await I.grabPageScrollPosition(); ``` -Returns **[Promise][27]<PageScrollPosition>** scroll position +Returns **[Promise][26]<PageScrollPosition>** scroll position ### grabPopupText @@ -1369,22 +1323,7 @@ Grab the text within the popup. If no popup is visible then it will return null. await I.grabPopupText(); ``` -Returns **[Promise][27]<[string][18]>** - -### grabRecordedNetworkTraffics - -_Note:_ Only works when devtoolsProtocol is enabled. - -Grab the recording network traffics - -```js -const traffics = await I.grabRecordedNetworkTraffics(); -expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); -expect(traffics[0].response.status).to.equal(200); -expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); -``` - -Returns **[Array][30]** recorded network traffics +Returns **[Promise][26]<[string][18]>** ### grabSource @@ -1395,7 +1334,7 @@ Resumes test execution, so **should be used inside async function with `await`** let pageSource = await I.grabSource(); ``` -Returns **[Promise][27]<[string][18]>** source code +Returns **[Promise][26]<[string][18]>** source code ### grabTextFrom @@ -1412,7 +1351,7 @@ If multiple elements found returns first element. - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabTextFromAll @@ -1427,7 +1366,7 @@ let pins = await I.grabTextFromAll('#pin li'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabTitle @@ -1438,7 +1377,7 @@ Resumes test execution, so **should be used inside async with `await`** operator let title = await I.grabTitle(); ``` -Returns **[Promise][27]<[string][18]>** title +Returns **[Promise][26]<[string][18]>** title ### grabValueFrom @@ -1454,7 +1393,7 @@ let email = await I.grabValueFrom('input[name=email]'); - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabValueFromAll @@ -1469,7 +1408,7 @@ let inputs = await I.grabValueFromAll('//form/input'); - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabWebElements @@ -1484,7 +1423,7 @@ const webElements = await I.grabWebElements('#button'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<any>** WebElement of being used Web helper +Returns **[Promise][26]<any>** WebElement of being used Web helper ### moveCursorTo @@ -1501,8 +1440,8 @@ I.moveCursorTo('#submit', 5,5); - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. - `xOffset` - `yOffset` -- `offsetX` **[number][24]** (optional, `0` by default) X-axis offset. -- `offsetY` **[number][24]** (optional, `0` by default) Y-axis offset. +- `offsetX` **[number][23]** (optional, `0` by default) X-axis offset. +- `offsetY` **[number][23]** (optional, `0` by default) Y-axis offset. Returns **void** automatically synchronized promise through #recorder @@ -1527,7 +1466,7 @@ _Note:_ In case a text field or textarea is focused be aware that some browsers Presses a key in the browser (on a focused element). -_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][32]. +_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][31]. ```js I.pressKey('Backspace'); @@ -1586,7 +1525,7 @@ Some of the supported key names are: #### Parameters -- `key` **([string][18] | [Array][30]<[string][18]>)** key or array of keys to press. +- `key` **([string][18] | [Array][29]<[string][18]>)** key or array of keys to press. Returns **void** automatically synchronized promise through #recorder @@ -1594,7 +1533,7 @@ Returns **void** automatically synchronized promise through #recorder Presses a key in the browser and leaves it in a down state. -To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][33]). +To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][32]). ```js I.pressKeyDown('Control'); @@ -1612,7 +1551,7 @@ Returns **void** automatically synchronized promise through #recorder Releases a key in the browser which was previously set to a down state. -To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][33]). +To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][32]). ```js I.pressKeyDown('Control'); @@ -1645,8 +1584,8 @@ First parameter can be set to `maximize`. #### Parameters -- `width` **[number][24]** width in pixels or `maximize`. -- `height` **[number][24]** height in pixels. +- `width` **[number][23]** width in pixels or `maximize`. +- `height` **[number][23]** height in pixels. Returns **void** automatically synchronized promise through #recorder @@ -1730,7 +1669,7 @@ I.saveScreenshot('debug.png', true) //resizes to available scrollHeight and scro #### Parameters - `fileName` **[string][18]** file name to save. -- `fullPage` **[boolean][34]** (optional, `false` by default) flag to enable fullscreen screenshot mode. +- `fullPage` **[boolean][33]** (optional, `false` by default) flag to enable fullscreen screenshot mode. Returns **void** automatically synchronized promise through #recorder @@ -1747,7 +1686,7 @@ I.scrollIntoView('#submit', { behavior: "smooth", block: "center", inline: "cent #### Parameters - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -- `scrollIntoViewOptions` **(ScrollIntoViewOptions | [boolean][34])** either alignToTop=true|false or scrollIntoViewOptions. See [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView][35]. +- `scrollIntoViewOptions` **(ScrollIntoViewOptions | [boolean][33])** either alignToTop=true|false or scrollIntoViewOptions. See [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView][34]. Returns **void** automatically synchronized promise through #recorder @@ -1784,8 +1723,8 @@ I.scrollTo('#submit', 5, 5); #### Parameters - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -- `offsetX` **[number][24]** (optional, `0` by default) X-axis offset. -- `offsetY` **[number][24]** (optional, `0` by default) Y-axis offset. +- `offsetX` **[number][23]** (optional, `0` by default) X-axis offset. +- `offsetY` **[number][23]** (optional, `0` by default) Y-axis offset. Returns **void** automatically synchronized promise through #recorder @@ -2005,7 +1944,7 @@ I.seeNumberOfElements('#submitBtn', 1); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. +- `num` **[number][23]** number of elements. Returns **void** automatically synchronized promise through #recorder @@ -2025,7 +1964,7 @@ I.seeNumberOfVisibleElements('.buttons', 3); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. +- `num` **[number][23]** number of elements. Returns **void** automatically synchronized promise through #recorder @@ -2062,50 +2001,6 @@ I.seeTitleEquals('Test title.'); Returns **void** automatically synchronized promise through #recorder -### seeTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Verifies that a certain request is part of network traffic. - -```js -// checking the request url contains certain query strings -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -await I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, - }); -``` - -```js -// checking the request url contains certain post data -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -await I.seeTraffic({ - name: 'event', - url: 'https://cloudflareinsights.com/cdn-cgi/rum', - requestPostData: { - st: 2, - }, - }); -``` - -#### Parameters - -- `opts` **[Object][17]** options when checking the traffic network. - - `opts.name` **[string][18]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail. - - `opts.url` **[string][18]** Expected URL of request in network traffic - - `opts.parameters` **[Object][17]?** Expected parameters of that request in network traffic - - `opts.requestPostData` **[Object][17]?** Expected that request contains post data in network traffic - - `opts.timeout` **[number][24]?** Timeout to wait for request in seconds. Default is 10 seconds. - -Returns **void** automatically synchronized promise through #recorder - ### selectOption Selects an option in a drop-down select. @@ -2130,13 +2025,13 @@ I.selectOption('Which OS do you use?', ['Android', 'iOS']); #### Parameters - `select` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -- `option` **([string][18] | [Array][30]<any>)** visible text or value of option. +- `option` **([string][18] | [Array][29]<any>)** visible text or value of option. Returns **void** automatically synchronized promise through #recorder ### setCookie -Uses Selenium's JSON [cookie format][36]. +Uses Selenium's JSON [cookie format][35]. Sets cookie(s). Can be a single cookie object or an array of cookies: @@ -2153,52 +2048,10 @@ I.setCookie([ #### Parameters -- `cookie` **(Cookie | [Array][30]<Cookie>)** a cookie object or array of cookie objects. +- `cookie` **(Cookie | [Array][29]<Cookie>)** a cookie object or array of cookie objects. Returns **void** automatically synchronized promise through #recorder -### setGeoLocation - -This method is **deprecated**. - -Set the current geo location - -```js -I.setGeoLocation(121.21, 11.56); -I.setGeoLocation(121.21, 11.56, 10); -``` - -#### Parameters - -- `latitude` **[number][24]** to set. -- `longitude` **[number][24]** to set -- `altitude` **[number][24]?** (optional, null by default) to set - -Returns **void** automatically synchronized promise through #recorder - -### startRecordingTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Starts recording the network traffics. -This also resets recorded network requests. - -```js -I.startRecordingTraffic(); -``` - -Returns **void** automatically synchronized promise through #recorder - -### stopRecordingTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Stops recording of network traffic. Recorded traffic is not flashed. - -```js -I.stopRecordingTraffic(); -``` - ### switchTo Switches frame or in case of null locator reverts to parent. @@ -2225,8 +2078,8 @@ I.switchToNextTab(2); #### Parameters -- `num` **[number][24]?** (optional) number of tabs to switch forward, default: 1. -- `sec` **([number][24] | null)?** (optional) time in seconds to wait. +- `num` **[number][23]?** (optional) number of tabs to switch forward, default: 1. +- `sec` **([number][23] | null)?** (optional) time in seconds to wait. Returns **void** automatically synchronized promise through #recorder @@ -2241,8 +2094,8 @@ I.switchToPreviousTab(2); #### Parameters -- `num` **[number][24]?** (optional) number of tabs to switch backward, default: 1. -- `sec` **[number][24]??** (optional) time in seconds to wait. +- `num` **[number][23]?** (optional) number of tabs to switch backward, default: 1. +- `sec` **[number][23]??** (optional) time in seconds to wait. Returns **void** automatically synchronized promise through #recorder @@ -2268,7 +2121,7 @@ await I.switchToWindow( window ); Types out the given text into an active field. To slow down typing use a second parameter, to set interval between key presses. -_Note:_ Should be used when [`fillField`][32] is not an option. +_Note:_ Should be used when [`fillField`][31] is not an option. ```js // passing in a string @@ -2287,8 +2140,8 @@ I.type(secret('123456')); #### Parameters - `keys` -- `delay` **[number][24]?** (optional) delay in ms between key presses -- `key` **([string][18] | [Array][30]<[string][18]>)** or array of keys to type. +- `delay` **[number][23]?** (optional) delay in ms between key presses +- `key` **([string][18] | [Array][29]<[string][18]>)** or array of keys to type. Returns **void** automatically synchronized promise through #recorder @@ -2315,12 +2168,12 @@ Returns **void** automatically synchronized promise through #recorder ### useWebDriverTo -Use [webdriverio][37] API inside a test. +Use [webdriverio][36] API inside a test. First argument is a description of an action. Second argument is async function that gets this helper as parameter. -{ [`browser`][37]) } object from WebDriver API is available. +{ [`browser`][36]) } object from WebDriver API is available. ```js I.useWebDriverTo('open multiple windows', async ({ browser }) { @@ -2332,7 +2185,7 @@ I.useWebDriverTo('open multiple windows', async ({ browser }) { #### Parameters - `description` **[string][18]** used to show in logs. -- `fn` **[function][26]** async functuion that executed with WebDriver helper as argument +- `fn` **[function][25]** async functuion that executed with WebDriver helper as argument ### wait @@ -2344,7 +2197,7 @@ I.wait(2); // wait 2 secs #### Parameters -- `sec` **[number][24]** number of second to wait. +- `sec` **[number][23]** number of second to wait. Returns **void** automatically synchronized promise through #recorder @@ -2362,7 +2215,7 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `waitTimeout` -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2377,7 +2230,7 @@ I.waitForCookie("token"); #### Parameters - `name` **[string][18]** expected cookie name. -- `sec` **[number][24]** (optional, `3` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `3` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2393,7 +2246,7 @@ I.waitForDetached('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2410,7 +2263,7 @@ I.waitForElement('.btn.continue', 5); // wait for 5 secs #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2422,7 +2275,7 @@ Element can be located by CSS or XPath. #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional) time in seconds to wait, 1 by default. +- `sec` **[number][23]** (optional) time in seconds to wait, 1 by default. Returns **void** automatically synchronized promise through #recorder @@ -2443,9 +2296,9 @@ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and #### Parameters -- `fn` **([string][18] | [function][26])** to be executed in browser context. -- `argsOrSec` **([Array][30]<any> | [number][24])?** (optional, `1` by default) arguments for function or seconds. -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `fn` **([string][18] | [function][25])** to be executed in browser context. +- `argsOrSec` **([Array][29]<any> | [number][23])?** (optional, `1` by default) arguments for function or seconds. +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2461,7 +2314,7 @@ I.waitForInvisible('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2475,8 +2328,8 @@ I.waitForNumberOfTabs(2); #### Parameters -- `expectedTabs` **[number][24]** expecting the number of tabs. -- `sec` **[number][24]** number of secs to wait. +- `expectedTabs` **[number][23]** expecting the number of tabs. +- `sec` **[number][23]** number of secs to wait. Returns **void** automatically synchronized promise through #recorder @@ -2494,7 +2347,7 @@ I.waitForText('Thank you, form has been submitted', 5, '#modal'); #### Parameters - `text` **[string][18]** to wait for. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait - `context` **([string][18] | [object][17])?** (optional) element located by CSS|XPath|strict locator. Returns **void** automatically synchronized promise through #recorder @@ -2511,7 +2364,7 @@ I.waitForValue('//input', "GoodValue"); - `field` **([string][18] | [object][17])** input field. - `value` **[string][18]** expected value. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2527,7 +2380,7 @@ I.waitForVisible('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2542,7 +2395,7 @@ I.waitInUrl('/info', 2); #### Parameters - `urlPart` **[string][18]** value to check. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2557,8 +2410,8 @@ I.waitNumberOfVisibleElements('a', 3); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `num` **[number][23]** number of elements. +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2574,7 +2427,7 @@ I.waitToHide('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2590,7 +2443,7 @@ I.waitUrlEquals('http://127.0.0.1:8000/info'); #### Parameters - `urlPart` **[string][18]** value to check. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2638,40 +2491,36 @@ Returns **void** automatically synchronized promise through #recorder [22]: https://webdriver.io/docs/timeouts.html -[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp - -[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number - -[25]: https://vuejs.org/v2/api/#Vue-nextTick +[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[24]: https://vuejs.org/v2/api/#Vue-nextTick -[27]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise +[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[28]: http://webdriver.io/api/protocol/execute.html +[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise -[29]: https://playwright.dev/docs/api/class-locator#locator-focus +[27]: http://webdriver.io/api/protocol/execute.html -[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[28]: https://playwright.dev/docs/api/class-locator#locator-focus -[31]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined +[29]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array -[32]: #fillfield +[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined -[33]: #click +[31]: #fillfield -[34]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[32]: #click -[35]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView +[33]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[36]: https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object +[34]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView -[37]: https://webdriver.io/docs/api.html +[35]: https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object -[38]: http://codecept.io/acceptance/#smartwait +[36]: https://webdriver.io/docs/api.html -[39]: http://webdriver.io/docs/timeouts.html +[37]: http://codecept.io/acceptance/#smartwait -[40]: https://webdriver.io/docs/configuration/#loglevel +[38]: http://webdriver.io/docs/timeouts.html -[41]: https://webdriver.io/docs/automationProtocols/#devtools-protocol +[39]: https://webdriver.io/docs/configuration/#loglevel diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index 9bd253405..2065deaec 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -72,7 +72,6 @@ const webRoot = 'body' * @prop {object} [timeouts] [WebDriver timeouts](http://webdriver.io/docs/timeouts.html) defined as hash. * @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). * @prop {string} [logLevel=silent] - level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: https://webdriver.io/docs/configuration/#loglevel - * @prop {boolean} [devtoolsProtocol=false] - enable devtools protocol. Default: false. More info: https://webdriver.io/docs/automationProtocols/#devtools-protocol. */ const config = {} @@ -180,7 +179,6 @@ const config = {} * WebDriver : { * url: "http://localhost", * browser: "chrome", - * devtoolsProtocol: true, * desiredCapabilities: { * chromeOptions: { * args: [ "--headless", "--disable-gpu", "--no-sandbox" ] @@ -614,11 +612,6 @@ class WebDriver extends Helper { delete this.options.capabilities.hostname delete this.options.capabilities.port delete this.options.capabilities.path - if (this.options.devtoolsProtocol) { - if (!['chrome', 'chromium'].includes(this.options.browser.toLowerCase())) - throw Error('The devtools protocol is only working with Chrome or Chromium') - this.options.automationProtocol = 'devtools' - } this.browser = await webdriverio.remote(this.options) } } catch (err) { @@ -649,11 +642,6 @@ class WebDriver extends Helper { this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase() } - if (this.options.automationProtocol) { - this.puppeteerBrowser = await this.browser.getPuppeteer() - this.page = (await this.puppeteerBrowser.pages())[0] - } - return this.browser } @@ -1143,10 +1131,6 @@ class WebDriver extends Helper { assertElementExists(res, field, 'Field') const elem = usingFirstElement(res) highlightActiveElement.call(this, elem) - if (this.options.automationProtocol) { - const curentValue = await elem.getValue() - return elem.setValue(curentValue + value.toString()) - } return elem.addValue(value.toString()) } @@ -1159,9 +1143,6 @@ class WebDriver extends Helper { assertElementExists(res, field, 'Field') const elem = usingFirstElement(res) highlightActiveElement.call(this, elem) - if (this.options.automationProtocol) { - return elem.setValue('') - } return elem.clearValue(getElementId(elem)) } @@ -1231,7 +1212,7 @@ class WebDriver extends Helper { const el = usingFirstElement(res) // Remote Upload (when running Selenium Server) - if (this.options.remoteFileUpload && !this.options.automationProtocol) { + if (this.options.remoteFileUpload) { try { this.debugSection('File', 'Uploading file to remote server') file = await this.browser.uploadFile(file) @@ -2593,9 +2574,6 @@ class WebDriver extends Helper { async switchTo(locator) { this.browser.isInsideFrame = true if (Number.isInteger(locator)) { - if (this.options.automationProtocol) { - return this.browser.switchToFrame(locator + 1) - } return this.browser.switchToFrame(locator) } if (!locator) { @@ -2734,44 +2712,6 @@ class WebDriver extends Helper { return this.executeScript(getScrollPosition) } - /** - * This method is **deprecated**. - * - * - * {{> setGeoLocation }} - */ - async setGeoLocation(latitude, longitude) { - if (!this.options.automationProtocol) { - console.log(`setGeoLocation deprecated: - * This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#setgeolocation - * Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`) - return - } - this.geoLocation = { latitude, longitude } - - await this.browser.call(async () => { - const pages = await this.puppeteerBrowser.pages() - await pages[0].setGeolocation({ latitude, longitude }) - }) - } - - /** - * This method is **deprecated**. - * - * {{> grabGeoLocation }} - * - */ - async grabGeoLocation() { - if (!this.options.automationProtocol) { - console.log(`grabGeoLocation deprecated: - * This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#getgeolocation - * Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`) - return - } - if (!this.geoLocation) return 'No GeoLocation is set!' - return this.geoLocation - } - /** * {{> grabElementBoundingRect }} */ @@ -2810,127 +2750,6 @@ class WebDriver extends Helper { runInWeb(fn) { return fn() } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> flushNetworkTraffics }} - */ - flushNetworkTraffics() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - this.requests = [] - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> stopRecordingTraffic }} - */ - stopRecordingTraffic() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - this.page.removeAllListeners('request') - this.recording = false - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> startRecordingTraffic }} - * - */ - async startRecordingTraffic() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - this.flushNetworkTraffics() - this.recording = true - this.recordedAtLeastOnce = true - - await this.page.setRequestInterception(true) - - this.page.on('request', (request) => { - const information = { - url: request.url(), - method: request.method(), - requestHeaders: request.headers(), - requestPostData: request.postData(), - response: request.response(), - } - - this.debugSection('REQUEST: ', JSON.stringify(information)) - - if (typeof information.requestPostData === 'object') { - information.requestPostData = JSON.parse(information.requestPostData) - } - request.continue() - this.requests.push(information) - }) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> grabRecordedNetworkTraffics }} - */ - async grabRecordedNetworkTraffics() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - return grabRecordedNetworkTraffics.call(this) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> seeTraffic }} - */ - async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - await seeTraffic.call(this, ...arguments) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> dontSeeTraffic }} - * - */ - dontSeeTraffic({ name, url }) { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } - dontSeeTraffic.call(this, ...arguments) - } } async function proceedSee(assertType, text, context, strict = false) { diff --git a/lib/plugin/coverage.js b/lib/plugin/coverage.js index d4e8da72d..9f2bd8e6e 100644 --- a/lib/plugin/coverage.js +++ b/lib/plugin/coverage.js @@ -143,9 +143,6 @@ module.exports = function (config) { const helper = helpers[helperName] - if (helperName === 'WebDriver' && !helper.config.devtoolsProtocol) - throw Error('Coverage is currently supporting the WebDriver running with Devtools protocol.') - const v8Helper = v8CoverageHelpers[helperName] const coverageOptions = { diff --git a/package.json b/package.json index 3492267df..fa7278d77 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "test:unit:webbapi:puppeteer": "mocha test/helper/Puppeteer_test.js", "test:unit:webbapi:webDriver": "mocha test/helper/WebDriver_test.js", "test:unit:webbapi:webDriver:noSeleniumServer": "mocha test/helper/WebDriver.noSeleniumServer_test.js", - "test:unit:webbapi:webDriver:devtools": "mocha test/helper/WebDriver_devtools_test.js --exit", "test:unit:webbapi:testCafe": "mocha test/helper/TestCafe_test.js", "test:unit:expect": "mocha test/helper/Expect_test.js", "test:plugin": "mocha test/plugin/plugin_test.js", @@ -90,7 +89,6 @@ "cross-spawn": "7.0.5", "css-to-xpath": "0.1.0", "csstoxpath": "1.6.0", - "devtools": "8.40.2", "envinfo": "7.14.0", "escape-string-regexp": "4.0.0", "figures": "3.2.0", @@ -167,7 +165,7 @@ "typedoc-plugin-markdown": "4.2.10", "typescript": "5.6.3", "wdio-docker-service": "1.5.0", - "webdriverio": "8.39.1", + "webdriverio": "8.40.6", "xml2js": "0.6.2", "xpath": "0.0.34" }, diff --git a/test/acceptance/codecept.WebDriver.devtools.coverage.js b/test/acceptance/codecept.WebDriver.devtools.coverage.js deleted file mode 100644 index 3d771815d..000000000 --- a/test/acceptance/codecept.WebDriver.devtools.coverage.js +++ /dev/null @@ -1,49 +0,0 @@ -const TestHelper = require('../support/TestHelper') - -module.exports.config = { - tests: './*_test.js', - timeout: 10000, - output: './output', - helpers: { - WebDriver: { - url: TestHelper.siteUrl(), - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - }, - ScreenshotSessionHelper: { - require: '../support/ScreenshotSessionHelper.js', - outputPath: './output', - }, - ExpectHelper: {}, - }, - include: {}, - mocha: {}, - name: 'acceptance', - plugins: { - screenshotOnFail: { - enabled: true, - }, - coverage: { - enabled: true, - debug: true, - name: 'CodeceptJS Coverage Report', - sourceFilter: '**/src/**', - sourcePath: { - 'todomvc-react/': '', - 'todomvc.com/examples/react/': '', - }, - outputDir: 'output/coverage', - }, - }, - gherkin: { - features: './gherkin/*.feature', - steps: ['./gherkin/steps.js'], - }, -} diff --git a/test/acceptance/codecept.WebDriver.devtools.js b/test/acceptance/codecept.WebDriver.devtools.js deleted file mode 100644 index 755e950d5..000000000 --- a/test/acceptance/codecept.WebDriver.devtools.js +++ /dev/null @@ -1,42 +0,0 @@ -const TestHelper = require('../support/TestHelper') - -module.exports.config = { - tests: './*_test.js', - timeout: 10000, - output: './output', - helpers: { - WebDriver: { - url: TestHelper.siteUrl(), - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - }, - ScreenshotSessionHelper: { - require: '../support/ScreenshotSessionHelper.js', - outputPath: './output', - }, - ExpectHelper: {}, - }, - include: {}, - bootstrap: async () => - new Promise((done) => { - setTimeout(done, 5000) - }), // let's wait for selenium - mocha: {}, - name: 'acceptance', - plugins: { - screenshotOnFail: { - enabled: true, - }, - }, - gherkin: { - features: './gherkin/*.feature', - steps: ['./gherkin/steps.js'], - }, -} diff --git a/test/helper/WebDriver.noSeleniumServer_test.js b/test/helper/WebDriver.noSeleniumServer_test.js index af956c1da..208201865 100644 --- a/test/helper/WebDriver.noSeleniumServer_test.js +++ b/test/helper/WebDriver.noSeleniumServer_test.js @@ -1204,16 +1204,6 @@ describe('WebDriver - No Selenium server started', function () { }) }) - describe('GeoLocation', () => { - // deprecated JSON Wire method commands - it.skip('should set the geoLocation', async () => { - await wd.setGeoLocation(37.4043, -122.0748) - const geoLocation = await wd.grabGeoLocation() - assert.equal(geoLocation.latitude, 37.4043, 'The latitude is not properly set') - assert.equal(geoLocation.longitude, -122.0748, 'The longitude is not properly set') - }) - }) - describe('#grabElementBoundingRect', () => { it('should get the element size', async () => { await wd.amOnPage('/form/hidden') diff --git a/test/helper/WebDriver_devtools_test.js b/test/helper/WebDriver_devtools_test.js deleted file mode 100644 index 84dad90a1..000000000 --- a/test/helper/WebDriver_devtools_test.js +++ /dev/null @@ -1,1251 +0,0 @@ -const assert = require('assert') - -let expect -import('chai').then((chai) => { - expect = chai.expect -}) -const path = require('path') -const fs = require('fs') - -const TestHelper = require('../support/TestHelper') -const WebDriver = require('../../lib/helper/WebDriver') -const AssertionFailedError = require('../../lib/assert/error') -const webApiTests = require('./webapi') -const Secret = require('../../lib/secret') -global.codeceptjs = require('../../lib') - -const siteUrl = TestHelper.siteUrl() -let wd - -describe('WebDriver - Devtools Protocol', function () { - this.retries(1) - this.timeout(35000) - - before(() => { - global.codecept_dir = path.join(__dirname, '/../data') - try { - fs.unlinkSync(dataFile) - } catch (err) { - // continue regardless of error - } - - process.env.DevTools = 'true' - - wd = new WebDriver({ - url: siteUrl, - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - customLocatorStrategies: { - customSelector: (selector) => ({ 'element-6066-11e4-a52e-4f735466cecf': `${selector}-foobar` }), - }, - }) - }) - - beforeEach(async () => { - webApiTests.init({ I: wd, siteUrl }) - this.wdBrowser = await wd._before() - return this.wdBrowser - }) - - afterEach(async () => wd._after()) - - // load common test suite - webApiTests.tests() - - describe('customLocatorStrategies', () => { - it('should locate through custom selector', async () => { - const el = await this.wdBrowser.custom$('customSelector', '.test') - expect(el.elementId).to.equal('.test-foobar') - }) - - it('should include the custom strategy', async () => { - expect(wd.customLocatorStrategies.customSelector).to.not.be.undefined - }) - - it('should be added to the browser locator strategies', async () => { - expect(this.wdBrowser.addLocatorStrategy).to.not.be.undefined - }) - - it('throws on invalid custom selector', async () => { - try { - await wd.waitForEnabled({ madeUpSelector: '#text' }, 2) - } catch (e) { - expect(e.message).to.include('Please define "customLocatorStrategies"') - } - }) - }) - - describe('open page : #amOnPage', () => { - it('should open main page of configured site', async () => { - await wd.amOnPage('/') - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/`) - }) - - it('should open any page of configured site', async () => { - await wd.amOnPage('/info') - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/info`) - }) - - it('should open absolute url', async () => { - await wd.amOnPage(siteUrl) - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/`) - }) - }) - - describe('see text : #see', () => { - it('should fail when text is not on site', async () => { - await wd.amOnPage('/') - - try { - await wd.see('Something incredible!') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.include('web page') - } - - try { - await wd.dontSee('Welcome') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.include('web page') - } - }) - }) - - describe('check fields: #seeInField, #seeCheckboxIsChecked, ...', () => { - it('should throw error if field is not empty', async () => { - await wd.amOnPage('/form/empty') - - try { - await wd.seeInField('#empty_input', 'Ayayay') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.be.equal('expected fields by #empty_input to include "Ayayay"') - } - }) - - it('should check values in checkboxes', async () => { - await wd.amOnPage('/form/field_values') - await wd.dontSeeInField('checkbox[]', 'not seen one') - await wd.seeInField('checkbox[]', 'see test one') - await wd.dontSeeInField('checkbox[]', 'not seen two') - await wd.seeInField('checkbox[]', 'see test two') - await wd.dontSeeInField('checkbox[]', 'not seen three') - await wd.seeInField('checkbox[]', 'see test three') - }) - - it('should check values are the secret type in checkboxes', async () => { - await wd.amOnPage('/form/field_values') - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen one')) - await wd.seeInField('checkbox[]', Secret.secret('see test one')) - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen two')) - await wd.seeInField('checkbox[]', Secret.secret('see test two')) - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen three')) - await wd.seeInField('checkbox[]', Secret.secret('see test three')) - }) - - it('should check values with boolean', async () => { - await wd.amOnPage('/form/field_values') - await wd.seeInField('checkbox1', true) - await wd.dontSeeInField('checkbox1', false) - await wd.seeInField('checkbox2', false) - await wd.dontSeeInField('checkbox2', true) - await wd.seeInField('radio2', true) - await wd.dontSeeInField('radio2', false) - await wd.seeInField('radio3', false) - await wd.dontSeeInField('radio3', true) - }) - - it('should check values in radio', async () => { - await wd.amOnPage('/form/field_values') - await wd.seeInField('radio1', 'see test one') - await wd.dontSeeInField('radio1', 'not seen one') - await wd.dontSeeInField('radio1', 'not seen two') - await wd.dontSeeInField('radio1', 'not seen three') - }) - - it('should return error when element has no value attribute', async () => { - await wd.amOnPage('https://codecept.io/quickstart') - - try { - await wd.seeInField('#search_input_react', 'WebDriver1') - } catch (e) { - e.should.be.instanceOf(Error) - } - }) - }) - - describe('Force Right Click: #forceRightClick', () => { - it('it should forceRightClick', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('Lorem Ipsum') - await wd.see('right clicked') - }) - - it('it should forceRightClick by locator', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('.context a') - await wd.see('right clicked') - }) - - it('it should forceRightClick by locator and context', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('Lorem Ipsum', '.context') - await wd.see('right clicked') - }) - }) - - describe.skip('#pressKey, #pressKeyDown, #pressKeyUp', () => { - it('should be able to send special keys to element', async () => { - await wd.amOnPage('/form/field') - await wd.appendField('Name', '-') - - await wd.pressKey(['Right Shift', 'Home']) - await wd.pressKey('Delete') - - // Sequence only executes up to first non-modifier key ('Digit1') - await wd.pressKey(['SHIFT_RIGHT', 'Digit1', 'Digit4']) - await wd.pressKey('1') - await wd.pressKey('2') - await wd.pressKey('3') - await wd.pressKey('ArrowLeft') - await wd.pressKey('Left Arrow') - await wd.pressKey('arrow_left') - await wd.pressKeyDown('Shift') - await wd.pressKey('a') - await wd.pressKey('KeyB') - await wd.pressKeyUp('ShiftLeft') - await wd.pressKey('C') - await wd.seeInField('Name', '!ABC123') - }) - - it('should use modifier key based on operating system', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', 'value that is cleared using select all shortcut') - - await wd.pressKey(['CommandOrControl', 'A']) - await wd.pressKey('Backspace') - await wd.dontSeeInField('Name', 'value that is cleared using select all shortcut') - }) - - it('should show correct numpad or punctuation key when Shift modifier is active', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', '') - - await wd.pressKey(';') - await wd.pressKey(['Shift', ';']) - await wd.pressKey(['Shift', 'Semicolon']) - await wd.pressKey('=') - await wd.pressKey(['Shift', '=']) - await wd.pressKey(['Shift', 'Equal']) - await wd.pressKey('*') - await wd.pressKey(['Shift', '*']) - await wd.pressKey(['Shift', 'Multiply']) - await wd.pressKey('+') - await wd.pressKey(['Shift', '+']) - await wd.pressKey(['Shift', 'Add']) - await wd.pressKey(',') - await wd.pressKey(['Shift', ',']) - await wd.pressKey(['Shift', 'Comma']) - await wd.pressKey(['Shift', 'NumpadComma']) - await wd.pressKey(['Shift', 'Separator']) - await wd.pressKey('-') - await wd.pressKey(['Shift', '-']) - await wd.pressKey(['Shift', 'Subtract']) - await wd.pressKey('.') - await wd.pressKey(['Shift', '.']) - await wd.pressKey(['Shift', 'Decimal']) - await wd.pressKey(['Shift', 'Period']) - await wd.pressKey('/') - await wd.pressKey(['Shift', '/']) - await wd.pressKey(['Shift', 'Divide']) - await wd.pressKey(['Shift', 'Slash']) - - await wd.seeInField('Name', ';::=++***+++,<<<<-_-.>.>/?/?') - }) - - it('should show correct number key when Shift modifier is active', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', '') - - await wd.pressKey('0') - await wd.pressKeyDown('Shift') - await wd.pressKey('0') - await wd.pressKey('Digit0') - await wd.pressKeyUp('Shift') - - await wd.pressKey('1') - await wd.pressKeyDown('Shift') - await wd.pressKey('1') - await wd.pressKey('Digit1') - await wd.pressKeyUp('Shift') - - await wd.pressKey('2') - await wd.pressKeyDown('Shift') - await wd.pressKey('2') - await wd.pressKey('Digit2') - await wd.pressKeyUp('Shift') - - await wd.pressKey('3') - await wd.pressKeyDown('Shift') - await wd.pressKey('3') - await wd.pressKey('Digit3') - await wd.pressKeyUp('Shift') - - await wd.pressKey('4') - await wd.pressKeyDown('Shift') - await wd.pressKey('4') - await wd.pressKey('Digit4') - await wd.pressKeyUp('Shift') - - await wd.pressKey('5') - await wd.pressKeyDown('Shift') - await wd.pressKey('5') - await wd.pressKey('Digit5') - await wd.pressKeyUp('Shift') - - await wd.pressKey('6') - await wd.pressKeyDown('Shift') - await wd.pressKey('6') - await wd.pressKey('Digit6') - await wd.pressKeyUp('Shift') - - await wd.pressKey('7') - await wd.pressKeyDown('Shift') - await wd.pressKey('7') - await wd.pressKey('Digit7') - await wd.pressKeyUp('Shift') - - await wd.pressKey('8') - await wd.pressKeyDown('Shift') - await wd.pressKey('8') - await wd.pressKey('Digit8') - await wd.pressKeyUp('Shift') - - await wd.pressKey('9') - await wd.pressKeyDown('Shift') - await wd.pressKey('9') - await wd.pressKey('Digit9') - await wd.pressKeyUp('Shift') - - await wd.seeInField('Name', '0))1!!2@@3##4$$5%%6^^7&&8**9((') - }) - }) - - describe('#seeInSource, #grabSource', () => { - it('should check for text to be in HTML source', async () => { - await wd.amOnPage('/') - await wd.seeInSource('