codeceptjs 2.4.3 → 2.6.2
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 +117 -0
- package/README.md +32 -7
- package/bin/codecept.js +3 -0
- package/docs/basics.md +11 -5
- package/docs/bdd.md +4 -4
- package/docs/build/MockRequest.js +3 -0
- package/docs/build/Nightmare.js +10 -2
- package/docs/build/Playwright.js +3187 -0
- package/docs/build/Protractor.js +16 -2
- package/docs/build/Puppeteer.js +126 -19
- package/docs/build/REST.js +3 -1
- package/docs/build/TestCafe.js +11 -3
- package/docs/build/WebDriver.js +361 -28
- package/docs/changelog.md +116 -0
- package/docs/configuration.md +2 -2
- package/docs/custom-helpers.md +55 -10
- package/docs/helpers/Appium.md +81 -1
- package/docs/helpers/MockRequest.md +281 -38
- package/docs/helpers/Nightmare.md +10 -2
- package/docs/helpers/Playwright.md +1770 -0
- package/docs/helpers/Protractor.md +15 -3
- package/docs/helpers/Puppeteer-firefox.md +32 -1
- package/docs/helpers/Puppeteer.md +126 -76
- package/docs/helpers/TestCafe.md +10 -2
- package/docs/helpers/WebDriver.md +208 -118
- package/docs/locators.md +2 -0
- package/docs/playwright.md +306 -0
- package/docs/plugins.md +103 -0
- package/docs/reports.md +12 -0
- package/docs/shadow.md +68 -0
- package/docs/visual.md +0 -73
- package/docs/webapi/forceClick.mustache +27 -0
- package/docs/webapi/seeInPopup.mustache +7 -0
- package/docs/webapi/setCookie.mustache +10 -2
- package/docs/webapi/type.mustache +12 -0
- package/docs/webdriver.md +7 -3
- package/lib/codecept.js +1 -1
- package/lib/command/definitions.js +2 -2
- package/lib/command/generate.js +4 -4
- package/lib/command/gherkin/snippets.js +4 -4
- package/lib/command/init.js +1 -1
- package/lib/command/interactive.js +3 -0
- package/lib/command/run-multiple.js +2 -2
- package/lib/command/run-rerun.js +2 -0
- package/lib/command/run-workers.js +22 -8
- package/lib/command/run.js +2 -0
- package/lib/command/workers/runTests.js +1 -0
- package/lib/container.js +1 -1
- package/lib/event.js +2 -0
- package/lib/helper/MockRequest.js +3 -0
- package/lib/helper/Playwright.js +2422 -0
- package/lib/helper/Protractor.js +1 -2
- package/lib/helper/Puppeteer.js +84 -19
- package/lib/helper/REST.js +3 -1
- package/lib/helper/TestCafe.js +1 -1
- package/lib/helper/WebDriver.js +313 -26
- package/lib/helper/extras/PlaywrightPropEngine.js +53 -0
- package/lib/helper/scripts/isElementClickable.js +54 -14
- package/lib/interfaces/gherkin.js +1 -1
- package/lib/listener/helpers.js +3 -0
- package/lib/locator.js +5 -0
- package/lib/mochaFactory.js +12 -10
- package/lib/plugin/allure.js +8 -1
- package/lib/plugin/autoDelay.js +1 -8
- package/lib/plugin/commentStep.js +133 -0
- package/lib/plugin/screenshotOnFail.js +3 -10
- package/lib/plugin/selenoid.js +2 -2
- package/lib/plugin/standardActingHelpers.js +13 -0
- package/lib/plugin/stepByStepReport.js +1 -8
- package/lib/plugin/wdio.js +10 -1
- package/lib/reporter/cli.js +30 -1
- package/lib/session.js +7 -4
- package/package.json +13 -10
- package/typings/Mocha.d.ts +567 -16
- package/typings/index.d.ts +9 -5
- package/typings/types.d.ts +1634 -74
package/lib/helper/Protractor.js
CHANGED
|
@@ -1054,8 +1054,7 @@ class Protractor extends Helper {
|
|
|
1054
1054
|
}
|
|
1055
1055
|
|
|
1056
1056
|
/**
|
|
1057
|
-
*
|
|
1058
|
-
* given string.
|
|
1057
|
+
* {{> seeInPopup }}
|
|
1059
1058
|
*/
|
|
1060
1059
|
async seeInPopup(text) {
|
|
1061
1060
|
const popupAlert = await this.browser.switchTo().alert();
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -36,7 +36,6 @@ const findReact = require('./extras/React');
|
|
|
36
36
|
|
|
37
37
|
let puppeteer;
|
|
38
38
|
let perfTiming;
|
|
39
|
-
let isAuthenticated = false;
|
|
40
39
|
const popupStore = new Popup();
|
|
41
40
|
const consoleLogStore = new Console();
|
|
42
41
|
|
|
@@ -168,11 +167,14 @@ class Puppeteer extends Helper {
|
|
|
168
167
|
constructor(config) {
|
|
169
168
|
super(config);
|
|
170
169
|
|
|
171
|
-
puppeteer = requireg(
|
|
170
|
+
puppeteer = requireg('puppeteer');
|
|
172
171
|
|
|
173
172
|
// set defaults
|
|
174
173
|
this.isRemoteBrowser = false;
|
|
175
174
|
this.isRunning = false;
|
|
175
|
+
this.isAuthenticated = false;
|
|
176
|
+
this.sessionPages = {};
|
|
177
|
+
this.activeSessionName = '';
|
|
176
178
|
|
|
177
179
|
// override defaults with config
|
|
178
180
|
this._setConfig(config);
|
|
@@ -201,7 +203,7 @@ class Puppeteer extends Helper {
|
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
_getOptions(config) {
|
|
204
|
-
return config.browser === 'firefox' ? this.options.firefox : this.options.chrome;
|
|
206
|
+
return config.browser === 'firefox' ? Object.assign(this.options.firefox, { product: 'firefox' }) : this.options.chrome;
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
_setConfig(config) {
|
|
@@ -220,6 +222,9 @@ class Puppeteer extends Helper {
|
|
|
220
222
|
{
|
|
221
223
|
name: 'show', message: 'Show browser window', default: true, type: 'confirm',
|
|
222
224
|
},
|
|
225
|
+
{
|
|
226
|
+
name: 'windowSize', message: 'Browser viewport size', default: '1200x900',
|
|
227
|
+
},
|
|
223
228
|
];
|
|
224
229
|
}
|
|
225
230
|
|
|
@@ -227,7 +232,7 @@ class Puppeteer extends Helper {
|
|
|
227
232
|
try {
|
|
228
233
|
requireg('puppeteer');
|
|
229
234
|
} catch (e) {
|
|
230
|
-
return ['puppeteer@^
|
|
235
|
+
return ['puppeteer@^3.0.1'];
|
|
231
236
|
}
|
|
232
237
|
}
|
|
233
238
|
|
|
@@ -243,6 +248,7 @@ class Puppeteer extends Helper {
|
|
|
243
248
|
|
|
244
249
|
|
|
245
250
|
async _before() {
|
|
251
|
+
this.sessionPages = {};
|
|
246
252
|
recorder.retry({
|
|
247
253
|
retries: 5,
|
|
248
254
|
when: err => err.message.indexOf('context') > -1, // ignore context errors
|
|
@@ -257,7 +263,8 @@ class Puppeteer extends Helper {
|
|
|
257
263
|
|
|
258
264
|
// close other sessions
|
|
259
265
|
const contexts = this.browser.browserContexts();
|
|
260
|
-
contexts.shift();
|
|
266
|
+
const defaultCtx = contexts.shift();
|
|
267
|
+
|
|
261
268
|
await Promise.all(contexts.map(c => c.close()));
|
|
262
269
|
|
|
263
270
|
if (this.options.restart) {
|
|
@@ -265,6 +272,12 @@ class Puppeteer extends Helper {
|
|
|
265
272
|
return this._stopBrowser();
|
|
266
273
|
}
|
|
267
274
|
|
|
275
|
+
// ensure this.page is from default context
|
|
276
|
+
if (this.page) {
|
|
277
|
+
const existingPages = defaultCtx.targets().filter(t => t.type() === 'page');
|
|
278
|
+
await this._setPage(await existingPages[0].page());
|
|
279
|
+
}
|
|
280
|
+
|
|
268
281
|
if (this.options.keepBrowserState) return;
|
|
269
282
|
|
|
270
283
|
if (!this.options.keepCookies) {
|
|
@@ -291,11 +304,13 @@ class Puppeteer extends Helper {
|
|
|
291
304
|
|
|
292
305
|
_session() {
|
|
293
306
|
return {
|
|
294
|
-
start: async () => {
|
|
307
|
+
start: async (name = '', config) => {
|
|
295
308
|
this.debugSection('Incognito Tab', 'opened');
|
|
309
|
+
this.activeSessionName = name;
|
|
296
310
|
|
|
297
311
|
const bc = await this.browser.createIncognitoBrowserContext();
|
|
298
|
-
await bc.newPage();
|
|
312
|
+
const page = await bc.newPage();
|
|
313
|
+
|
|
299
314
|
// Create a new page inside context.
|
|
300
315
|
return bc;
|
|
301
316
|
},
|
|
@@ -304,12 +319,21 @@ class Puppeteer extends Helper {
|
|
|
304
319
|
},
|
|
305
320
|
loadVars: async (context) => {
|
|
306
321
|
const existingPages = context.targets().filter(t => t.type() === 'page');
|
|
307
|
-
|
|
322
|
+
this.sessionPages[this.activeSessionName] = await existingPages[0].page();
|
|
323
|
+
return this._setPage(this.sessionPages[this.activeSessionName]);
|
|
308
324
|
},
|
|
309
|
-
restoreVars: async () => {
|
|
325
|
+
restoreVars: async (session) => {
|
|
310
326
|
this.withinLocator = null;
|
|
311
|
-
|
|
327
|
+
|
|
328
|
+
if (!session) {
|
|
329
|
+
this.activeSessionName = '';
|
|
330
|
+
} else {
|
|
331
|
+
this.activeSessionName = session;
|
|
332
|
+
}
|
|
333
|
+
const defaultCtx = this.browser.defaultBrowserContext();
|
|
334
|
+
const existingPages = defaultCtx.targets().filter(t => t.type() === 'page');
|
|
312
335
|
await this._setPage(await existingPages[0].page());
|
|
336
|
+
|
|
313
337
|
return this._waitForAction();
|
|
314
338
|
},
|
|
315
339
|
};
|
|
@@ -361,8 +385,7 @@ class Puppeteer extends Helper {
|
|
|
361
385
|
}
|
|
362
386
|
|
|
363
387
|
/**
|
|
364
|
-
*
|
|
365
|
-
* given string.
|
|
388
|
+
* {{> seeInPopup }}
|
|
366
389
|
*/
|
|
367
390
|
async seeInPopup(text) {
|
|
368
391
|
popupStore.assertPopupVisible();
|
|
@@ -475,6 +498,7 @@ class Puppeteer extends Helper {
|
|
|
475
498
|
this._setPage(null);
|
|
476
499
|
this.context = null;
|
|
477
500
|
popupStore.clear();
|
|
501
|
+
this.isAuthenticated = false;
|
|
478
502
|
if (this.isRemoteBrowser) {
|
|
479
503
|
await this.browser.disconnect();
|
|
480
504
|
} else {
|
|
@@ -543,10 +567,10 @@ class Puppeteer extends Helper {
|
|
|
543
567
|
url = this.options.url + url;
|
|
544
568
|
}
|
|
545
569
|
|
|
546
|
-
if (this.config.basicAuth && (isAuthenticated !== true)) {
|
|
570
|
+
if (this.config.basicAuth && (this.isAuthenticated !== true)) {
|
|
547
571
|
if (url.includes(this.options.url)) {
|
|
548
|
-
this.page.authenticate(this.config.basicAuth);
|
|
549
|
-
isAuthenticated = true;
|
|
572
|
+
await this.page.authenticate(this.config.basicAuth);
|
|
573
|
+
this.isAuthenticated = true;
|
|
550
574
|
}
|
|
551
575
|
}
|
|
552
576
|
|
|
@@ -919,6 +943,36 @@ class Puppeteer extends Helper {
|
|
|
919
943
|
return proceedClick.call(this, locator, context);
|
|
920
944
|
}
|
|
921
945
|
|
|
946
|
+
/**
|
|
947
|
+
* {{> forceClick }}
|
|
948
|
+
*
|
|
949
|
+
* {{ react }}
|
|
950
|
+
*/
|
|
951
|
+
async forceClick(locator, context = null) {
|
|
952
|
+
let matcher = await this.context;
|
|
953
|
+
if (context) {
|
|
954
|
+
const els = await this._locate(context);
|
|
955
|
+
assertElementExists(els, context);
|
|
956
|
+
matcher = els[0];
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
const els = await findClickable.call(this, matcher, locator);
|
|
960
|
+
if (context) {
|
|
961
|
+
assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
|
|
962
|
+
} else {
|
|
963
|
+
assertElementExists(els, locator, 'Clickable element');
|
|
964
|
+
}
|
|
965
|
+
const elem = els[0];
|
|
966
|
+
return this.executeScript((el) => {
|
|
967
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
968
|
+
document.activeElement.blur();
|
|
969
|
+
}
|
|
970
|
+
const event = document.createEvent('MouseEvent');
|
|
971
|
+
event.initEvent('click', true, true);
|
|
972
|
+
return el.dispatchEvent(event);
|
|
973
|
+
}, elem);
|
|
974
|
+
}
|
|
975
|
+
|
|
922
976
|
/**
|
|
923
977
|
* {{> clickLink }}
|
|
924
978
|
*
|
|
@@ -1185,6 +1239,8 @@ class Puppeteer extends Helper {
|
|
|
1185
1239
|
|
|
1186
1240
|
/**
|
|
1187
1241
|
* {{> attachFile }}
|
|
1242
|
+
*
|
|
1243
|
+
* > ⚠ There is an [issue with file upload in Puppeteer 2.1.0 & 2.1.1](https://github.com/puppeteer/puppeteer/issues/5420), downgrade to 2.0.0 if you face it.
|
|
1188
1244
|
*/
|
|
1189
1245
|
async attachFile(locator, pathToFile) {
|
|
1190
1246
|
const file = path.join(global.codecept_dir, pathToFile);
|
|
@@ -1614,10 +1670,19 @@ class Puppeteer extends Helper {
|
|
|
1614
1670
|
const outputFile = screenshotOutputFolder(fileName);
|
|
1615
1671
|
|
|
1616
1672
|
this.debug(`Screenshot is saving to ${outputFile}`);
|
|
1617
|
-
|
|
1618
|
-
if (
|
|
1619
|
-
|
|
1673
|
+
|
|
1674
|
+
if (this.activeSessionName) {
|
|
1675
|
+
const activeSessionPage = this.sessionPages[this.activeSessionName];
|
|
1676
|
+
|
|
1677
|
+
if (activeSessionPage) {
|
|
1678
|
+
return activeSessionPage.screenshot({
|
|
1679
|
+
path: outputFile,
|
|
1680
|
+
fullPage: fullPageOption,
|
|
1681
|
+
type: 'png',
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1620
1684
|
}
|
|
1685
|
+
|
|
1621
1686
|
return this.page.screenshot({ path: outputFile, fullPage: fullPageOption, type: 'png' });
|
|
1622
1687
|
}
|
|
1623
1688
|
|
|
@@ -1898,7 +1963,7 @@ class Puppeteer extends Helper {
|
|
|
1898
1963
|
}, { timeout: waitTimeout }, locator.value, text, $XPath.toString());
|
|
1899
1964
|
}
|
|
1900
1965
|
} else {
|
|
1901
|
-
waiter = contextObject.waitForFunction(text => document.body.innerText.indexOf(text) > -1, { timeout: waitTimeout }, text);
|
|
1966
|
+
waiter = contextObject.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, { timeout: waitTimeout }, text);
|
|
1902
1967
|
}
|
|
1903
1968
|
|
|
1904
1969
|
return waiter.catch((err) => {
|
package/lib/helper/REST.js
CHANGED
|
@@ -75,7 +75,9 @@ class REST extends Helper {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
if ((typeof request.data) === 'string') {
|
|
78
|
-
request.headers
|
|
78
|
+
if (!request.headers || !request.headers['Content-Type']) {
|
|
79
|
+
request.headers = Object.assign(request.headers, { 'Content-Type': 'application/x-www-form-urlencoded' });
|
|
80
|
+
}
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
if (this.config.onRequest) {
|
package/lib/helper/TestCafe.js
CHANGED
|
@@ -1208,7 +1208,7 @@ async function proceedClick(locator, context = null) {
|
|
|
1208
1208
|
await assertElementExists(els, locator, 'Clickable element');
|
|
1209
1209
|
}
|
|
1210
1210
|
|
|
1211
|
-
const firstElement = await els.nth(0);
|
|
1211
|
+
const firstElement = await els.filterVisible().nth(0);
|
|
1212
1212
|
|
|
1213
1213
|
return this.t
|
|
1214
1214
|
.click(firstElement)
|