codeceptjs 2.1.3 → 2.2.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 +125 -37
- package/README.md +15 -22
- package/bin/codecept.js +4 -1
- package/docs/acceptance.md +44 -1
- package/docs/advanced.md +1 -1
- package/docs/angular.md +6 -9
- package/docs/basics.md +388 -75
- package/docs/bdd.md +4 -3
- package/docs/best.md +1 -1
- package/docs/books.md +31 -0
- package/docs/build/Appium.js +215 -176
- package/docs/build/Nightmare.js +618 -489
- package/docs/build/Polly.js +189 -0
- package/docs/build/Protractor.js +747 -608
- package/docs/build/Puppeteer.js +914 -633
- package/docs/build/REST.js +1 -1
- package/docs/build/TestCafe.js +1835 -0
- package/docs/build/WebDriver.js +861 -805
- package/docs/build/WebDriverIO.js +616 -617
- package/docs/changelog.md +410 -316
- package/docs/commands.md +6 -6
- package/docs/community-helpers.md +2 -0
- package/docs/detox.md +235 -0
- package/docs/examples.md +23 -0
- package/docs/helpers/ApiDataFactory.md +11 -10
- package/docs/helpers/Appium.md +130 -61
- package/docs/helpers/Detox.md +579 -0
- package/docs/helpers/FileSystem.md +2 -1
- package/docs/helpers/Mochawesome.md +1 -0
- package/docs/helpers/Nightmare.md +348 -128
- package/docs/helpers/Polly.md +85 -0
- package/docs/helpers/Protractor.md +451 -184
- package/docs/helpers/Puppeteer-firefox.md +55 -0
- package/docs/helpers/Puppeteer.md +619 -183
- package/docs/helpers/REST.md +17 -16
- package/docs/helpers/SeleniumWebdriver.md +9 -8
- package/docs/helpers/TestCafe.md +1168 -0
- package/docs/helpers/WebDriver.md +600 -291
- package/docs/helpers/WebDriverIO.md +393 -278
- package/docs/helpers.md +37 -18
- package/docs/locators.md +2 -0
- package/docs/mobile-react-native-locators.md +64 -0
- package/docs/mobile.md +5 -0
- package/docs/plugins.md +54 -13
- package/docs/puppeteer.md +74 -26
- package/docs/quickstart.md +47 -12
- package/docs/react.md +67 -0
- package/docs/reports.md +1 -1
- package/docs/{webapi/_keys.mustache → shared/keys.mustache} +0 -0
- package/docs/shared/react.mustache +1 -0
- package/docs/testcafe.md +157 -0
- package/docs/videos.md +19 -0
- package/docs/webapi/amOnPage.mustache +1 -1
- package/docs/webapi/appendField.mustache +2 -2
- package/docs/webapi/attachFile.mustache +2 -2
- package/docs/webapi/checkOption.mustache +2 -2
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/clearField.mustache +1 -1
- package/docs/webapi/click.mustache +2 -2
- package/docs/webapi/clickLink.mustache +3 -3
- package/docs/webapi/dontSee.mustache +6 -3
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +7 -1
- package/docs/webapi/dontSeeCookie.mustache +5 -1
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +6 -1
- package/docs/webapi/dontSeeElement.mustache +5 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +5 -1
- package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +7 -2
- package/docs/webapi/dontSeeInSource.mustache +5 -1
- package/docs/webapi/dontSeeInTitle.mustache +5 -1
- package/docs/webapi/doubleClick.mustache +2 -2
- package/docs/webapi/downloadFile.mustache +2 -2
- package/docs/webapi/dragAndDrop.mustache +2 -2
- package/docs/webapi/dragSlider.mustache +2 -2
- package/docs/webapi/executeAsyncScript.mustache +1 -1
- package/docs/webapi/executeScript.mustache +1 -1
- package/docs/webapi/fillField.mustache +2 -2
- package/docs/webapi/grabAttributeFrom.mustache +3 -2
- package/docs/webapi/grabBrowserLogs.mustache +3 -1
- package/docs/webapi/grabCookie.mustache +2 -1
- package/docs/webapi/grabCssPropertyFrom.mustache +3 -2
- package/docs/webapi/grabCurrentUrl.mustache +3 -1
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +19 -0
- package/docs/webapi/grabHTMLFrom.mustache +2 -1
- package/docs/webapi/grabNumberOfOpenTabs.mustache +4 -2
- package/docs/webapi/grabNumberOfVisibleElements.mustache +3 -2
- package/docs/webapi/grabPageScrollPosition.mustache +3 -1
- package/docs/webapi/grabSource.mustache +3 -1
- package/docs/webapi/grabTextFrom.mustache +2 -1
- package/docs/webapi/grabTitle.mustache +3 -1
- package/docs/webapi/grabValueFrom.mustache +2 -1
- package/docs/webapi/moveCursorTo.mustache +3 -3
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/resizeWindow.mustache +2 -2
- package/docs/webapi/rightClick.mustache +2 -2
- package/docs/webapi/saveScreenshot.mustache +3 -3
- package/docs/webapi/say.mustache +2 -2
- package/docs/webapi/scrollPageToBottom.mustache +1 -1
- package/docs/webapi/scrollPageToTop.mustache +1 -1
- package/docs/webapi/scrollTo.mustache +3 -3
- package/docs/webapi/see.mustache +2 -2
- package/docs/webapi/seeAttributesOnElements.mustache +3 -3
- package/docs/webapi/seeCheckboxIsChecked.mustache +2 -1
- package/docs/webapi/seeCookie.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +2 -2
- package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInCurrentUrl.mustache +1 -1
- package/docs/webapi/seeInField.mustache +2 -2
- package/docs/webapi/seeInSource.mustache +1 -1
- package/docs/webapi/seeInTitle.mustache +5 -1
- package/docs/webapi/seeNumberOfElements.mustache +10 -0
- package/docs/webapi/seeNumberOfVisibleElements.mustache +2 -2
- package/docs/webapi/selectOption.mustache +2 -2
- package/docs/webapi/setCookie.mustache +1 -1
- package/docs/webapi/switchTo.mustache +6 -1
- package/docs/webapi/uncheckOption.mustache +2 -2
- package/docs/webapi/wait.mustache +1 -2
- package/docs/webapi/waitForDetached.mustache +3 -3
- package/docs/webapi/waitForElement.mustache +2 -2
- package/docs/webapi/waitForEnabled.mustache +1 -1
- package/docs/webapi/waitForFunction.mustache +3 -3
- package/docs/webapi/waitForInvisible.mustache +3 -3
- package/docs/webapi/waitForText.mustache +3 -3
- package/docs/webapi/waitForValue.mustache +3 -3
- package/docs/webapi/waitForVisible.mustache +3 -3
- package/docs/webapi/waitInUrl.mustache +2 -2
- package/docs/webapi/waitNumberOfVisibleElements.mustache +3 -3
- package/docs/webapi/waitToHide.mustache +3 -3
- package/docs/webapi/waitUntil.mustache +3 -3
- package/docs/webapi/waitUrlEquals.mustache +2 -2
- package/docs/webdriver.md +453 -0
- package/lib/codecept.js +11 -9
- package/lib/command/definitions.js +183 -30
- package/lib/command/gherkin/snippets.js +29 -9
- package/lib/command/init.js +31 -9
- package/lib/command/run-multiple.js +46 -59
- package/lib/command/utils.js +1 -1
- package/lib/container.js +30 -4
- package/lib/data/dataScenarioConfig.js +18 -0
- package/lib/helper/Appium.js +24 -24
- package/lib/helper/Nightmare.js +81 -84
- package/lib/helper/Polly.js +189 -0
- package/lib/helper/Protractor.js +96 -86
- package/lib/helper/Puppeteer.js +238 -113
- package/lib/helper/REST.js +1 -1
- package/lib/helper/TestCafe.js +1257 -0
- package/lib/helper/WebDriver.js +217 -277
- package/lib/helper/WebDriverIO.js +75 -75
- package/lib/helper/clientscripts/nightmare.js +8 -0
- package/lib/helper/extras/React.js +55 -0
- package/lib/helper/testcafe/testControllerHolder.js +42 -0
- package/lib/helper/testcafe/testcafe-utils.js +63 -0
- package/lib/history.js +39 -0
- package/lib/hooks.js +25 -1
- package/lib/interfaces/gherkin.js +17 -1
- package/lib/interfaces/scenarioConfig.js +2 -2
- package/lib/listener/config.js +3 -3
- package/lib/locator.js +6 -0
- package/lib/pause.js +22 -1
- package/lib/plugin/allure.js +63 -0
- package/lib/plugin/autoLogin.js +65 -16
- package/lib/plugin/puppeteerCoverage.js +6 -1
- package/lib/plugin/stepByStepReport.js +4 -3
- package/lib/scenario.js +23 -17
- package/lib/step.js +5 -2
- package/lib/ui.js +1 -1
- package/lib/utils.js +70 -20
- package/package.json +20 -19
- package/translations/de-DE.js +69 -0
- package/translations/index.js +1 -0
- package/docs/video.md +0 -26
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -11,7 +11,6 @@ const {
|
|
|
11
11
|
xpathLocator,
|
|
12
12
|
ucfirst,
|
|
13
13
|
fileExists,
|
|
14
|
-
clearString,
|
|
15
14
|
chunkArray,
|
|
16
15
|
convertCssPropertiesToCamelCase,
|
|
17
16
|
screenshotOutputFolder,
|
|
@@ -25,11 +24,13 @@ const ElementNotFound = require('./errors/ElementNotFound');
|
|
|
25
24
|
const RemoteBrowserConnectionRefused = require('./errors/RemoteBrowserConnectionRefused');
|
|
26
25
|
const Popup = require('./extras/Popup');
|
|
27
26
|
const Console = require('./extras/Console');
|
|
27
|
+
const findReact = require('./extras/React');
|
|
28
28
|
const axios = require('axios');
|
|
29
29
|
const fs = require('fs');
|
|
30
|
-
|
|
30
|
+
const fsExtra = require('fs-extra');
|
|
31
31
|
|
|
32
32
|
let puppeteer;
|
|
33
|
+
let perfTiming;
|
|
33
34
|
const popupStore = new Popup();
|
|
34
35
|
const consoleLogStore = new Console();
|
|
35
36
|
|
|
@@ -40,6 +41,8 @@ const consoleLogStore = new Console();
|
|
|
40
41
|
*
|
|
41
42
|
* Requires `puppeteer` package to be installed.
|
|
42
43
|
*
|
|
44
|
+
* > Experiemental Firefox support [can be activated](https://codecept.io/helpers/Puppeteer-firefox).
|
|
45
|
+
*
|
|
43
46
|
* ## Configuration
|
|
44
47
|
*
|
|
45
48
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -54,11 +57,13 @@ const consoleLogStore = new Console();
|
|
|
54
57
|
* * `keepCookies`: (optional, default: false) - keep cookies between tests when `restart` is set to false.
|
|
55
58
|
* * `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
56
59
|
* * `waitForNavigation`: (optional, default: 'load'). When to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions). Array values are accepted as well.
|
|
60
|
+
* * `pressKeyDelay`: (optional, default: '10'). Delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
|
|
57
61
|
* * `getPageTimeout` (optional, default: '0') config option to set maximum navigation time in milliseconds.
|
|
58
62
|
* * `waitForTimeout`: (optional) default wait* timeout in ms. Default: 1000.
|
|
59
63
|
* * `windowSize`: (optional) default window size. Set a dimension like `640x480`.
|
|
60
64
|
* * `userAgent`: (optional) user-agent string.
|
|
61
65
|
* * `manualStart`: (optional, default: false) - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
|
|
66
|
+
* * `browser`: (optional, default: chrome) - can be changed to `firefox` when using [puppeteer-firefox](https://codecept.io/helpers/Puppeteer-firefox).
|
|
62
67
|
* * `chrome`: (optional) pass additional [Puppeteer run options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions).
|
|
63
68
|
*
|
|
64
69
|
*
|
|
@@ -139,7 +144,8 @@ const consoleLogStore = new Console();
|
|
|
139
144
|
class Puppeteer extends Helper {
|
|
140
145
|
constructor(config) {
|
|
141
146
|
super(config);
|
|
142
|
-
|
|
147
|
+
|
|
148
|
+
puppeteer = requireg(config.browser === 'firefox' ? 'puppeteer-firefox' : 'puppeteer');
|
|
143
149
|
|
|
144
150
|
// set defaults
|
|
145
151
|
this.isRemoteBrowser = false;
|
|
@@ -151,8 +157,10 @@ class Puppeteer extends Helper {
|
|
|
151
157
|
|
|
152
158
|
_validateConfig(config) {
|
|
153
159
|
const defaults = {
|
|
160
|
+
browser: 'chrome',
|
|
154
161
|
waitForAction: 100,
|
|
155
162
|
waitForTimeout: 1000,
|
|
163
|
+
pressKeyDelay: 10,
|
|
156
164
|
fullPageScreenshots: false,
|
|
157
165
|
disableScreenshots: false,
|
|
158
166
|
uniqueScreenshotNames: false,
|
|
@@ -169,9 +177,13 @@ class Puppeteer extends Helper {
|
|
|
169
177
|
return Object.assign(defaults, config);
|
|
170
178
|
}
|
|
171
179
|
|
|
180
|
+
_getOptions(config) {
|
|
181
|
+
return config.browser === 'firefox' ? this.options.firefox : this.options.chrome;
|
|
182
|
+
}
|
|
183
|
+
|
|
172
184
|
_setConfig(config) {
|
|
173
185
|
this.options = this._validateConfig(config);
|
|
174
|
-
this.puppeteerOptions = Object.assign({ headless: !this.options.show }, this.
|
|
186
|
+
this.puppeteerOptions = Object.assign({ headless: !this.options.show }, this._getOptions(config));
|
|
175
187
|
this.isRemoteBrowser = !!this.puppeteerOptions.browserWSEndpoint;
|
|
176
188
|
popupStore.defaultAction = this.options.defaultPopupAction;
|
|
177
189
|
}
|
|
@@ -179,6 +191,9 @@ class Puppeteer extends Helper {
|
|
|
179
191
|
static _config() {
|
|
180
192
|
return [
|
|
181
193
|
{ name: 'url', message: 'Base url of site to be tested', default: 'http://localhost' },
|
|
194
|
+
{
|
|
195
|
+
name: 'show', message: 'Show browser window', default: true, type: 'confirm',
|
|
196
|
+
},
|
|
182
197
|
];
|
|
183
198
|
}
|
|
184
199
|
|
|
@@ -339,7 +354,9 @@ class Puppeteer extends Helper {
|
|
|
339
354
|
if (!page) return;
|
|
340
355
|
page.setDefaultNavigationTimeout(this.options.getPageTimeout);
|
|
341
356
|
this.context = await this.page.$('body');
|
|
342
|
-
|
|
357
|
+
if (this.config.browser === 'chrome') {
|
|
358
|
+
await page.bringToFront();
|
|
359
|
+
}
|
|
343
360
|
}
|
|
344
361
|
|
|
345
362
|
/**
|
|
@@ -488,19 +505,41 @@ class Puppeteer extends Helper {
|
|
|
488
505
|
this.context = await this.page.mainFrame().$('body');
|
|
489
506
|
}
|
|
490
507
|
|
|
508
|
+
_extractDataFromPerformanceTiming(timing, ...dataNames) {
|
|
509
|
+
const navigationStart = timing.navigationStart;
|
|
510
|
+
|
|
511
|
+
const extractedData = {};
|
|
512
|
+
dataNames.forEach((name) => {
|
|
513
|
+
extractedData[name] = timing[name] - navigationStart;
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
return extractedData;
|
|
517
|
+
}
|
|
518
|
+
|
|
491
519
|
/**
|
|
492
|
-
* {{>
|
|
520
|
+
* {{> amOnPage }}
|
|
493
521
|
*/
|
|
494
522
|
async amOnPage(url) {
|
|
495
523
|
if (!(/^\w+\:\/\//.test(url))) {
|
|
496
524
|
url = this.options.url + url;
|
|
497
525
|
}
|
|
498
526
|
await this.page.goto(url, { waitUntil: this.options.waitForNavigation });
|
|
527
|
+
|
|
528
|
+
const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)));
|
|
529
|
+
|
|
530
|
+
perfTiming = this._extractDataFromPerformanceTiming(
|
|
531
|
+
performanceTiming,
|
|
532
|
+
'responseEnd',
|
|
533
|
+
'domInteractive',
|
|
534
|
+
'domContentLoadedEventEnd',
|
|
535
|
+
'loadEventEnd',
|
|
536
|
+
);
|
|
537
|
+
|
|
499
538
|
return this._waitForAction();
|
|
500
539
|
}
|
|
501
540
|
|
|
502
541
|
/**
|
|
503
|
-
* {{>
|
|
542
|
+
* {{> resizeWindow }}
|
|
504
543
|
*
|
|
505
544
|
* Unlike other drivers Puppeteer changes the size of a viewport, not the window!
|
|
506
545
|
* Puppeteer does not control the window of a browser so it can't adjust its real size.
|
|
@@ -523,6 +562,8 @@ class Puppeteer extends Helper {
|
|
|
523
562
|
* 'X-Sent-By': 'CodeceptJS',
|
|
524
563
|
* });
|
|
525
564
|
* ```
|
|
565
|
+
*
|
|
566
|
+
* @param {object} customHeaders headers to set
|
|
526
567
|
*/
|
|
527
568
|
async haveRequestHeaders(customHeaders) {
|
|
528
569
|
if (!customHeaders) {
|
|
@@ -532,7 +573,8 @@ class Puppeteer extends Helper {
|
|
|
532
573
|
}
|
|
533
574
|
|
|
534
575
|
/**
|
|
535
|
-
* {{>
|
|
576
|
+
* {{> moveCursorTo }}
|
|
577
|
+
* {{ react }}
|
|
536
578
|
*/
|
|
537
579
|
async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
|
|
538
580
|
const els = await this._locate(locator);
|
|
@@ -545,33 +587,33 @@ class Puppeteer extends Helper {
|
|
|
545
587
|
}
|
|
546
588
|
|
|
547
589
|
/**
|
|
548
|
-
* {{>
|
|
590
|
+
* {{> dragAndDrop }}
|
|
549
591
|
*/
|
|
550
592
|
async dragAndDrop(srcElement, destElement) {
|
|
551
593
|
return proceedDragAndDrop.call(this, srcElement, destElement);
|
|
552
594
|
}
|
|
553
595
|
|
|
554
596
|
/**
|
|
555
|
-
* {{>
|
|
597
|
+
* {{> refreshPage }}
|
|
556
598
|
*/
|
|
557
599
|
async refreshPage() {
|
|
558
600
|
return this.page.reload({ timeout: this.options.getPageTimeout, waitUntil: this.options.waitForNavigation });
|
|
559
601
|
}
|
|
560
602
|
|
|
561
603
|
/**
|
|
562
|
-
* {{>
|
|
604
|
+
* {{> scrollPageToTop }}
|
|
563
605
|
*/
|
|
564
606
|
scrollPageToTop() {
|
|
565
|
-
return this.
|
|
607
|
+
return this.executeScript(() => {
|
|
566
608
|
window.scrollTo(0, 0);
|
|
567
609
|
});
|
|
568
610
|
}
|
|
569
611
|
|
|
570
612
|
/**
|
|
571
|
-
* {{>
|
|
613
|
+
* {{> scrollPageToBottom }}
|
|
572
614
|
*/
|
|
573
615
|
scrollPageToBottom() {
|
|
574
|
-
return this.
|
|
616
|
+
return this.executeScript(() => {
|
|
575
617
|
const body = document.body;
|
|
576
618
|
const html = document.documentElement;
|
|
577
619
|
window.scrollTo(0, Math.max(
|
|
@@ -582,7 +624,7 @@ class Puppeteer extends Helper {
|
|
|
582
624
|
}
|
|
583
625
|
|
|
584
626
|
/**
|
|
585
|
-
* {{>
|
|
627
|
+
* {{> scrollTo }}
|
|
586
628
|
*/
|
|
587
629
|
async scrollTo(locator, offsetX = 0, offsetY = 0) {
|
|
588
630
|
if (typeof locator === 'number' && typeof offsetX === 'number') {
|
|
@@ -590,25 +632,21 @@ class Puppeteer extends Helper {
|
|
|
590
632
|
offsetX = locator;
|
|
591
633
|
locator = null;
|
|
592
634
|
}
|
|
593
|
-
|
|
594
|
-
let y = 0;
|
|
635
|
+
|
|
595
636
|
if (locator) {
|
|
596
637
|
const els = await this._locate(locator);
|
|
597
638
|
assertElementExists(els, locator, 'Element');
|
|
598
639
|
await els[0]._scrollIntoViewIfNeeded();
|
|
599
640
|
const elementCoordinates = await els[0]._clickablePoint();
|
|
600
|
-
x
|
|
601
|
-
|
|
641
|
+
await this.executeScript((x, y) => window.scrollBy(x, y), elementCoordinates.x + offsetX, elementCoordinates.y + offsetY);
|
|
642
|
+
} else {
|
|
643
|
+
await this.executeScript((x, y) => window.scrollTo(x, y), offsetX, offsetY);
|
|
602
644
|
}
|
|
603
|
-
|
|
604
|
-
await this.page.evaluate((x, y) => {
|
|
605
|
-
window.scrollTo(x, y);
|
|
606
|
-
}, x + offsetX, y + offsetY);
|
|
607
645
|
return this._waitForAction();
|
|
608
646
|
}
|
|
609
647
|
|
|
610
648
|
/**
|
|
611
|
-
* {{>
|
|
649
|
+
* {{> seeInTitle }}
|
|
612
650
|
*/
|
|
613
651
|
async seeInTitle(text) {
|
|
614
652
|
const title = await this.page.title();
|
|
@@ -616,7 +654,7 @@ class Puppeteer extends Helper {
|
|
|
616
654
|
}
|
|
617
655
|
|
|
618
656
|
/**
|
|
619
|
-
* {{>
|
|
657
|
+
* {{> grabPageScrollPosition }}
|
|
620
658
|
*/
|
|
621
659
|
async grabPageScrollPosition() {
|
|
622
660
|
/* eslint-disable comma-dangle */
|
|
@@ -643,7 +681,7 @@ class Puppeteer extends Helper {
|
|
|
643
681
|
}
|
|
644
682
|
|
|
645
683
|
/**
|
|
646
|
-
* {{>
|
|
684
|
+
* {{> dontSeeInTitle }}
|
|
647
685
|
*/
|
|
648
686
|
async dontSeeInTitle(text) {
|
|
649
687
|
const title = await this.page.title();
|
|
@@ -651,7 +689,7 @@ class Puppeteer extends Helper {
|
|
|
651
689
|
}
|
|
652
690
|
|
|
653
691
|
/**
|
|
654
|
-
* {{>
|
|
692
|
+
* {{> grabTitle }}
|
|
655
693
|
*/
|
|
656
694
|
async grabTitle() {
|
|
657
695
|
return this.page.title();
|
|
@@ -664,6 +702,8 @@ class Puppeteer extends Helper {
|
|
|
664
702
|
* ```js
|
|
665
703
|
* const elements = await this.helpers['Puppeteer']._locate({name: 'password'});
|
|
666
704
|
* ```
|
|
705
|
+
*
|
|
706
|
+
* {{ react }}
|
|
667
707
|
*/
|
|
668
708
|
async _locate(locator) {
|
|
669
709
|
return findElements(await this.context, locator);
|
|
@@ -714,6 +754,8 @@ class Puppeteer extends Helper {
|
|
|
714
754
|
* I.switchToNextTab();
|
|
715
755
|
* I.switchToNextTab(2);
|
|
716
756
|
* ```
|
|
757
|
+
*
|
|
758
|
+
* @param {number} [num=1]
|
|
717
759
|
*/
|
|
718
760
|
async switchToNextTab(num = 1) {
|
|
719
761
|
const pages = await this.browser.pages();
|
|
@@ -736,6 +778,7 @@ class Puppeteer extends Helper {
|
|
|
736
778
|
* I.switchToPreviousTab();
|
|
737
779
|
* I.switchToPreviousTab(2);
|
|
738
780
|
* ```
|
|
781
|
+
* @param {number} [num=1]
|
|
739
782
|
*/
|
|
740
783
|
async switchToPreviousTab(num = 1) {
|
|
741
784
|
const pages = await this.browser.pages();
|
|
@@ -797,7 +840,7 @@ class Puppeteer extends Helper {
|
|
|
797
840
|
}
|
|
798
841
|
|
|
799
842
|
/**
|
|
800
|
-
* {{>
|
|
843
|
+
* {{> grabNumberOfOpenTabs }}
|
|
801
844
|
*/
|
|
802
845
|
async grabNumberOfOpenTabs() {
|
|
803
846
|
const pages = await this.browser.pages();
|
|
@@ -805,9 +848,9 @@ class Puppeteer extends Helper {
|
|
|
805
848
|
}
|
|
806
849
|
|
|
807
850
|
/**
|
|
808
|
-
* {{>
|
|
851
|
+
* {{> seeElement }}
|
|
852
|
+
* {{ react }}
|
|
809
853
|
*/
|
|
810
|
-
|
|
811
854
|
async seeElement(locator) {
|
|
812
855
|
let els = await this._locate(locator);
|
|
813
856
|
els = await Promise.all(els.map(el => el.boundingBox()));
|
|
@@ -815,7 +858,8 @@ class Puppeteer extends Helper {
|
|
|
815
858
|
}
|
|
816
859
|
|
|
817
860
|
/**
|
|
818
|
-
* {{>
|
|
861
|
+
* {{> dontSeeElement }}
|
|
862
|
+
* {{ react }}
|
|
819
863
|
*/
|
|
820
864
|
async dontSeeElement(locator) {
|
|
821
865
|
let els = await this._locate(locator);
|
|
@@ -824,7 +868,7 @@ class Puppeteer extends Helper {
|
|
|
824
868
|
}
|
|
825
869
|
|
|
826
870
|
/**
|
|
827
|
-
* {{>
|
|
871
|
+
* {{> seeElementInDOM }}
|
|
828
872
|
*/
|
|
829
873
|
async seeElementInDOM(locator) {
|
|
830
874
|
const els = await this._locate(locator);
|
|
@@ -832,7 +876,7 @@ class Puppeteer extends Helper {
|
|
|
832
876
|
}
|
|
833
877
|
|
|
834
878
|
/**
|
|
835
|
-
* {{>
|
|
879
|
+
* {{> dontSeeElementInDOM }}
|
|
836
880
|
*/
|
|
837
881
|
async dontSeeElementInDOM(locator) {
|
|
838
882
|
const els = await this._locate(locator);
|
|
@@ -840,37 +884,77 @@ class Puppeteer extends Helper {
|
|
|
840
884
|
}
|
|
841
885
|
|
|
842
886
|
/**
|
|
843
|
-
* {{>
|
|
887
|
+
* {{> click }}
|
|
888
|
+
*
|
|
889
|
+
* {{ react }}
|
|
844
890
|
*/
|
|
845
891
|
async click(locator, context = null) {
|
|
846
892
|
return proceedClick.call(this, locator, context);
|
|
847
893
|
}
|
|
848
894
|
|
|
849
895
|
/**
|
|
850
|
-
* {{>
|
|
896
|
+
* {{> clickLink }}
|
|
897
|
+
*
|
|
898
|
+
* {{ react }}
|
|
851
899
|
*/
|
|
852
900
|
async clickLink(locator, context = null) {
|
|
853
901
|
return proceedClick.call(this, locator, context, { waitForNavigation: true });
|
|
854
902
|
}
|
|
855
903
|
|
|
856
904
|
/**
|
|
857
|
-
*
|
|
905
|
+
* Sets a directory to where save files. Allows to test file downloads.
|
|
906
|
+
* Should be used with [FileSystem helper](https://codecept.io/helpers/FileSystem) to check that file were downloaded correctly.
|
|
907
|
+
*
|
|
908
|
+
* By default files are saved to `output/downloads`.
|
|
909
|
+
* This directory is cleaned on every `handleDownloads` call, to ensure no old files are kept.
|
|
910
|
+
*
|
|
911
|
+
* ```js
|
|
912
|
+
* I.handleDownloads();
|
|
913
|
+
* I.click('Download Avatar');
|
|
914
|
+
* I.amInPath('output/downloads');
|
|
915
|
+
* I.seeFile('avatar.jpg');
|
|
916
|
+
*
|
|
917
|
+
* ```
|
|
918
|
+
*
|
|
919
|
+
* @param {string} [downloadPath='downloads'] change this parameter to set another directory for saving
|
|
920
|
+
*/
|
|
921
|
+
async handleDownloads(downloadPath = 'downloads') {
|
|
922
|
+
downloadPath = path.join(global.output_dir, downloadPath);
|
|
923
|
+
if (!fs.existsSync(downloadPath)) {
|
|
924
|
+
fs.mkdirSync(downloadPath, '0777');
|
|
925
|
+
}
|
|
926
|
+
fsExtra.emptyDirSync(downloadPath);
|
|
927
|
+
return this.page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath });
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* This method is **depreacted**.
|
|
932
|
+
*
|
|
933
|
+
* Please use `handleDownloads()` instead.
|
|
858
934
|
*/
|
|
859
935
|
async downloadFile(locator, customName) {
|
|
860
936
|
let fileName;
|
|
861
937
|
await this.page.setRequestInterception(true);
|
|
862
|
-
this.click(locator);
|
|
863
938
|
|
|
864
939
|
const xRequest = await new Promise((resolve) => {
|
|
865
940
|
this.page.on('request', (request) => {
|
|
941
|
+
console.log('rq', request, customName);
|
|
866
942
|
const grabbedFileName = request.url().split('/')[request.url().split('/').length - 1];
|
|
867
943
|
const fileExtension = request.url().split('/')[request.url().split('/').length - 1].split('.')[1];
|
|
944
|
+
console.log('nm', customName, fileExtension);
|
|
945
|
+
if (customName && path.extname(customName) !== fileExtension) {
|
|
946
|
+
console.log('bypassing a request');
|
|
947
|
+
request.continue();
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
868
950
|
customName ? fileName = `${customName}.${fileExtension}` : fileName = grabbedFileName;
|
|
869
951
|
request.abort();
|
|
870
952
|
resolve(request);
|
|
871
953
|
});
|
|
872
954
|
});
|
|
873
955
|
|
|
956
|
+
await this.click(locator);
|
|
957
|
+
|
|
874
958
|
const options = {
|
|
875
959
|
encoding: null,
|
|
876
960
|
method: xRequest._method,
|
|
@@ -883,14 +967,21 @@ class Puppeteer extends Helper {
|
|
|
883
967
|
options.headers.Cookie = cookies.map(ck => `${ck.name}=${ck.value}`).join(';');
|
|
884
968
|
|
|
885
969
|
const response = await axios({
|
|
886
|
-
method: options.method,
|
|
970
|
+
method: options.method,
|
|
971
|
+
url: options.uri,
|
|
972
|
+
headers: options.headers,
|
|
973
|
+
responseType: 'arraybuffer',
|
|
974
|
+
onDownloadProgress(e) {
|
|
975
|
+
console.log('+', e);
|
|
976
|
+
},
|
|
887
977
|
});
|
|
888
978
|
|
|
889
979
|
const outputFile = path.join(`${global.output_dir}/${fileName}`);
|
|
890
980
|
|
|
891
981
|
try {
|
|
892
|
-
|
|
982
|
+
await new Promise((resolve, reject) => {
|
|
893
983
|
const wstream = fs.createWriteStream(outputFile);
|
|
984
|
+
console.log(response);
|
|
894
985
|
wstream.write(response.data);
|
|
895
986
|
wstream.end();
|
|
896
987
|
this.debug(`File is downloaded in ${outputFile}`);
|
|
@@ -903,21 +994,25 @@ class Puppeteer extends Helper {
|
|
|
903
994
|
}
|
|
904
995
|
|
|
905
996
|
/**
|
|
906
|
-
* {{>
|
|
997
|
+
* {{> doubleClick }}
|
|
998
|
+
*
|
|
999
|
+
* {{ react }}
|
|
907
1000
|
*/
|
|
908
1001
|
async doubleClick(locator, context = null) {
|
|
909
1002
|
return proceedClick.call(this, locator, context, { clickCount: 2 });
|
|
910
1003
|
}
|
|
911
1004
|
|
|
912
1005
|
/**
|
|
913
|
-
* {{>
|
|
1006
|
+
* {{> rightClick }}
|
|
1007
|
+
*
|
|
1008
|
+
* {{ react }}
|
|
914
1009
|
*/
|
|
915
1010
|
async rightClick(locator, context = null) {
|
|
916
1011
|
return proceedClick.call(this, locator, context, { button: 'right' });
|
|
917
1012
|
}
|
|
918
1013
|
|
|
919
1014
|
/**
|
|
920
|
-
* {{>
|
|
1015
|
+
* {{> checkOption }}
|
|
921
1016
|
*/
|
|
922
1017
|
async checkOption(field, context = null) {
|
|
923
1018
|
const elm = await this._locateCheckable(field, context);
|
|
@@ -931,7 +1026,7 @@ class Puppeteer extends Helper {
|
|
|
931
1026
|
}
|
|
932
1027
|
|
|
933
1028
|
/**
|
|
934
|
-
* {{>
|
|
1029
|
+
* {{> uncheckOption }}
|
|
935
1030
|
*/
|
|
936
1031
|
async uncheckOption(field, context = null) {
|
|
937
1032
|
const elm = await this._locateCheckable(field, context);
|
|
@@ -945,21 +1040,23 @@ class Puppeteer extends Helper {
|
|
|
945
1040
|
}
|
|
946
1041
|
|
|
947
1042
|
/**
|
|
948
|
-
* {{>
|
|
1043
|
+
* {{> seeCheckboxIsChecked }}
|
|
949
1044
|
*/
|
|
950
1045
|
async seeCheckboxIsChecked(field) {
|
|
951
1046
|
return proceedIsChecked.call(this, 'assert', field);
|
|
952
1047
|
}
|
|
953
1048
|
|
|
954
1049
|
/**
|
|
955
|
-
* {{>
|
|
1050
|
+
* {{> dontSeeCheckboxIsChecked }}
|
|
956
1051
|
*/
|
|
957
1052
|
async dontSeeCheckboxIsChecked(field) {
|
|
958
1053
|
return proceedIsChecked.call(this, 'negate', field);
|
|
959
1054
|
}
|
|
960
1055
|
|
|
961
1056
|
/**
|
|
962
|
-
* {{>
|
|
1057
|
+
* {{> pressKey }}
|
|
1058
|
+
*
|
|
1059
|
+
* {{ keys }}
|
|
963
1060
|
*/
|
|
964
1061
|
async pressKey(key) {
|
|
965
1062
|
let modifier;
|
|
@@ -975,7 +1072,8 @@ class Puppeteer extends Helper {
|
|
|
975
1072
|
}
|
|
976
1073
|
|
|
977
1074
|
/**
|
|
978
|
-
* {{>
|
|
1075
|
+
* {{> fillField }}
|
|
1076
|
+
* {{ react }}
|
|
979
1077
|
*/
|
|
980
1078
|
async fillField(field, value) {
|
|
981
1079
|
const els = await findFields.call(this, field);
|
|
@@ -989,38 +1087,40 @@ class Puppeteer extends Helper {
|
|
|
989
1087
|
} else if (editable) {
|
|
990
1088
|
await this._evaluateHandeInContext(el => el.innerHTML = '', el);
|
|
991
1089
|
}
|
|
992
|
-
await el.type(value.toString(), { delay:
|
|
1090
|
+
await el.type(value.toString(), { delay: this.options.pressKeyDelay });
|
|
993
1091
|
return this._waitForAction();
|
|
994
1092
|
}
|
|
995
1093
|
|
|
996
1094
|
|
|
997
1095
|
/**
|
|
998
|
-
* {{>
|
|
1096
|
+
* {{> clearField }}
|
|
999
1097
|
*/
|
|
1000
1098
|
async clearField(field) {
|
|
1001
1099
|
return this.fillField(field, '');
|
|
1002
1100
|
}
|
|
1003
1101
|
|
|
1004
1102
|
/**
|
|
1005
|
-
* {{>
|
|
1103
|
+
* {{> appendField }}
|
|
1104
|
+
*
|
|
1105
|
+
* {{ react }}
|
|
1006
1106
|
*/
|
|
1007
1107
|
async appendField(field, value) {
|
|
1008
1108
|
const els = await findFields.call(this, field);
|
|
1009
1109
|
assertElementExists(els, field, 'Field');
|
|
1010
1110
|
await els[0].press('End');
|
|
1011
|
-
await els[0].type(value, { delay:
|
|
1111
|
+
await els[0].type(value, { delay: this.options.pressKeyDelay });
|
|
1012
1112
|
return this._waitForAction();
|
|
1013
1113
|
}
|
|
1014
1114
|
|
|
1015
1115
|
/**
|
|
1016
|
-
* {{>
|
|
1116
|
+
* {{> seeInField }}
|
|
1017
1117
|
*/
|
|
1018
1118
|
async seeInField(field, value) {
|
|
1019
1119
|
return proceedSeeInField.call(this, 'assert', field, value);
|
|
1020
1120
|
}
|
|
1021
1121
|
|
|
1022
1122
|
/**
|
|
1023
|
-
* {{>
|
|
1123
|
+
* {{> dontSeeInField }}
|
|
1024
1124
|
*/
|
|
1025
1125
|
async dontSeeInField(field, value) {
|
|
1026
1126
|
return proceedSeeInField.call(this, 'negate', field, value);
|
|
@@ -1028,8 +1128,7 @@ class Puppeteer extends Helper {
|
|
|
1028
1128
|
|
|
1029
1129
|
|
|
1030
1130
|
/**
|
|
1031
|
-
* {{>
|
|
1032
|
-
*
|
|
1131
|
+
* {{> attachFile }}
|
|
1033
1132
|
*/
|
|
1034
1133
|
async attachFile(locator, pathToFile) {
|
|
1035
1134
|
const file = path.join(global.codecept_dir, pathToFile);
|
|
@@ -1044,7 +1143,7 @@ class Puppeteer extends Helper {
|
|
|
1044
1143
|
}
|
|
1045
1144
|
|
|
1046
1145
|
/**
|
|
1047
|
-
* {{>
|
|
1146
|
+
* {{> selectOption }}
|
|
1048
1147
|
*/
|
|
1049
1148
|
async selectOption(select, option) {
|
|
1050
1149
|
const els = await findFields.call(this, select);
|
|
@@ -1076,7 +1175,8 @@ class Puppeteer extends Helper {
|
|
|
1076
1175
|
}
|
|
1077
1176
|
|
|
1078
1177
|
/**
|
|
1079
|
-
* {{>
|
|
1178
|
+
* {{> grabNumberOfVisibleElements }}
|
|
1179
|
+
* {{ react }}
|
|
1080
1180
|
*/
|
|
1081
1181
|
async grabNumberOfVisibleElements(locator) {
|
|
1082
1182
|
let els = await this._locate(locator);
|
|
@@ -1085,35 +1185,37 @@ class Puppeteer extends Helper {
|
|
|
1085
1185
|
}
|
|
1086
1186
|
|
|
1087
1187
|
/**
|
|
1088
|
-
* {{>
|
|
1188
|
+
* {{> seeInCurrentUrl }}
|
|
1089
1189
|
*/
|
|
1090
1190
|
async seeInCurrentUrl(url) {
|
|
1091
1191
|
stringIncludes('url').assert(url, await this._getPageUrl());
|
|
1092
1192
|
}
|
|
1093
1193
|
|
|
1094
1194
|
/**
|
|
1095
|
-
* {{>
|
|
1195
|
+
* {{> dontSeeInCurrentUrl }}
|
|
1096
1196
|
*/
|
|
1097
1197
|
async dontSeeInCurrentUrl(url) {
|
|
1098
1198
|
stringIncludes('url').negate(url, await this._getPageUrl());
|
|
1099
1199
|
}
|
|
1100
1200
|
|
|
1101
1201
|
/**
|
|
1102
|
-
* {{>
|
|
1202
|
+
* {{> seeCurrentUrlEquals }}
|
|
1103
1203
|
*/
|
|
1104
1204
|
async seeCurrentUrlEquals(url) {
|
|
1105
1205
|
urlEquals(this.options.url).assert(url, await this._getPageUrl());
|
|
1106
1206
|
}
|
|
1107
1207
|
|
|
1108
1208
|
/**
|
|
1109
|
-
* {{>
|
|
1209
|
+
* {{> dontSeeCurrentUrlEquals }}
|
|
1110
1210
|
*/
|
|
1111
1211
|
async dontSeeCurrentUrlEquals(url) {
|
|
1112
1212
|
urlEquals(this.options.url).negate(url, await this._getPageUrl());
|
|
1113
1213
|
}
|
|
1114
1214
|
|
|
1115
1215
|
/**
|
|
1116
|
-
* {{>
|
|
1216
|
+
* {{> see }}
|
|
1217
|
+
*
|
|
1218
|
+
* {{ react }}
|
|
1117
1219
|
*/
|
|
1118
1220
|
async see(text, context = null) {
|
|
1119
1221
|
return proceedSee.call(this, 'assert', text, context);
|
|
@@ -1131,14 +1233,16 @@ class Puppeteer extends Helper {
|
|
|
1131
1233
|
}
|
|
1132
1234
|
|
|
1133
1235
|
/**
|
|
1134
|
-
* {{>
|
|
1236
|
+
* {{> dontSee }}
|
|
1237
|
+
*
|
|
1238
|
+
* {{ react }}
|
|
1135
1239
|
*/
|
|
1136
1240
|
async dontSee(text, context = null) {
|
|
1137
1241
|
return proceedSee.call(this, 'negate', text, context);
|
|
1138
1242
|
}
|
|
1139
1243
|
|
|
1140
1244
|
/**
|
|
1141
|
-
* {{>
|
|
1245
|
+
* {{> grabSource }}
|
|
1142
1246
|
*/
|
|
1143
1247
|
async grabSource() {
|
|
1144
1248
|
return this.page.content();
|
|
@@ -1159,14 +1263,14 @@ class Puppeteer extends Helper {
|
|
|
1159
1263
|
}
|
|
1160
1264
|
|
|
1161
1265
|
/**
|
|
1162
|
-
* {{>
|
|
1266
|
+
* {{> grabCurrentUrl }}
|
|
1163
1267
|
*/
|
|
1164
1268
|
async grabCurrentUrl() {
|
|
1165
1269
|
return this._getPageUrl();
|
|
1166
1270
|
}
|
|
1167
1271
|
|
|
1168
1272
|
/**
|
|
1169
|
-
* {{>
|
|
1273
|
+
* {{> seeInSource }}
|
|
1170
1274
|
*/
|
|
1171
1275
|
async seeInSource(text) {
|
|
1172
1276
|
const source = await this.page.content();
|
|
@@ -1174,7 +1278,7 @@ class Puppeteer extends Helper {
|
|
|
1174
1278
|
}
|
|
1175
1279
|
|
|
1176
1280
|
/**
|
|
1177
|
-
* {{>
|
|
1281
|
+
* {{> dontSeeInSource }}
|
|
1178
1282
|
*/
|
|
1179
1283
|
async dontSeeInSource(text) {
|
|
1180
1284
|
const source = await this.page.content();
|
|
@@ -1183,20 +1287,19 @@ class Puppeteer extends Helper {
|
|
|
1183
1287
|
|
|
1184
1288
|
|
|
1185
1289
|
/**
|
|
1186
|
-
*
|
|
1187
|
-
* Element is located by label or name or CSS or XPath.
|
|
1290
|
+
* {{> seeNumberOfElements }}
|
|
1188
1291
|
*
|
|
1189
|
-
*
|
|
1190
|
-
* I.seeNumberOfElements('#submitBtn', 1);
|
|
1191
|
-
* ```
|
|
1292
|
+
* {{ react }}
|
|
1192
1293
|
*/
|
|
1193
|
-
async seeNumberOfElements(
|
|
1194
|
-
const elements = await this._locate(
|
|
1195
|
-
return equals(`expected number of elements (${
|
|
1294
|
+
async seeNumberOfElements(locator, num) {
|
|
1295
|
+
const elements = await this._locate(locator);
|
|
1296
|
+
return equals(`expected number of elements (${locator}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
|
|
1196
1297
|
}
|
|
1197
1298
|
|
|
1198
1299
|
/**
|
|
1199
|
-
* {{>
|
|
1300
|
+
* {{> seeNumberOfVisibleElements }}
|
|
1301
|
+
*
|
|
1302
|
+
* {{ react }}
|
|
1200
1303
|
*/
|
|
1201
1304
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1202
1305
|
const res = await this.grabNumberOfVisibleElements(locator);
|
|
@@ -1204,7 +1307,7 @@ class Puppeteer extends Helper {
|
|
|
1204
1307
|
}
|
|
1205
1308
|
|
|
1206
1309
|
/**
|
|
1207
|
-
* {{>
|
|
1310
|
+
* {{> setCookie }}
|
|
1208
1311
|
*/
|
|
1209
1312
|
async setCookie(cookie) {
|
|
1210
1313
|
if (Array.isArray(cookie)) {
|
|
@@ -1214,7 +1317,7 @@ class Puppeteer extends Helper {
|
|
|
1214
1317
|
}
|
|
1215
1318
|
|
|
1216
1319
|
/**
|
|
1217
|
-
* {{>
|
|
1320
|
+
* {{> seeCookie }}
|
|
1218
1321
|
*
|
|
1219
1322
|
*/
|
|
1220
1323
|
async seeCookie(name) {
|
|
@@ -1223,7 +1326,7 @@ class Puppeteer extends Helper {
|
|
|
1223
1326
|
}
|
|
1224
1327
|
|
|
1225
1328
|
/**
|
|
1226
|
-
* {{>
|
|
1329
|
+
* {{> dontSeeCookie }}
|
|
1227
1330
|
*/
|
|
1228
1331
|
async dontSeeCookie(name) {
|
|
1229
1332
|
const cookies = await this.page.cookies();
|
|
@@ -1231,7 +1334,7 @@ class Puppeteer extends Helper {
|
|
|
1231
1334
|
}
|
|
1232
1335
|
|
|
1233
1336
|
/**
|
|
1234
|
-
* {{>
|
|
1337
|
+
* {{> grabCookie }}
|
|
1235
1338
|
*
|
|
1236
1339
|
* Returns cookie in JSON format. If name not passed returns all cookies for this domain.
|
|
1237
1340
|
*/
|
|
@@ -1243,7 +1346,7 @@ class Puppeteer extends Helper {
|
|
|
1243
1346
|
}
|
|
1244
1347
|
|
|
1245
1348
|
/**
|
|
1246
|
-
* {{>
|
|
1349
|
+
* {{> clearCookie }}
|
|
1247
1350
|
*/
|
|
1248
1351
|
async clearCookie(name) {
|
|
1249
1352
|
const cookies = await this.page.cookies();
|
|
@@ -1256,7 +1359,7 @@ class Puppeteer extends Helper {
|
|
|
1256
1359
|
}
|
|
1257
1360
|
|
|
1258
1361
|
/**
|
|
1259
|
-
* {{>
|
|
1362
|
+
* {{> executeScript }}
|
|
1260
1363
|
*
|
|
1261
1364
|
* If a function returns a Promise It will wait for it resolution.
|
|
1262
1365
|
*/
|
|
@@ -1269,7 +1372,7 @@ class Puppeteer extends Helper {
|
|
|
1269
1372
|
}
|
|
1270
1373
|
|
|
1271
1374
|
/**
|
|
1272
|
-
* {{>
|
|
1375
|
+
* {{> executeAsyncScript }}
|
|
1273
1376
|
*
|
|
1274
1377
|
* Asynchronous scripts can also be executed with `executeScript` if a function returns a Promise.
|
|
1275
1378
|
*/
|
|
@@ -1290,7 +1393,8 @@ class Puppeteer extends Helper {
|
|
|
1290
1393
|
|
|
1291
1394
|
|
|
1292
1395
|
/**
|
|
1293
|
-
* {{>
|
|
1396
|
+
* {{> grabTextFrom }}
|
|
1397
|
+
* {{ react }}
|
|
1294
1398
|
*/
|
|
1295
1399
|
async grabTextFrom(locator) {
|
|
1296
1400
|
const els = await this._locate(locator);
|
|
@@ -1304,7 +1408,7 @@ class Puppeteer extends Helper {
|
|
|
1304
1408
|
}
|
|
1305
1409
|
|
|
1306
1410
|
/**
|
|
1307
|
-
* {{>
|
|
1411
|
+
* {{> grabValueFrom }}
|
|
1308
1412
|
*/
|
|
1309
1413
|
async grabValueFrom(locator) {
|
|
1310
1414
|
const els = await findFields.call(this, locator);
|
|
@@ -1313,7 +1417,7 @@ class Puppeteer extends Helper {
|
|
|
1313
1417
|
}
|
|
1314
1418
|
|
|
1315
1419
|
/**
|
|
1316
|
-
* {{>
|
|
1420
|
+
* {{> grabHTMLFrom }}
|
|
1317
1421
|
*/
|
|
1318
1422
|
async grabHTMLFrom(locator) {
|
|
1319
1423
|
const els = await this._locate(locator);
|
|
@@ -1326,7 +1430,8 @@ class Puppeteer extends Helper {
|
|
|
1326
1430
|
}
|
|
1327
1431
|
|
|
1328
1432
|
/**
|
|
1329
|
-
* {{>
|
|
1433
|
+
* {{> grabCssPropertyFrom }}
|
|
1434
|
+
* {{ react }}
|
|
1330
1435
|
*/
|
|
1331
1436
|
async grabCssPropertyFrom(locator, cssProperty) {
|
|
1332
1437
|
const els = await this._locate(locator);
|
|
@@ -1340,7 +1445,8 @@ class Puppeteer extends Helper {
|
|
|
1340
1445
|
}
|
|
1341
1446
|
|
|
1342
1447
|
/**
|
|
1343
|
-
* {{>
|
|
1448
|
+
* {{> seeCssPropertiesOnElements }}
|
|
1449
|
+
* {{ react }}
|
|
1344
1450
|
*/
|
|
1345
1451
|
async seeCssPropertiesOnElements(locator, cssProperties) {
|
|
1346
1452
|
const res = await this._locate(locator);
|
|
@@ -1378,7 +1484,8 @@ class Puppeteer extends Helper {
|
|
|
1378
1484
|
}
|
|
1379
1485
|
|
|
1380
1486
|
/**
|
|
1381
|
-
* {{>
|
|
1487
|
+
* {{> seeAttributesOnElements }}
|
|
1488
|
+
* {{ react }}
|
|
1382
1489
|
*/
|
|
1383
1490
|
async seeAttributesOnElements(locator, attributes) {
|
|
1384
1491
|
const res = await this._locate(locator);
|
|
@@ -1408,7 +1515,8 @@ class Puppeteer extends Helper {
|
|
|
1408
1515
|
}
|
|
1409
1516
|
|
|
1410
1517
|
/**
|
|
1411
|
-
* {{>
|
|
1518
|
+
* {{> dragSlider }}
|
|
1519
|
+
* {{ react }}
|
|
1412
1520
|
*/
|
|
1413
1521
|
async dragSlider(locator, offsetX = 0) {
|
|
1414
1522
|
const src = await this._locate(locator);
|
|
@@ -1429,7 +1537,8 @@ class Puppeteer extends Helper {
|
|
|
1429
1537
|
}
|
|
1430
1538
|
|
|
1431
1539
|
/**
|
|
1432
|
-
* {{>
|
|
1540
|
+
* {{> grabAttributeFrom }}
|
|
1541
|
+
* {{ react }}
|
|
1433
1542
|
*/
|
|
1434
1543
|
async grabAttributeFrom(locator, attr) {
|
|
1435
1544
|
const els = await this._locate(locator);
|
|
@@ -1445,7 +1554,7 @@ class Puppeteer extends Helper {
|
|
|
1445
1554
|
}
|
|
1446
1555
|
|
|
1447
1556
|
/**
|
|
1448
|
-
* {{>
|
|
1557
|
+
* {{> saveScreenshot }}
|
|
1449
1558
|
*/
|
|
1450
1559
|
async saveScreenshot(fileName, fullPage) {
|
|
1451
1560
|
const fullPageOption = fullPage || this.options.fullPageScreenshots;
|
|
@@ -1464,7 +1573,7 @@ class Puppeteer extends Helper {
|
|
|
1464
1573
|
}
|
|
1465
1574
|
|
|
1466
1575
|
/**
|
|
1467
|
-
* {{>
|
|
1576
|
+
* {{> wait }}
|
|
1468
1577
|
*/
|
|
1469
1578
|
async wait(sec) {
|
|
1470
1579
|
return new Promise(((done) => {
|
|
@@ -1473,7 +1582,7 @@ class Puppeteer extends Helper {
|
|
|
1473
1582
|
}
|
|
1474
1583
|
|
|
1475
1584
|
/**
|
|
1476
|
-
* {{>
|
|
1585
|
+
* {{> waitForEnabled }}
|
|
1477
1586
|
*/
|
|
1478
1587
|
async waitForEnabled(locator, sec) {
|
|
1479
1588
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1503,7 +1612,7 @@ class Puppeteer extends Helper {
|
|
|
1503
1612
|
}
|
|
1504
1613
|
|
|
1505
1614
|
/**
|
|
1506
|
-
* {{>
|
|
1615
|
+
* {{> waitForValue }}
|
|
1507
1616
|
*/
|
|
1508
1617
|
async waitForValue(field, value, sec) {
|
|
1509
1618
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1534,7 +1643,8 @@ class Puppeteer extends Helper {
|
|
|
1534
1643
|
}
|
|
1535
1644
|
|
|
1536
1645
|
/**
|
|
1537
|
-
* {{>
|
|
1646
|
+
* {{> waitNumberOfVisibleElements }}
|
|
1647
|
+
* {{ react }}
|
|
1538
1648
|
*/
|
|
1539
1649
|
async waitNumberOfVisibleElements(locator, num, sec) {
|
|
1540
1650
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1564,7 +1674,8 @@ class Puppeteer extends Helper {
|
|
|
1564
1674
|
}
|
|
1565
1675
|
|
|
1566
1676
|
/**
|
|
1567
|
-
* {{>
|
|
1677
|
+
* {{> waitForElement }}
|
|
1678
|
+
* {{ react }}
|
|
1568
1679
|
*/
|
|
1569
1680
|
async waitForElement(locator, sec) {
|
|
1570
1681
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1583,7 +1694,9 @@ class Puppeteer extends Helper {
|
|
|
1583
1694
|
}
|
|
1584
1695
|
|
|
1585
1696
|
/**
|
|
1586
|
-
* {{>
|
|
1697
|
+
* {{> waitForVisible }}
|
|
1698
|
+
*
|
|
1699
|
+
* This method accepts [React selectors](https://codecept.io/react).
|
|
1587
1700
|
*/
|
|
1588
1701
|
async waitForVisible(locator, sec) {
|
|
1589
1702
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1606,7 +1719,7 @@ class Puppeteer extends Helper {
|
|
|
1606
1719
|
}
|
|
1607
1720
|
|
|
1608
1721
|
/**
|
|
1609
|
-
* {{>
|
|
1722
|
+
* {{> waitForInvisible }}
|
|
1610
1723
|
*/
|
|
1611
1724
|
async waitForInvisible(locator, sec) {
|
|
1612
1725
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1630,7 +1743,7 @@ class Puppeteer extends Helper {
|
|
|
1630
1743
|
}
|
|
1631
1744
|
|
|
1632
1745
|
/**
|
|
1633
|
-
* {{>
|
|
1746
|
+
* {{> waitToHide }}
|
|
1634
1747
|
*/
|
|
1635
1748
|
async waitToHide(locator, sec) {
|
|
1636
1749
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1659,7 +1772,7 @@ class Puppeteer extends Helper {
|
|
|
1659
1772
|
}
|
|
1660
1773
|
|
|
1661
1774
|
/**
|
|
1662
|
-
* {{>
|
|
1775
|
+
* {{> waitInUrl }}
|
|
1663
1776
|
*/
|
|
1664
1777
|
async waitInUrl(urlPart, sec = null) {
|
|
1665
1778
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1678,7 +1791,7 @@ class Puppeteer extends Helper {
|
|
|
1678
1791
|
}
|
|
1679
1792
|
|
|
1680
1793
|
/**
|
|
1681
|
-
* {{>
|
|
1794
|
+
* {{> waitUrlEquals }}
|
|
1682
1795
|
*/
|
|
1683
1796
|
async waitUrlEquals(urlPart, sec = null) {
|
|
1684
1797
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1702,7 +1815,7 @@ class Puppeteer extends Helper {
|
|
|
1702
1815
|
}
|
|
1703
1816
|
|
|
1704
1817
|
/**
|
|
1705
|
-
* {{>
|
|
1818
|
+
* {{> waitForText }}
|
|
1706
1819
|
*/
|
|
1707
1820
|
async waitForText(text, sec = null, context = null) {
|
|
1708
1821
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1744,8 +1857,8 @@ class Puppeteer extends Helper {
|
|
|
1744
1857
|
* I.waitForRequest(request => request.url() === 'http://example.com' && request.method() === 'GET');
|
|
1745
1858
|
* ```
|
|
1746
1859
|
*
|
|
1747
|
-
* @param {
|
|
1748
|
-
* @param {
|
|
1860
|
+
* @param {string|function} urlOrPredicate
|
|
1861
|
+
* @param {number?} [sec=null] seconds to wait
|
|
1749
1862
|
*/
|
|
1750
1863
|
async waitForRequest(urlOrPredicate, sec = null) {
|
|
1751
1864
|
const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1760,8 +1873,8 @@ class Puppeteer extends Helper {
|
|
|
1760
1873
|
* I.waitForResponse(request => request.url() === 'http://example.com' && request.method() === 'GET');
|
|
1761
1874
|
* ```
|
|
1762
1875
|
*
|
|
1763
|
-
* @param {
|
|
1764
|
-
* @param {
|
|
1876
|
+
* @param {string|function} urlOrPredicate
|
|
1877
|
+
* @param {number?} [sec=null] number of seconds to wait
|
|
1765
1878
|
*/
|
|
1766
1879
|
async waitForResponse(urlOrPredicate, sec = null) {
|
|
1767
1880
|
const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1769,7 +1882,7 @@ class Puppeteer extends Helper {
|
|
|
1769
1882
|
}
|
|
1770
1883
|
|
|
1771
1884
|
/**
|
|
1772
|
-
* {{>
|
|
1885
|
+
* {{> switchTo }}
|
|
1773
1886
|
*/
|
|
1774
1887
|
async switchTo(locator) {
|
|
1775
1888
|
if (Number.isInteger(locator)) {
|
|
@@ -1813,7 +1926,7 @@ class Puppeteer extends Helper {
|
|
|
1813
1926
|
}
|
|
1814
1927
|
|
|
1815
1928
|
/**
|
|
1816
|
-
* {{>
|
|
1929
|
+
* {{> waitForFunction }}
|
|
1817
1930
|
*/
|
|
1818
1931
|
async waitForFunction(fn, argsOrSec = null, sec = null) {
|
|
1819
1932
|
let args = [];
|
|
@@ -1842,7 +1955,7 @@ class Puppeteer extends Helper {
|
|
|
1842
1955
|
}
|
|
1843
1956
|
|
|
1844
1957
|
/**
|
|
1845
|
-
* {{>
|
|
1958
|
+
* {{> waitUntil }}
|
|
1846
1959
|
*/
|
|
1847
1960
|
async waitUntil(fn, sec = null) {
|
|
1848
1961
|
console.log('This method will remove in CodeceptJS 1.4; use `waitForFunction` instead!');
|
|
@@ -1859,7 +1972,7 @@ class Puppeteer extends Helper {
|
|
|
1859
1972
|
}
|
|
1860
1973
|
|
|
1861
1974
|
/**
|
|
1862
|
-
* {{>
|
|
1975
|
+
* {{> waitForDetached }}
|
|
1863
1976
|
*/
|
|
1864
1977
|
async waitForDetached(locator, sec) {
|
|
1865
1978
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -1887,6 +2000,13 @@ class Puppeteer extends Helper {
|
|
|
1887
2000
|
async _waitForAction() {
|
|
1888
2001
|
return this.wait(this.options.waitForAction / 1000);
|
|
1889
2002
|
}
|
|
2003
|
+
|
|
2004
|
+
/**
|
|
2005
|
+
* {{> grabDataFromPerformanceTiming }}
|
|
2006
|
+
*/
|
|
2007
|
+
async grabDataFromPerformanceTiming() {
|
|
2008
|
+
return perfTiming;
|
|
2009
|
+
}
|
|
1890
2010
|
}
|
|
1891
2011
|
|
|
1892
2012
|
module.exports = Puppeteer;
|
|
@@ -1911,9 +2031,9 @@ async function findFrame(context, name, url) {
|
|
|
1911
2031
|
}
|
|
1912
2032
|
|
|
1913
2033
|
async function findElements(matcher, locator) {
|
|
2034
|
+
if (locator.react) return findReact(matcher, locator);
|
|
1914
2035
|
locator = new Locator(locator, 'css');
|
|
1915
2036
|
if (!locator.isXPath()) return matcher.$$(locator.simplify());
|
|
1916
|
-
|
|
1917
2037
|
return matcher.$x(locator.value);
|
|
1918
2038
|
}
|
|
1919
2039
|
|
|
@@ -1940,6 +2060,7 @@ async function proceedClick(locator, context = null, options = {}) {
|
|
|
1940
2060
|
}
|
|
1941
2061
|
|
|
1942
2062
|
async function findClickable(matcher, locator) {
|
|
2063
|
+
if (locator.react) return findReact(matcher, locator);
|
|
1943
2064
|
locator = new Locator(locator);
|
|
1944
2065
|
if (!locator.isFuzzy()) return findElements.call(this, matcher, locator);
|
|
1945
2066
|
|
|
@@ -2181,7 +2302,11 @@ function $XPath(element, selector) {
|
|
|
2181
2302
|
function targetCreatedHandler(page) {
|
|
2182
2303
|
if (!page) return;
|
|
2183
2304
|
this.withinLocator = null;
|
|
2184
|
-
page.on('load', frame =>
|
|
2305
|
+
page.on('load', (frame) => {
|
|
2306
|
+
page.$('body')
|
|
2307
|
+
.catch(() => null)
|
|
2308
|
+
.then(context => this.context = context);
|
|
2309
|
+
});
|
|
2185
2310
|
page.on('console', (msg) => {
|
|
2186
2311
|
this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '));
|
|
2187
2312
|
consoleLogStore.add(msg);
|