codeceptjs 2.3.4 → 2.4.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.
- package/CHANGELOG.md +52 -0
- package/README.md +28 -6
- package/bin/codecept.js +42 -0
- package/docs/advanced.md +45 -1
- package/docs/angular.md +3 -3
- package/docs/basics.md +162 -118
- package/docs/bdd.md +30 -5
- package/docs/best.md +8 -6
- package/docs/books.md +6 -1
- package/docs/build/Appium.js +95 -85
- package/docs/build/FileSystem.js +48 -3
- package/docs/build/GraphQL.js +3 -2
- package/docs/build/GraphQLDataFactory.js +1 -0
- package/docs/build/Mochawesome.js +3 -2
- package/docs/build/MockRequest.js +23 -5
- package/docs/build/Nightmare.js +87 -128
- package/docs/build/Protractor.js +107 -155
- package/docs/build/Puppeteer.js +190 -174
- package/docs/build/REST.js +13 -9
- package/docs/build/SeleniumWebdriver.js +0 -17
- package/docs/build/TestCafe.js +164 -158
- package/docs/build/WebDriver.js +236 -211
- package/docs/build/WebDriverIO.js +218 -187
- package/docs/changelog.md +57 -1
- package/docs/commands.md +41 -2
- package/docs/community-helpers.md +12 -1
- package/docs/configuration.md +5 -2
- package/docs/continuous-integration.md +22 -0
- package/docs/{helpers.md → custom-helpers.md} +16 -10
- package/docs/data.md +7 -6
- package/docs/detox.md +6 -6
- package/docs/email.md +4 -2
- package/docs/examples.md +22 -3
- package/docs/helpers/ApiDataFactory.md +15 -13
- package/docs/helpers/Appium.md +1011 -468
- package/docs/helpers/Detox.md +33 -26
- package/docs/helpers/FileSystem.md +43 -13
- package/docs/helpers/GraphQL.md +17 -15
- package/docs/helpers/GraphQLDataFactory.md +15 -13
- package/docs/helpers/Mochawesome.md +3 -1
- package/docs/helpers/MockRequest.md +37 -19
- package/docs/helpers/Nightmare.md +129 -240
- package/docs/helpers/Polly.md +1 -1
- package/docs/helpers/Protractor.md +157 -298
- package/docs/helpers/Puppeteer.md +216 -335
- package/docs/helpers/REST.md +29 -24
- package/docs/helpers/TestCafe.md +137 -235
- package/docs/helpers/WebDriver.md +250 -347
- package/docs/hooks.md +14 -10
- package/docs/index.md +112 -0
- package/docs/installation.md +3 -1
- package/docs/locators.md +19 -8
- package/docs/mobile-react-native-locators.md +2 -2
- package/docs/mobile.md +5 -3
- package/docs/nightmare.md +2 -1
- package/docs/pageobjects.md +4 -2
- package/docs/parallel.md +4 -2
- package/docs/plugins.md +41 -15
- package/docs/puppeteer.md +8 -6
- package/docs/quickstart.md +130 -0
- package/docs/react.md +4 -2
- package/docs/reports.md +6 -4
- package/docs/testcafe.md +10 -8
- package/docs/translation.md +4 -2
- package/docs/ui.md +56 -0
- package/docs/videos.md +11 -2
- package/docs/visual.md +7 -5
- package/docs/vue.md +121 -0
- package/docs/webapi/appendField.mustache +1 -1
- package/docs/webapi/attachFile.mustache +1 -1
- package/docs/webapi/checkOption.mustache +2 -2
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/click.mustache +2 -2
- package/docs/webapi/clickLink.mustache +2 -2
- package/docs/webapi/dontSee.mustache +1 -2
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/dontSeeElement.mustache +1 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/doubleClick.mustache +2 -2
- package/docs/webapi/downloadFile.mustache +1 -1
- package/docs/webapi/dragSlider.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +2 -1
- package/docs/webapi/executeScript.mustache +2 -1
- package/docs/webapi/fillField.mustache +1 -1
- package/docs/webapi/grabAttributeFrom.mustache +1 -1
- package/docs/webapi/grabBrowserLogs.mustache +1 -1
- package/docs/webapi/grabCookie.mustache +2 -2
- package/docs/webapi/grabCssPropertyFrom.mustache +1 -1
- package/docs/webapi/grabHTMLFrom.mustache +1 -1
- package/docs/webapi/grabNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/grabPageScrollPosition.mustache +1 -1
- package/docs/webapi/grabTextFrom.mustache +2 -2
- package/docs/webapi/grabValueFrom.mustache +1 -1
- package/docs/webapi/moveCursorTo.mustache +3 -3
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
- package/docs/webapi/rightClick.mustache +2 -2
- package/docs/webapi/saveScreenshot.mustache +1 -1
- package/docs/webapi/scrollIntoView.mustache +10 -0
- package/docs/webapi/scrollTo.mustache +3 -3
- package/docs/webapi/see.mustache +1 -1
- package/docs/webapi/seeAttributesOnElements.mustache +1 -1
- package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/webapi/seeNumberOfElements.mustache +1 -1
- package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/seeTextEquals.mustache +8 -0
- package/docs/webapi/selectOption.mustache +2 -2
- package/docs/webapi/switchTo.mustache +1 -1
- package/docs/webapi/uncheckOption.mustache +2 -2
- package/docs/webapi/waitForClickable.mustache +10 -0
- package/docs/webapi/waitForDetached.mustache +2 -2
- package/docs/webapi/waitForElement.mustache +2 -2
- package/docs/webapi/waitForEnabled.mustache +2 -2
- package/docs/webapi/waitForFunction.mustache +2 -2
- package/docs/webapi/waitForInvisible.mustache +2 -2
- package/docs/webapi/waitForText.mustache +2 -2
- package/docs/webapi/waitForValue.mustache +1 -1
- package/docs/webapi/waitForVisible.mustache +2 -2
- package/docs/webapi/waitInUrl.mustache +1 -1
- package/docs/webapi/waitNumberOfVisibleElements.mustache +2 -2
- package/docs/webapi/waitToHide.mustache +2 -2
- package/docs/webapi/waitUntil.mustache +3 -2
- package/docs/webapi/waitUrlEquals.mustache +1 -1
- package/docs/webdriver.md +20 -18
- package/docs/wiki/.git/FETCH_HEAD +1 -0
- package/docs/wiki/.git/HEAD +1 -0
- package/docs/wiki/.git/ORIG_HEAD +1 -0
- package/docs/wiki/.git/config +11 -0
- package/docs/wiki/.git/description +1 -0
- package/docs/wiki/.git/hooks/applypatch-msg.sample +15 -0
- package/docs/wiki/.git/hooks/commit-msg.sample +24 -0
- package/docs/wiki/.git/hooks/fsmonitor-watchman.sample +114 -0
- package/docs/wiki/.git/hooks/post-update.sample +8 -0
- package/docs/wiki/.git/hooks/pre-applypatch.sample +14 -0
- package/docs/wiki/.git/hooks/pre-commit.sample +49 -0
- package/docs/wiki/.git/hooks/pre-push.sample +53 -0
- package/docs/wiki/.git/hooks/pre-rebase.sample +169 -0
- package/docs/wiki/.git/hooks/pre-receive.sample +24 -0
- package/docs/wiki/.git/hooks/prepare-commit-msg.sample +42 -0
- package/docs/wiki/.git/hooks/update.sample +128 -0
- package/docs/wiki/.git/index +0 -0
- package/docs/wiki/.git/info/exclude +6 -0
- package/docs/wiki/.git/logs/HEAD +4 -0
- package/docs/wiki/.git/logs/refs/heads/master +4 -0
- package/docs/wiki/.git/logs/refs/remotes/origin/HEAD +1 -0
- package/docs/wiki/.git/logs/refs/remotes/origin/master +3 -0
- package/docs/wiki/.git/objects/00/d216b0774d15db2d0a2a0d4ce249b5251acc55 +3 -0
- package/docs/wiki/.git/objects/09/01d87c5241905fdfe3493cfe8f04df4a2685ea +0 -0
- package/docs/wiki/.git/objects/0d/bdd0c20c4deb6a8cc81dbbf32ecf8c09238983 +2 -0
- package/docs/wiki/.git/objects/1a/c29e4fa82422c52392f22f0f2b8d1a759535bf +0 -0
- package/docs/wiki/.git/objects/27/12f92898d3e8f68e229b6cda76570d6c66d781 +0 -0
- package/docs/wiki/.git/objects/2d/dbe22c257166b648928eeb9460ecfb71ba702d +0 -0
- package/docs/wiki/.git/objects/2f/c942ec3773efd2678d9ff98035c61fcded81a1 +0 -0
- package/docs/wiki/.git/objects/40/a2856342c67796b48911a256b764fb06888b94 +5 -0
- package/docs/wiki/.git/objects/47/53181844fc4dc563cf3aa5e80462243cb58d38 +0 -0
- package/docs/wiki/.git/objects/4e/24a95fb2e4f8ffef51f19b694451a205c06f10 +3 -0
- package/docs/wiki/.git/objects/73/31ebd96f3c7e08a9f63f05a25f939afa0d4de1 +0 -0
- package/docs/wiki/.git/objects/86/19cbb2289caa502e33fccf0ed14eecf6ba2ba0 +0 -0
- package/docs/wiki/.git/objects/a4/72f797d9d74b87c9f71a2b1539d75bb07d1e35 +0 -0
- package/docs/wiki/.git/objects/c9/9f3e4bd227d6b050b2e416f9876df49583dbf6 +0 -0
- package/docs/wiki/.git/objects/ca/e609b4ef3e0ef85fcbe0d68d1a58246584b915 +0 -0
- package/docs/wiki/.git/objects/d5/8386ca72f6d550548f3d71d74e3ac73d5ad488 +0 -0
- package/docs/wiki/.git/objects/d9/c6874a6de524bdafeb563a20d847f4fdd59a86 +0 -0
- package/docs/wiki/.git/objects/f1/c944675bb38b40ae553b0be36c14674c79af54 +0 -0
- package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.idx +0 -0
- package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.pack +0 -0
- package/docs/wiki/.git/packed-refs +2 -0
- package/docs/wiki/.git/refs/heads/master +1 -0
- package/docs/wiki/.git/refs/remotes/origin/HEAD +1 -0
- package/docs/wiki/.git/refs/remotes/origin/master +1 -0
- package/docs/wiki/Books-&-Posts.md +27 -0
- package/docs/wiki/Community-Helpers.md +41 -0
- package/docs/wiki/Examples.md +138 -0
- package/docs/wiki/Home.md +11 -0
- package/docs/wiki/Release-process.md +25 -0
- package/docs/wiki/Roadmap.md +23 -0
- package/docs/wiki/Videos.md +19 -0
- package/lib/actor.js +18 -1
- package/lib/assert/error.js +3 -3
- package/lib/codecept.js +9 -6
- package/lib/command/configMigrate.js +7 -6
- package/lib/command/definitions.js +98 -350
- package/lib/command/generate.js +22 -17
- package/lib/command/gherkin/init.js +2 -1
- package/lib/command/gherkin/snippets.js +6 -6
- package/lib/command/gherkin/steps.js +0 -1
- package/lib/command/info.js +40 -0
- package/lib/command/init.js +54 -41
- package/lib/command/run-multiple.js +5 -4
- package/lib/command/run-rerun.js +39 -0
- package/lib/command/run-workers.js +4 -6
- package/lib/command/run.js +8 -18
- package/lib/command/utils.js +23 -2
- package/lib/command/workers/runTests.js +1 -2
- package/lib/config.js +10 -4
- package/lib/container.js +31 -6
- package/lib/data/dataTableArgument.js +31 -0
- package/lib/data/table.js +4 -0
- package/lib/event.js +65 -1
- package/lib/helper/Appium.js +52 -38
- package/lib/helper/FileSystem.js +48 -3
- package/lib/helper/GraphQL.js +3 -2
- package/lib/helper/GraphQLDataFactory.js +1 -0
- package/lib/helper/Mochawesome.js +3 -2
- package/lib/helper/MockRequest.js +23 -5
- package/lib/helper/Nightmare.js +5 -6
- package/lib/helper/Protractor.js +7 -8
- package/lib/helper/Puppeteer.js +76 -20
- package/lib/helper/REST.js +13 -9
- package/lib/helper/SeleniumWebdriver.js +0 -17
- package/lib/helper/TestCafe.js +84 -36
- package/lib/helper/WebDriver.js +113 -59
- package/lib/helper/WebDriverIO.js +43 -59
- package/lib/helper/clientscripts/nightmare.js +66 -4
- package/lib/helper/scripts/isElementClickable.js +24 -0
- package/lib/helper.js +34 -10
- package/lib/history.js +1 -1
- package/lib/hooks.js +2 -1
- package/lib/index.js +19 -0
- package/lib/interfaces/bdd.js +4 -0
- package/lib/interfaces/featureConfig.js +10 -3
- package/lib/interfaces/gherkin.js +6 -2
- package/lib/interfaces/scenarioConfig.js +17 -6
- package/lib/listener/config.js +1 -1
- package/lib/listener/exit.js +6 -0
- package/lib/listener/steps.js +0 -1
- package/lib/listener/trace.js +0 -1
- package/lib/locator.js +67 -2
- package/lib/output.js +53 -0
- package/lib/parser.js +2 -71
- package/lib/pause.js +3 -2
- package/lib/plugin/allure.js +41 -22
- package/lib/plugin/autoLogin.js +4 -1
- package/lib/plugin/pauseOnFail.js +38 -0
- package/lib/plugin/puppeteerCoverage.js +8 -7
- package/lib/plugin/screenshotOnFail.js +13 -8
- package/lib/plugin/stepByStepReport.js +7 -6
- package/lib/plugin/wdio.js +2 -1
- package/lib/recorder.js +85 -7
- package/lib/rerun.js +81 -0
- package/lib/secret.js +6 -0
- package/lib/session.js +9 -2
- package/lib/step.js +37 -2
- package/lib/store.js +5 -1
- package/lib/ui.js +34 -8
- package/lib/utils.js +6 -13
- package/lib/within.js +5 -0
- package/package.json +49 -29
- package/typings/Mocha.d.ts +21 -0
- package/typings/Protractor.d.ts +16 -0
- package/typings/index.d.ts +169 -0
- package/typings/jsdoc.conf.js +34 -0
- package/typings/jsdoc.namespace.js +29 -0
- package/typings/types.d.ts +9827 -0
- package/typings/utils.d.ts +7 -0
- package/docs/acceptance.md +0 -409
- package/docs/api/codecept.md +0 -75
- package/docs/api/config.md +0 -49
- package/docs/api/container.md +0 -66
- package/docs/api/helper.md +0 -116
- package/docs/api/output.md +0 -67
- package/docs/api/recorder.md +0 -63
- package/docs/helpers/SeleniumWebdriver.md +0 -92
- package/docs/helpers/WebDriverIO.md +0 -1671
package/docs/build/TestCafe.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const assert = require('assert');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const qrcode = require('qrcode-terminal');
|
|
5
6
|
const requireg = require('requireg');
|
|
6
7
|
const createTestCafe = require('testcafe');
|
|
7
8
|
const { Selector, ClientFunction } = require('testcafe');
|
|
8
|
-
const ElementNotFound = require('./errors/ElementNotFound');
|
|
9
9
|
|
|
10
|
+
const ElementNotFound = require('./errors/ElementNotFound');
|
|
10
11
|
const testControllerHolder = require('./testcafe/testControllerHolder');
|
|
11
12
|
const {
|
|
12
13
|
mapError,
|
|
@@ -67,6 +68,21 @@ const getHtmlSource = t => ClientFunction(() => document.getElementsByTagName('h
|
|
|
67
68
|
* }
|
|
68
69
|
* ```
|
|
69
70
|
*
|
|
71
|
+
* To use remote device you can provide 'remote' as browser parameter this will display a link with QR Code
|
|
72
|
+
* See https://devexpress.github.io/testcafe/documentation/recipes/test-on-remote-computers-and-mobile-devices.html
|
|
73
|
+
* #### Example #2: Remote browser connection
|
|
74
|
+
*
|
|
75
|
+
* ```js
|
|
76
|
+
* {
|
|
77
|
+
* helpers: {
|
|
78
|
+
* TestCafe : {
|
|
79
|
+
* url: "http://localhost",
|
|
80
|
+
* waitForTimeout: 15000,
|
|
81
|
+
* browser: "remote"
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
70
86
|
*
|
|
71
87
|
* ## Access From Helpers
|
|
72
88
|
*
|
|
@@ -96,7 +112,7 @@ class TestCafe extends Helper {
|
|
|
96
112
|
this.context = undefined; // TODO Not sure if this applies to testcafe
|
|
97
113
|
|
|
98
114
|
|
|
99
|
-
this.options =
|
|
115
|
+
this.options = {
|
|
100
116
|
url: 'http://localhost',
|
|
101
117
|
show: false,
|
|
102
118
|
browser: 'chrome',
|
|
@@ -108,7 +124,8 @@ class TestCafe extends Helper {
|
|
|
108
124
|
fullPageScreenshots: false,
|
|
109
125
|
disableScreenshots: false,
|
|
110
126
|
windowSize: undefined,
|
|
111
|
-
|
|
127
|
+
...config,
|
|
128
|
+
};
|
|
112
129
|
}
|
|
113
130
|
|
|
114
131
|
// TOOD Do a requirements check
|
|
@@ -130,12 +147,12 @@ class TestCafe extends Helper {
|
|
|
130
147
|
];
|
|
131
148
|
}
|
|
132
149
|
|
|
133
|
-
async
|
|
150
|
+
async _configureAndStartBrowser() {
|
|
134
151
|
this.dummyTestcafeFile = createTestFile(global.output_dir); // create a dummy test file to get hold of the test controller
|
|
135
152
|
|
|
136
153
|
this.iteration += 2; // Use different ports for each test run
|
|
137
154
|
// @ts-ignore
|
|
138
|
-
this.testcafe = await createTestCafe('
|
|
155
|
+
this.testcafe = await createTestCafe('', null, null);
|
|
139
156
|
|
|
140
157
|
this.debugSection('_before', 'Starting testcafe browser...');
|
|
141
158
|
|
|
@@ -143,6 +160,19 @@ class TestCafe extends Helper {
|
|
|
143
160
|
|
|
144
161
|
// TODO Do we have to cleanup the runner?
|
|
145
162
|
const runner = this.testcafe.createRunner();
|
|
163
|
+
|
|
164
|
+
this.options.browser !== 'remote' ? this._startBrowser(runner) : this._startRemoteBrowser(runner);
|
|
165
|
+
|
|
166
|
+
this.t = await testControllerHolder.get();
|
|
167
|
+
assert(this.t, 'Expected to have the testcafe test controller');
|
|
168
|
+
|
|
169
|
+
if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0) {
|
|
170
|
+
const dimensions = this.options.windowSize.split('x');
|
|
171
|
+
await this.t.resizeWindow(parseInt(dimensions[0], 10), parseInt(dimensions[1], 10));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async _startBrowser(runner) {
|
|
146
176
|
runner
|
|
147
177
|
.src(this.dummyTestcafeFile)
|
|
148
178
|
.screenshots(global.output_dir, !this.options.disableScreenshots)
|
|
@@ -166,16 +196,31 @@ class TestCafe extends Helper {
|
|
|
166
196
|
this.isRunning = false;
|
|
167
197
|
this.testcafe.close();
|
|
168
198
|
});
|
|
199
|
+
}
|
|
169
200
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
201
|
+
async _startRemoteBrowser(runner) {
|
|
202
|
+
const remoteConnection = await this.testcafe.createBrowserConnection();
|
|
203
|
+
console.log('Connect your device to the following URL or scan QR Code: ', remoteConnection.url);
|
|
204
|
+
qrcode.generate(remoteConnection.url);
|
|
205
|
+
remoteConnection.once('ready', () => {
|
|
206
|
+
runner
|
|
207
|
+
.src(this.dummyTestcafeFile)
|
|
208
|
+
.browsers(remoteConnection)
|
|
209
|
+
.reporter('minimal')
|
|
210
|
+
.run({
|
|
211
|
+
selectorTimeout: this.options.waitForTimeout,
|
|
212
|
+
skipJsErrors: true,
|
|
213
|
+
skipUncaughtErrors: true,
|
|
214
|
+
})
|
|
215
|
+
.catch((err) => {
|
|
216
|
+
this.debugSection('_before', `Error ${err.toString()}`);
|
|
217
|
+
this.isRunning = false;
|
|
218
|
+
this.testcafe.close();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
177
221
|
}
|
|
178
222
|
|
|
223
|
+
|
|
179
224
|
async _stopBrowser() {
|
|
180
225
|
this.debugSection('_after', 'Stopping testcafe browser...');
|
|
181
226
|
|
|
@@ -190,19 +235,20 @@ class TestCafe extends Helper {
|
|
|
190
235
|
this.isRunning = false;
|
|
191
236
|
}
|
|
192
237
|
|
|
193
|
-
_init() {
|
|
238
|
+
_init() {
|
|
239
|
+
}
|
|
194
240
|
|
|
195
241
|
async _beforeSuite() {
|
|
196
242
|
if (!this.options.restart && !this.options.manualStart && !this.isRunning) {
|
|
197
243
|
this.debugSection('Session', 'Starting singleton browser session');
|
|
198
|
-
return this.
|
|
244
|
+
return this._configureAndStartBrowser();
|
|
199
245
|
}
|
|
200
246
|
}
|
|
201
247
|
|
|
202
248
|
|
|
203
249
|
async _before() {
|
|
204
|
-
if (this.options.restart && !this.options.manualStart) return this.
|
|
205
|
-
if (!this.isRunning && !this.options.manualStart) return this.
|
|
250
|
+
if (this.options.restart && !this.options.manualStart) return this._configureAndStartBrowser();
|
|
251
|
+
if (!this.isRunning && !this.options.manualStart) return this._configureAndStartBrowser();
|
|
206
252
|
this.context = null;
|
|
207
253
|
}
|
|
208
254
|
|
|
@@ -269,7 +315,6 @@ class TestCafe extends Helper {
|
|
|
269
315
|
* ```
|
|
270
316
|
*
|
|
271
317
|
* @param {string} url url path or global url.
|
|
272
|
-
* {--end--}
|
|
273
318
|
*/
|
|
274
319
|
async amOnPage(url) {
|
|
275
320
|
if (!(/^\w+\:\/\//.test(url))) {
|
|
@@ -287,7 +332,6 @@ class TestCafe extends Helper {
|
|
|
287
332
|
*
|
|
288
333
|
* @param {number} width width in pixels or `maximize`.
|
|
289
334
|
* @param {number} height height in pixels.
|
|
290
|
-
* {--end--}
|
|
291
335
|
*/
|
|
292
336
|
async resizeWindow(width, height) {
|
|
293
337
|
if (width === 'maximize') {
|
|
@@ -320,9 +364,9 @@ class TestCafe extends Helper {
|
|
|
320
364
|
* I.click({css: 'nav a.login'});
|
|
321
365
|
* ```
|
|
322
366
|
*
|
|
323
|
-
* @param {
|
|
324
|
-
* @param {
|
|
325
|
-
*
|
|
367
|
+
* @param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
368
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
369
|
+
*
|
|
326
370
|
*
|
|
327
371
|
*/
|
|
328
372
|
async click(locator, context = null) {
|
|
@@ -336,7 +380,7 @@ class TestCafe extends Helper {
|
|
|
336
380
|
* ```js
|
|
337
381
|
* I.refreshPage();
|
|
338
382
|
* ```
|
|
339
|
-
*
|
|
383
|
+
*
|
|
340
384
|
*/
|
|
341
385
|
async refreshPage() {
|
|
342
386
|
// eslint-disable-next-line no-restricted-globals
|
|
@@ -351,9 +395,8 @@ class TestCafe extends Helper {
|
|
|
351
395
|
* I.waitForVisible('#popup');
|
|
352
396
|
* ```
|
|
353
397
|
*
|
|
354
|
-
* @param {
|
|
355
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
356
|
-
* {--end--}
|
|
398
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
399
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
357
400
|
*
|
|
358
401
|
*/
|
|
359
402
|
async waitForVisible(locator, sec) {
|
|
@@ -378,9 +421,9 @@ class TestCafe extends Helper {
|
|
|
378
421
|
* // or by strict locator
|
|
379
422
|
* I.fillField({css: 'form#login input[name=username]'}, 'John');
|
|
380
423
|
* ```
|
|
381
|
-
* @param {
|
|
424
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
382
425
|
* @param {string} value text value to fill.
|
|
383
|
-
*
|
|
426
|
+
*
|
|
384
427
|
*/
|
|
385
428
|
async fillField(field, value) {
|
|
386
429
|
const els = await findFields.call(this, field);
|
|
@@ -400,16 +443,16 @@ class TestCafe extends Helper {
|
|
|
400
443
|
* I.clearField('#email');
|
|
401
444
|
* ```
|
|
402
445
|
* @param {string|object} editable field located by label|name|CSS|XPath|strict locator.
|
|
403
|
-
* {--end--}
|
|
404
446
|
*/
|
|
405
447
|
async clearField(field) {
|
|
406
448
|
const els = await findFields.call(this, field);
|
|
407
449
|
assertElementExists(els, field, 'Field');
|
|
408
450
|
const el = await els.nth(0);
|
|
409
451
|
|
|
410
|
-
|
|
411
|
-
.
|
|
412
|
-
.pressKey('
|
|
452
|
+
const res = await this.t
|
|
453
|
+
.selectText(el)
|
|
454
|
+
.pressKey('delete');
|
|
455
|
+
return res;
|
|
413
456
|
}
|
|
414
457
|
|
|
415
458
|
/**
|
|
@@ -419,9 +462,8 @@ class TestCafe extends Helper {
|
|
|
419
462
|
* ```js
|
|
420
463
|
* I.appendField('#myTextField', 'appended');
|
|
421
464
|
* ```
|
|
422
|
-
* @param {
|
|
465
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator
|
|
423
466
|
* @param {string} value text value to append.
|
|
424
|
-
* {--end--}
|
|
425
467
|
*
|
|
426
468
|
*/
|
|
427
469
|
async appendField(field, value) {
|
|
@@ -444,9 +486,8 @@ class TestCafe extends Helper {
|
|
|
444
486
|
* I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
|
|
445
487
|
* ```
|
|
446
488
|
*
|
|
447
|
-
* @param {
|
|
489
|
+
* @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
|
|
448
490
|
* @param {string} pathToFile local file path relative to codecept.json config file.
|
|
449
|
-
* {--end--}
|
|
450
491
|
*
|
|
451
492
|
*/
|
|
452
493
|
async attachFile(field, pathToFile) {
|
|
@@ -471,8 +512,7 @@ class TestCafe extends Helper {
|
|
|
471
512
|
* I.pressKey(['Control','a']);
|
|
472
513
|
* ```
|
|
473
514
|
*
|
|
474
|
-
* @param {string|
|
|
475
|
-
* {--end--}
|
|
515
|
+
* @param {string|string[]} key key or array of keys to press.
|
|
476
516
|
*
|
|
477
517
|
* {{ keys }}
|
|
478
518
|
*/
|
|
@@ -493,10 +533,10 @@ class TestCafe extends Helper {
|
|
|
493
533
|
* I.moveCursorTo('#submit', 5,5);
|
|
494
534
|
* ```
|
|
495
535
|
*
|
|
496
|
-
* @param {
|
|
497
|
-
* @param {number} offsetX (optional, `0` by default) X-axis offset.
|
|
498
|
-
* @param {number} offsetY (optional, `0` by default) Y-axis offset.
|
|
499
|
-
*
|
|
536
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
|
|
537
|
+
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
538
|
+
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
539
|
+
*
|
|
500
540
|
*
|
|
501
541
|
*/
|
|
502
542
|
async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
|
|
@@ -519,9 +559,9 @@ class TestCafe extends Helper {
|
|
|
519
559
|
* I.doubleClick('.btn.edit');
|
|
520
560
|
* ```
|
|
521
561
|
*
|
|
522
|
-
* @param {
|
|
523
|
-
* @param {
|
|
524
|
-
*
|
|
562
|
+
* @param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
563
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
564
|
+
*
|
|
525
565
|
*
|
|
526
566
|
*/
|
|
527
567
|
async doubleClick(locator, context = null) {
|
|
@@ -550,9 +590,9 @@ class TestCafe extends Helper {
|
|
|
550
590
|
* I.rightClick('Click me', '.context');
|
|
551
591
|
* ```
|
|
552
592
|
*
|
|
553
|
-
* @param {
|
|
554
|
-
* @param {
|
|
555
|
-
*
|
|
593
|
+
* @param {CodeceptJS.LocatorOrString} locator clickable element located by CSS|XPath|strict locator.
|
|
594
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
595
|
+
*
|
|
556
596
|
*
|
|
557
597
|
*/
|
|
558
598
|
async rightClick(locator, context = null) {
|
|
@@ -580,9 +620,8 @@ class TestCafe extends Helper {
|
|
|
580
620
|
* I.checkOption('I Agree to Terms and Conditions');
|
|
581
621
|
* I.checkOption('agree', '//form');
|
|
582
622
|
* ```
|
|
583
|
-
* @param {
|
|
584
|
-
* @param {
|
|
585
|
-
* {--end--}
|
|
623
|
+
* @param {CodeceptJS.LocatorOrString} field checkbox located by label | name | CSS | XPath | strict locator.
|
|
624
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
|
|
586
625
|
*/
|
|
587
626
|
async checkOption(field, context = null) {
|
|
588
627
|
const el = await findCheckable.call(this, field, context);
|
|
@@ -603,9 +642,8 @@ class TestCafe extends Helper {
|
|
|
603
642
|
* I.uncheckOption('I Agree to Terms and Conditions');
|
|
604
643
|
* I.uncheckOption('agree', '//form');
|
|
605
644
|
* ```
|
|
606
|
-
* @param {
|
|
607
|
-
* @param {
|
|
608
|
-
* {--end--}
|
|
645
|
+
* @param {CodeceptJS.LocatorOrString} field checkbox located by label | name | CSS | XPath | strict locator.
|
|
646
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
|
|
609
647
|
*/
|
|
610
648
|
async uncheckOption(field, context = null) {
|
|
611
649
|
const el = await findCheckable.call(this, field, context);
|
|
@@ -626,8 +664,8 @@ class TestCafe extends Helper {
|
|
|
626
664
|
* I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
|
|
627
665
|
* ```
|
|
628
666
|
*
|
|
629
|
-
* @param {
|
|
630
|
-
*
|
|
667
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
668
|
+
*
|
|
631
669
|
*/
|
|
632
670
|
async seeCheckboxIsChecked(field) {
|
|
633
671
|
return proceedIsChecked.call(this, 'assert', field);
|
|
@@ -642,8 +680,8 @@ class TestCafe extends Helper {
|
|
|
642
680
|
* I.dontSeeCheckboxIsChecked('agree'); // located by name
|
|
643
681
|
* ```
|
|
644
682
|
*
|
|
645
|
-
* @param {
|
|
646
|
-
*
|
|
683
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
684
|
+
*
|
|
647
685
|
*/
|
|
648
686
|
async dontSeeCheckboxIsChecked(field) {
|
|
649
687
|
return proceedIsChecked.call(this, 'negate', field);
|
|
@@ -668,9 +706,8 @@ class TestCafe extends Helper {
|
|
|
668
706
|
* ```js
|
|
669
707
|
* I.selectOption('Which OS do you use?', ['Android', 'iOS']);
|
|
670
708
|
* ```
|
|
671
|
-
* @param {
|
|
672
|
-
* @param {string|
|
|
673
|
-
* {--end--}
|
|
709
|
+
* @param {CodeceptJS.LocatorOrString} select field located by label|name|CSS|XPath|strict locator.
|
|
710
|
+
* @param {string|Array<*>} option visible text or value of option.
|
|
674
711
|
*/
|
|
675
712
|
async selectOption(select, option) {
|
|
676
713
|
const els = await findFields.call(this, select);
|
|
@@ -698,8 +735,9 @@ class TestCafe extends Helper {
|
|
|
698
735
|
await this.t.click(optEl, clickOpts).catch(mapError);
|
|
699
736
|
continue;
|
|
700
737
|
}
|
|
701
|
-
|
|
702
|
-
} catch (err) {
|
|
738
|
+
// eslint-disable-next-line no-empty
|
|
739
|
+
} catch (err) {
|
|
740
|
+
}
|
|
703
741
|
|
|
704
742
|
try {
|
|
705
743
|
const sel = `[value="${opt}"]`;
|
|
@@ -707,8 +745,9 @@ class TestCafe extends Helper {
|
|
|
707
745
|
if (await optEl.count) {
|
|
708
746
|
await this.t.click(optEl, clickOpts).catch(mapError);
|
|
709
747
|
}
|
|
710
|
-
|
|
711
|
-
} catch (err) {
|
|
748
|
+
// eslint-disable-next-line no-empty
|
|
749
|
+
} catch (err) {
|
|
750
|
+
}
|
|
712
751
|
}
|
|
713
752
|
}
|
|
714
753
|
|
|
@@ -720,24 +759,22 @@ class TestCafe extends Helper {
|
|
|
720
759
|
* ```
|
|
721
760
|
*
|
|
722
761
|
* @param {string} url a fragment to check
|
|
723
|
-
* {--end--}
|
|
724
762
|
*/
|
|
725
763
|
async seeInCurrentUrl(url) {
|
|
726
764
|
stringIncludes('url').assert(url, await getPageUrl(this.t)().catch(mapError));
|
|
727
765
|
}
|
|
728
766
|
|
|
729
767
|
/**
|
|
730
|
-
|
|
768
|
+
* Checks that current url does not contain a provided fragment.
|
|
731
769
|
*
|
|
732
770
|
* @param {string} url value to check.
|
|
733
|
-
|
|
734
|
-
*/
|
|
771
|
+
*/
|
|
735
772
|
async dontSeeInCurrentUrl(url) {
|
|
736
773
|
stringIncludes('url').negate(url, await getPageUrl(this.t)().catch(mapError));
|
|
737
774
|
}
|
|
738
775
|
|
|
739
776
|
/**
|
|
740
|
-
|
|
777
|
+
* Checks that current url is equal to provided one.
|
|
741
778
|
* If a relative url provided, a configured url will be prepended to it.
|
|
742
779
|
* So both examples will work:
|
|
743
780
|
*
|
|
@@ -747,14 +784,13 @@ class TestCafe extends Helper {
|
|
|
747
784
|
* ```
|
|
748
785
|
*
|
|
749
786
|
* @param {string} url value to check.
|
|
750
|
-
|
|
751
|
-
*/
|
|
787
|
+
*/
|
|
752
788
|
async seeCurrentUrlEquals(url) {
|
|
753
789
|
urlEquals(this.options.url).assert(url, await getPageUrl(this.t)().catch(mapError));
|
|
754
790
|
}
|
|
755
791
|
|
|
756
792
|
/**
|
|
757
|
-
|
|
793
|
+
* Checks that current url is not equal to provided one.
|
|
758
794
|
* If a relative url provided, a configured url will be prepended to it.
|
|
759
795
|
*
|
|
760
796
|
* ```js
|
|
@@ -763,8 +799,7 @@ class TestCafe extends Helper {
|
|
|
763
799
|
* ```
|
|
764
800
|
*
|
|
765
801
|
* @param {string} url value to check.
|
|
766
|
-
|
|
767
|
-
*/
|
|
802
|
+
*/
|
|
768
803
|
async dontSeeCurrentUrlEquals(url) {
|
|
769
804
|
urlEquals(this.options.url).negate(url, await getPageUrl(this.t)().catch(mapError));
|
|
770
805
|
}
|
|
@@ -779,8 +814,7 @@ class TestCafe extends Helper {
|
|
|
779
814
|
* I.see('Register', {css: 'form.register'}); // use strict locator
|
|
780
815
|
* ```
|
|
781
816
|
* @param {string} text expected on page.
|
|
782
|
-
* @param {
|
|
783
|
-
* {--end--}
|
|
817
|
+
* @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
|
|
784
818
|
*
|
|
785
819
|
*/
|
|
786
820
|
async see(text, context = null) {
|
|
@@ -806,9 +840,8 @@ class TestCafe extends Helper {
|
|
|
806
840
|
* ```
|
|
807
841
|
*
|
|
808
842
|
* @param {string} text which is not present.
|
|
809
|
-
* @param {
|
|
810
|
-
*
|
|
811
|
-
* {--end--}
|
|
843
|
+
* @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator in which to perfrom search.
|
|
844
|
+
*
|
|
812
845
|
*
|
|
813
846
|
*/
|
|
814
847
|
async dontSee(text, context = null) {
|
|
@@ -831,8 +864,7 @@ class TestCafe extends Helper {
|
|
|
831
864
|
* ```js
|
|
832
865
|
* I.seeElement('#modal');
|
|
833
866
|
* ```
|
|
834
|
-
* @param {
|
|
835
|
-
* {--end--}
|
|
867
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
|
|
836
868
|
*/
|
|
837
869
|
async seeElement(locator) {
|
|
838
870
|
const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists;
|
|
@@ -848,8 +880,7 @@ class TestCafe extends Helper {
|
|
|
848
880
|
* I.dontSeeElement('.modal'); // modal is not shown
|
|
849
881
|
* ```
|
|
850
882
|
*
|
|
851
|
-
* @param {
|
|
852
|
-
* {--end--}
|
|
883
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|Strict locator.
|
|
853
884
|
*/
|
|
854
885
|
async dontSeeElement(locator) {
|
|
855
886
|
const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists;
|
|
@@ -865,8 +896,8 @@ class TestCafe extends Helper {
|
|
|
865
896
|
* ```js
|
|
866
897
|
* I.seeElementInDOM('#modal');
|
|
867
898
|
* ```
|
|
868
|
-
* @param {
|
|
869
|
-
*
|
|
899
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
900
|
+
*
|
|
870
901
|
*/
|
|
871
902
|
async seeElementInDOM(locator) {
|
|
872
903
|
const exists = (await findElements.call(this, this.context, locator)).exists;
|
|
@@ -882,8 +913,7 @@ class TestCafe extends Helper {
|
|
|
882
913
|
* I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
|
|
883
914
|
* ```
|
|
884
915
|
*
|
|
885
|
-
* @param {
|
|
886
|
-
* {--end--}
|
|
916
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|Strict locator.
|
|
887
917
|
*/
|
|
888
918
|
async dontSeeElementInDOM(locator) {
|
|
889
919
|
const exists = (await findElements.call(this, this.context, locator)).exists;
|
|
@@ -900,9 +930,9 @@ class TestCafe extends Helper {
|
|
|
900
930
|
* I.seeNumberOfVisibleElements('.buttons', 3);
|
|
901
931
|
* ```
|
|
902
932
|
*
|
|
903
|
-
* @param {
|
|
933
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
904
934
|
* @param {number} num number of elements.
|
|
905
|
-
*
|
|
935
|
+
*
|
|
906
936
|
*
|
|
907
937
|
*/
|
|
908
938
|
async seeNumberOfVisibleElements(locator, num) {
|
|
@@ -919,9 +949,8 @@ class TestCafe extends Helper {
|
|
|
919
949
|
* let numOfElements = await I.grabNumberOfVisibleElements('p');
|
|
920
950
|
* ```
|
|
921
951
|
*
|
|
922
|
-
* @param {
|
|
952
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
|
|
923
953
|
* @returns {Promise<number>} number of visible elements
|
|
924
|
-
* {--end--}
|
|
925
954
|
*/
|
|
926
955
|
async grabNumberOfVisibleElements(locator) {
|
|
927
956
|
const count = (await findElements.call(this, this.context, locator)).filterVisible().count;
|
|
@@ -938,9 +967,9 @@ class TestCafe extends Helper {
|
|
|
938
967
|
* I.seeInField('form input[type=hidden]','hidden_value');
|
|
939
968
|
* I.seeInField('#searchform input','Search');
|
|
940
969
|
* ```
|
|
941
|
-
* @param {
|
|
970
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
942
971
|
* @param {string} value value to check.
|
|
943
|
-
*
|
|
972
|
+
*
|
|
944
973
|
*/
|
|
945
974
|
async seeInField(field, value) {
|
|
946
975
|
// const expectedValue = findElements.call(this, this.context, field).value;
|
|
@@ -962,9 +991,8 @@ class TestCafe extends Helper {
|
|
|
962
991
|
* I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
|
|
963
992
|
* ```
|
|
964
993
|
*
|
|
965
|
-
* @param {
|
|
994
|
+
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
966
995
|
* @param {string} value value to check.
|
|
967
|
-
* {--end--}
|
|
968
996
|
*/
|
|
969
997
|
async dontSeeInField(field, value) {
|
|
970
998
|
// const expectedValue = findElements.call(this, this.context, field).value;
|
|
@@ -998,7 +1026,6 @@ class TestCafe extends Helper {
|
|
|
998
1026
|
* I.seeInSource('<h1>Green eggs & ham</h1>');
|
|
999
1027
|
* ```
|
|
1000
1028
|
* @param {string} text value to check.
|
|
1001
|
-
* {--end--}
|
|
1002
1029
|
*/
|
|
1003
1030
|
async seeInSource(text) {
|
|
1004
1031
|
const source = await getHtmlSource(this.t)();
|
|
@@ -1013,7 +1040,7 @@ class TestCafe extends Helper {
|
|
|
1013
1040
|
* ```
|
|
1014
1041
|
*
|
|
1015
1042
|
* @param {string} value to check.
|
|
1016
|
-
*
|
|
1043
|
+
*
|
|
1017
1044
|
*/
|
|
1018
1045
|
async dontSeeInSource(text) {
|
|
1019
1046
|
const source = await getHtmlSource(this.t)();
|
|
@@ -1032,8 +1059,7 @@ class TestCafe extends Helper {
|
|
|
1032
1059
|
* ```
|
|
1033
1060
|
*
|
|
1034
1061
|
* @param {string} fileName file name to save.
|
|
1035
|
-
* @param {boolean} fullPage (optional, `false` by default) flag to enable fullscreen screenshot mode.
|
|
1036
|
-
* {--end--}
|
|
1062
|
+
* @param {boolean} [fullPage=false] (optional, `false` by default) flag to enable fullscreen screenshot mode.
|
|
1037
1063
|
*/
|
|
1038
1064
|
async saveScreenshot(fileName, fullPage) {
|
|
1039
1065
|
// TODO Implement full page screenshots
|
|
@@ -1054,7 +1080,6 @@ class TestCafe extends Helper {
|
|
|
1054
1080
|
* ```
|
|
1055
1081
|
*
|
|
1056
1082
|
* @param {number} sec number of second to wait.
|
|
1057
|
-
* {--end--}
|
|
1058
1083
|
*/
|
|
1059
1084
|
async wait(sec) {
|
|
1060
1085
|
return new Promise(((done) => {
|
|
@@ -1088,8 +1113,9 @@ class TestCafe extends Helper {
|
|
|
1088
1113
|
* ```
|
|
1089
1114
|
*
|
|
1090
1115
|
* @param {string|function} fn function to be executed in browser context.
|
|
1091
|
-
* @param ...
|
|
1092
|
-
* {
|
|
1116
|
+
* @param {...any} args to be passed to function.
|
|
1117
|
+
* @return {Promise<any>}
|
|
1118
|
+
*
|
|
1093
1119
|
*
|
|
1094
1120
|
* If a function returns a Promise It will wait for it resolution.
|
|
1095
1121
|
*/
|
|
@@ -1107,9 +1133,8 @@ class TestCafe extends Helper {
|
|
|
1107
1133
|
* ```
|
|
1108
1134
|
* If multiple elements found returns an array of texts.
|
|
1109
1135
|
*
|
|
1110
|
-
* @param locator element located by CSS|XPath|strict locator.
|
|
1111
|
-
* @returns {Promise<string>} attribute value
|
|
1112
|
-
* {--end--}
|
|
1136
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1137
|
+
* @returns {Promise<string|string[]>} attribute value
|
|
1113
1138
|
*/
|
|
1114
1139
|
async grabTextFrom(locator) {
|
|
1115
1140
|
const sel = await findElements.call(this, this.context, locator);
|
|
@@ -1134,15 +1159,14 @@ class TestCafe extends Helper {
|
|
|
1134
1159
|
* ```js
|
|
1135
1160
|
* let hint = await I.grabAttributeFrom('#tooltip', 'title');
|
|
1136
1161
|
* ```
|
|
1137
|
-
* @param {
|
|
1162
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1138
1163
|
* @param {string} attr attribute name.
|
|
1139
1164
|
* @returns {Promise<string>} attribute value
|
|
1140
|
-
* {--end--}
|
|
1141
1165
|
*/
|
|
1142
1166
|
async grabAttributeFrom(locator, attr) {
|
|
1143
1167
|
const sel = await findElements.call(this, this.context, locator);
|
|
1144
1168
|
assertElementExists(sel);
|
|
1145
|
-
return (await sel.nth(0)).
|
|
1169
|
+
return (await sel.nth(0)).getAttribute(attr);
|
|
1146
1170
|
}
|
|
1147
1171
|
|
|
1148
1172
|
/**
|
|
@@ -1152,12 +1176,13 @@ class TestCafe extends Helper {
|
|
|
1152
1176
|
* ```js
|
|
1153
1177
|
* let email = await I.grabValueFrom('input[name=email]');
|
|
1154
1178
|
* ```
|
|
1155
|
-
* @param {
|
|
1179
|
+
* @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
|
|
1156
1180
|
* @returns {Promise<string>} attribute value
|
|
1157
|
-
* {--end--}
|
|
1158
1181
|
*/
|
|
1159
1182
|
async grabValueFrom(locator) {
|
|
1160
|
-
|
|
1183
|
+
const sel = await findElements.call(this, this.context, locator);
|
|
1184
|
+
assertElementExists(sel);
|
|
1185
|
+
return (await sel.nth(0)).value;
|
|
1161
1186
|
}
|
|
1162
1187
|
|
|
1163
1188
|
/**
|
|
@@ -1169,7 +1194,6 @@ class TestCafe extends Helper {
|
|
|
1169
1194
|
* ```
|
|
1170
1195
|
*
|
|
1171
1196
|
* @returns {Promise<string>} source code
|
|
1172
|
-
* {--end--}
|
|
1173
1197
|
*/
|
|
1174
1198
|
async grabSource() {
|
|
1175
1199
|
return ClientFunction(() => document.documentElement.innerHTML).with({ boundTestRun: this.t })();
|
|
@@ -1198,7 +1222,6 @@ class TestCafe extends Helper {
|
|
|
1198
1222
|
* ```
|
|
1199
1223
|
*
|
|
1200
1224
|
* @returns {Promise<string>} current URL
|
|
1201
|
-
* {--end--}
|
|
1202
1225
|
*/
|
|
1203
1226
|
async grabCurrentUrl() {
|
|
1204
1227
|
return ClientFunction(() => document.location.href).with({ boundTestRun: this.t })();
|
|
@@ -1212,8 +1235,7 @@ class TestCafe extends Helper {
|
|
|
1212
1235
|
* let { x, y } = await I.grabPageScrollPosition();
|
|
1213
1236
|
* ```
|
|
1214
1237
|
*
|
|
1215
|
-
* @returns {Promise<
|
|
1216
|
-
* {--end--}
|
|
1238
|
+
* @returns {Promise<Object<string, *>>} scroll position
|
|
1217
1239
|
*/
|
|
1218
1240
|
async grabPageScrollPosition() {
|
|
1219
1241
|
return ClientFunction(() => ({ x: window.pageXOffset, y: window.pageYOffset })).with({ boundTestRun: this.t })();
|
|
@@ -1225,7 +1247,7 @@ class TestCafe extends Helper {
|
|
|
1225
1247
|
* ```js
|
|
1226
1248
|
* I.scrollPageToTop();
|
|
1227
1249
|
* ```
|
|
1228
|
-
*
|
|
1250
|
+
*
|
|
1229
1251
|
*/
|
|
1230
1252
|
scrollPageToTop() {
|
|
1231
1253
|
return ClientFunction(() => window.scrollTo(0, 0)).with({ boundTestRun: this.t })().catch(mapError);
|
|
@@ -1237,7 +1259,7 @@ class TestCafe extends Helper {
|
|
|
1237
1259
|
* ```js
|
|
1238
1260
|
* I.scrollPageToBottom();
|
|
1239
1261
|
* ```
|
|
1240
|
-
*
|
|
1262
|
+
*
|
|
1241
1263
|
*/
|
|
1242
1264
|
scrollPageToBottom() {
|
|
1243
1265
|
return ClientFunction(() => {
|
|
@@ -1259,10 +1281,9 @@ class TestCafe extends Helper {
|
|
|
1259
1281
|
* I.scrollTo('#submit', 5, 5);
|
|
1260
1282
|
* ```
|
|
1261
1283
|
*
|
|
1262
|
-
* @param {
|
|
1263
|
-
* @param {number} offsetX (optional, `0` by default) X-axis offset.
|
|
1264
|
-
* @param {number} offsetY (optional, `0` by default) Y-axis offset.
|
|
1265
|
-
* {--end--}
|
|
1284
|
+
* @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
|
|
1285
|
+
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
1286
|
+
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
1266
1287
|
*/
|
|
1267
1288
|
async scrollTo(locator, offsetX = 0, offsetY = 0) {
|
|
1268
1289
|
if (typeof locator === 'number' && typeof offsetX === 'number') {
|
|
@@ -1300,8 +1321,7 @@ class TestCafe extends Helper {
|
|
|
1300
1321
|
* I.switchTo(); // switch back to main page
|
|
1301
1322
|
* ```
|
|
1302
1323
|
*
|
|
1303
|
-
* @param {
|
|
1304
|
-
* {--end--}
|
|
1324
|
+
* @param {?CodeceptJS.LocatorOrString} [locator=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
1305
1325
|
*/
|
|
1306
1326
|
async switchTo(locator) {
|
|
1307
1327
|
if (Number.isInteger(locator)) {
|
|
@@ -1326,7 +1346,6 @@ class TestCafe extends Helper {
|
|
|
1326
1346
|
* ```
|
|
1327
1347
|
*
|
|
1328
1348
|
* @param {object} cookie a cookie object.
|
|
1329
|
-
* {--end--}
|
|
1330
1349
|
*/
|
|
1331
1350
|
async setCookie(cookie) {
|
|
1332
1351
|
if (Array.isArray(cookie)) {
|
|
@@ -1351,7 +1370,7 @@ class TestCafe extends Helper {
|
|
|
1351
1370
|
* ```
|
|
1352
1371
|
*
|
|
1353
1372
|
* @param {string} name cookie name.
|
|
1354
|
-
*
|
|
1373
|
+
*
|
|
1355
1374
|
*
|
|
1356
1375
|
*/
|
|
1357
1376
|
async seeCookie(name) {
|
|
@@ -1367,7 +1386,6 @@ class TestCafe extends Helper {
|
|
|
1367
1386
|
* ```
|
|
1368
1387
|
*
|
|
1369
1388
|
* @param {string} name cookie name.
|
|
1370
|
-
* {--end--}
|
|
1371
1389
|
*/
|
|
1372
1390
|
async dontSeeCookie(name) {
|
|
1373
1391
|
const cookie = await this.grabCookie(name);
|
|
@@ -1377,16 +1395,15 @@ class TestCafe extends Helper {
|
|
|
1377
1395
|
/**
|
|
1378
1396
|
* Gets a cookie object by name.
|
|
1379
1397
|
* If none provided gets all cookies.
|
|
1380
|
-
*
|
|
1398
|
+
* Resumes test execution, so **should be used inside async with `await`** operator.
|
|
1381
1399
|
*
|
|
1382
1400
|
* ```js
|
|
1383
1401
|
* let cookie = await I.grabCookie('auth');
|
|
1384
1402
|
* assert(cookie.value, '123456');
|
|
1385
1403
|
* ```
|
|
1386
1404
|
*
|
|
1387
|
-
* @param [name=null] cookie name.
|
|
1405
|
+
* @param {?string} [name=null] cookie name.
|
|
1388
1406
|
* @returns {Promise<string>} attribute value
|
|
1389
|
-
* {--end--}
|
|
1390
1407
|
*
|
|
1391
1408
|
* Returns cookie in JSON format. If name not passed returns all cookies for this domain.
|
|
1392
1409
|
*/
|
|
@@ -1416,8 +1433,7 @@ class TestCafe extends Helper {
|
|
|
1416
1433
|
* I.clearCookie('test');
|
|
1417
1434
|
* ```
|
|
1418
1435
|
*
|
|
1419
|
-
* @param {string} cookie (optional, `null` by default) cookie name
|
|
1420
|
-
* {--end--}
|
|
1436
|
+
* @param {?string} [cookie=null] (optional, `null` by default) cookie name
|
|
1421
1437
|
*/
|
|
1422
1438
|
async clearCookie(cookieName) {
|
|
1423
1439
|
const clearCookies = ClientFunction(() => {
|
|
@@ -1444,8 +1460,7 @@ class TestCafe extends Helper {
|
|
|
1444
1460
|
* ```
|
|
1445
1461
|
*
|
|
1446
1462
|
* @param {string} urlPart value to check.
|
|
1447
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1448
|
-
* {--end--}
|
|
1463
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1449
1464
|
*/
|
|
1450
1465
|
async waitInUrl(urlPart, sec = null) {
|
|
1451
1466
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1470,8 +1485,7 @@ class TestCafe extends Helper {
|
|
|
1470
1485
|
* ```
|
|
1471
1486
|
*
|
|
1472
1487
|
* @param {string} urlPart value to check.
|
|
1473
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1474
|
-
* {--end--}
|
|
1488
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1475
1489
|
*/
|
|
1476
1490
|
async waitUrlEquals(urlPart, sec = null) {
|
|
1477
1491
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1507,9 +1521,9 @@ class TestCafe extends Helper {
|
|
|
1507
1521
|
* ```
|
|
1508
1522
|
*
|
|
1509
1523
|
* @param {string|function} fn to be executed in browser context.
|
|
1510
|
-
* @param {
|
|
1511
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1512
|
-
*
|
|
1524
|
+
* @param {any[]|number} [argsOrSec] (optional, `1` by default) arguments for function or seconds.
|
|
1525
|
+
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
1526
|
+
*
|
|
1513
1527
|
*/
|
|
1514
1528
|
async waitForFunction(fn, argsOrSec = null, sec = null) {
|
|
1515
1529
|
let args = [];
|
|
@@ -1522,10 +1536,7 @@ class TestCafe extends Helper {
|
|
|
1522
1536
|
}
|
|
1523
1537
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
1524
1538
|
|
|
1525
|
-
const clientFn = createClientFunction((
|
|
1526
|
-
const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
|
|
1527
|
-
return currUrl.indexOf(urlPart) > -1;
|
|
1528
|
-
}, args);
|
|
1539
|
+
const clientFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
|
|
1529
1540
|
|
|
1530
1541
|
return waitForFunction(clientFn, waitTimeout);
|
|
1531
1542
|
}
|
|
@@ -1537,10 +1548,9 @@ class TestCafe extends Helper {
|
|
|
1537
1548
|
* I.waitNumberOfVisibleElements('a', 3);
|
|
1538
1549
|
* ```
|
|
1539
1550
|
*
|
|
1540
|
-
* @param {
|
|
1551
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1541
1552
|
* @param {number} num number of elements.
|
|
1542
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1543
|
-
* {--end--}
|
|
1553
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1544
1554
|
*/
|
|
1545
1555
|
async waitNumberOfVisibleElements(locator, num, sec) {
|
|
1546
1556
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1560,9 +1570,8 @@ class TestCafe extends Helper {
|
|
|
1560
1570
|
* I.waitForElement('.btn.continue', 5); // wait for 5 secs
|
|
1561
1571
|
* ```
|
|
1562
1572
|
*
|
|
1563
|
-
* @param {
|
|
1564
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1565
|
-
* {--end--}
|
|
1573
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1574
|
+
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
1566
1575
|
*/
|
|
1567
1576
|
async waitForElement(locator, sec) {
|
|
1568
1577
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1580,9 +1589,8 @@ class TestCafe extends Helper {
|
|
|
1580
1589
|
* I.waitToHide('#popup');
|
|
1581
1590
|
* ```
|
|
1582
1591
|
*
|
|
1583
|
-
* @param {
|
|
1584
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1585
|
-
* {--end--}
|
|
1592
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1593
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1586
1594
|
*/
|
|
1587
1595
|
async waitToHide(locator, sec) {
|
|
1588
1596
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1600,9 +1608,8 @@ class TestCafe extends Helper {
|
|
|
1600
1608
|
* I.waitForInvisible('#popup');
|
|
1601
1609
|
* ```
|
|
1602
1610
|
*
|
|
1603
|
-
* @param {
|
|
1604
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1605
|
-
* {--end--}
|
|
1611
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1612
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1606
1613
|
*/
|
|
1607
1614
|
async waitForInvisible(locator, sec) {
|
|
1608
1615
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1623,9 +1630,8 @@ class TestCafe extends Helper {
|
|
|
1623
1630
|
* ```
|
|
1624
1631
|
*
|
|
1625
1632
|
* @param {string }text to wait for.
|
|
1626
|
-
* @param {number} sec (optional, `1` by default) time in seconds to wait
|
|
1627
|
-
* @param {
|
|
1628
|
-
* {--end--}
|
|
1633
|
+
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
1634
|
+
* @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator.
|
|
1629
1635
|
*
|
|
1630
1636
|
*/
|
|
1631
1637
|
async waitForText(text, sec = null, context = null) {
|
|
@@ -1657,7 +1663,7 @@ async function waitForFunction(browserFn, waitTimeout) {
|
|
|
1657
1663
|
let result;
|
|
1658
1664
|
try {
|
|
1659
1665
|
result = await browserFn();
|
|
1660
|
-
|
|
1666
|
+
// eslint-disable-next-line no-empty
|
|
1661
1667
|
} catch (err) {
|
|
1662
1668
|
throw new Error(`Error running function ${err.toString()}`);
|
|
1663
1669
|
}
|