codeceptjs 3.2.3 → 3.3.0-beta.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 +50 -0
- package/docs/advanced.md +0 -4
- package/docs/api.md +227 -188
- package/docs/build/ApiDataFactory.js +13 -6
- package/docs/build/Appium.js +36 -36
- package/docs/build/GraphQL.js +11 -0
- package/docs/build/JSONResponse.js +297 -0
- package/docs/build/Nightmare.js +48 -48
- package/docs/build/Playwright.js +261 -146
- package/docs/build/Puppeteer.js +76 -67
- package/docs/build/REST.js +36 -0
- package/docs/build/TestCafe.js +44 -44
- package/docs/build/WebDriver.js +69 -69
- package/docs/helpers/ApiDataFactory.md +7 -0
- package/docs/helpers/Appium.md +3 -3
- package/docs/helpers/JSONResponse.md +230 -0
- package/docs/helpers/Playwright.md +282 -218
- package/docs/helpers/Puppeteer.md +9 -1
- package/docs/helpers/REST.md +30 -9
- package/docs/installation.md +2 -0
- package/docs/internal-api.md +265 -0
- package/docs/playwright.md +70 -15
- package/docs/plugins.md +125 -29
- package/docs/puppeteer.md +24 -8
- package/docs/quickstart.md +2 -3
- package/docs/reports.md +43 -2
- package/docs/translation.md +1 -1
- package/docs/videos.md +2 -2
- package/docs/webdriver.md +90 -2
- package/lib/command/init.js +5 -15
- package/lib/config.js +17 -13
- package/lib/helper/ApiDataFactory.js +13 -6
- package/lib/helper/Appium.js +3 -3
- package/lib/helper/GraphQL.js +11 -0
- package/lib/helper/JSONResponse.js +297 -0
- package/lib/helper/Playwright.js +199 -84
- package/lib/helper/Puppeteer.js +12 -3
- package/lib/helper/REST.js +36 -0
- package/lib/helper/extras/Console.js +8 -0
- package/lib/helper/extras/PlaywrightRestartOpts.js +35 -0
- package/lib/interfaces/bdd.js +3 -1
- package/lib/plugin/allure.js +12 -0
- package/lib/plugin/eachElement.js +127 -0
- package/lib/utils.js +20 -0
- package/package.json +6 -4
- package/translations/pt-BR.js +8 -0
- package/typings/index.d.ts +2 -0
- package/typings/types.d.ts +237 -11
package/docs/build/Playwright.js
CHANGED
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
getNormalizedKeyAttributeValue,
|
|
20
20
|
isModifierKey,
|
|
21
21
|
clearString,
|
|
22
|
+
requireWithFallback,
|
|
22
23
|
} = require('../utils');
|
|
23
24
|
const {
|
|
24
25
|
isColorProperty,
|
|
@@ -38,6 +39,9 @@ const popupStore = new Popup();
|
|
|
38
39
|
const consoleLogStore = new Console();
|
|
39
40
|
const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron'];
|
|
40
41
|
|
|
42
|
+
const {
|
|
43
|
+
setRestartStrategy, restartsSession, restartsContext, restartsBrowser,
|
|
44
|
+
} = require('./extras/PlaywrightRestartOpts');
|
|
41
45
|
const { createValueEngine, createDisabledEngine } = require('./extras/PlaywrightPropEngine');
|
|
42
46
|
|
|
43
47
|
/**
|
|
@@ -49,12 +53,18 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
49
53
|
*
|
|
50
54
|
* This helper works with a browser out of the box with no additional tools required to install.
|
|
51
55
|
*
|
|
52
|
-
* Requires `playwright` package version ^1 to be installed:
|
|
56
|
+
* Requires `playwright` or `playwright-core` package version ^1 to be installed:
|
|
53
57
|
*
|
|
54
58
|
* ```
|
|
55
|
-
* npm i playwright@^1 --save
|
|
59
|
+
* npm i playwright@^1.18 --save
|
|
60
|
+
* ```
|
|
61
|
+
* or
|
|
62
|
+
* ```
|
|
63
|
+
* npm i playwright-core@^1.18 --save
|
|
56
64
|
* ```
|
|
57
65
|
*
|
|
66
|
+
* Using playwright-core package, will prevent the download of browser binaries and allow connecting to an existing browser installation or for connecting to a remote one.
|
|
67
|
+
*
|
|
58
68
|
* ## Configuration
|
|
59
69
|
*
|
|
60
70
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -62,15 +72,19 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
62
72
|
* * `url`: base url of website to be tested
|
|
63
73
|
* * `browser`: a browser to test on, either: `chromium`, `firefox`, `webkit`, `electron`. Default: chromium.
|
|
64
74
|
* * `show`: (optional, default: false) - show browser window.
|
|
65
|
-
* * `restart`: (optional, default:
|
|
75
|
+
* * `restart`: (optional, default: false) - restart strategy between tests. Possible values:
|
|
76
|
+
* * 'context' or **false** - restarts [browser context](https://playwright.dev/docs/api/class-browsercontext) but keeps running browser. Recommended by Playwright team to keep tests isolated.
|
|
77
|
+
* * 'browser' or **true** - closes browser and opens it again between tests.
|
|
78
|
+
* * 'session' or 'keep' - keeps browser context and session, but cleans up cookies and localStorage between tests. The fastest option when running tests in windowed mode. Works with `keepCookies` and `keepBrowserState` options. This behavior was default before CodeceptJS 3.1
|
|
79
|
+
* * `timeout`: (optional, default: 1000) - [timeout](https://playwright.dev/docs/api/class-page#page-set-default-timeout) in ms of all Playwright actions .
|
|
66
80
|
* * `disableScreenshots`: (optional, default: false) - don't save screenshot on failure.
|
|
67
81
|
* * `emulate`: (optional, default: {}) launch browser in device emulation mode.
|
|
68
82
|
* * `video`: (optional, default: false) enables video recording for failed tests; videos are saved into `output/videos` folder
|
|
69
83
|
* * `trace`: (optional, default: false) record [tracing information](https://playwright.dev/docs/trace-viewer) with screenshots and snapshots.
|
|
70
84
|
* * `fullPageScreenshots` (optional, default: false) - make full page screenshots on failure.
|
|
71
85
|
* * `uniqueScreenshotNames`: (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites.
|
|
72
|
-
* * `keepBrowserState`: (optional, default: false) - keep browser state between tests when `restart` is set to
|
|
73
|
-
* * `keepCookies`: (optional, default: false) - keep cookies between tests when `restart` is set to
|
|
86
|
+
* * `keepBrowserState`: (optional, default: false) - keep browser state between tests when `restart` is set to 'session'.
|
|
87
|
+
* * `keepCookies`: (optional, default: false) - keep cookies between tests when `restart` is set to 'session'.
|
|
74
88
|
* * `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
75
89
|
* * `waitForNavigation`: (optional, default: 'load'). When to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle`. Choose one of those options is possible. See [Playwright API](https://github.com/microsoft/playwright/blob/main/docs/api.md#pagewaitfornavigationoptions).
|
|
76
90
|
* * `pressKeyDelay`: (optional, default: '10'). Delay between key presses in ms. Used when calling Playwrights page.type(...) in fillField/appendField
|
|
@@ -235,7 +249,7 @@ class Playwright extends Helper {
|
|
|
235
249
|
constructor(config) {
|
|
236
250
|
super(config);
|
|
237
251
|
|
|
238
|
-
playwright =
|
|
252
|
+
playwright = requireWithFallback('playwright', 'playwright-core');
|
|
239
253
|
|
|
240
254
|
// set defaults
|
|
241
255
|
this.isRemoteBrowser = false;
|
|
@@ -259,8 +273,10 @@ class Playwright extends Helper {
|
|
|
259
273
|
waitForAction: 100,
|
|
260
274
|
waitForTimeout: 1000,
|
|
261
275
|
pressKeyDelay: 10,
|
|
276
|
+
timeout: 1000,
|
|
262
277
|
fullPageScreenshots: false,
|
|
263
278
|
disableScreenshots: false,
|
|
279
|
+
ignoreLog: ['warning', 'log'],
|
|
264
280
|
uniqueScreenshotNames: false,
|
|
265
281
|
manualStart: false,
|
|
266
282
|
getPageTimeout: 0,
|
|
@@ -270,6 +286,7 @@ class Playwright extends Helper {
|
|
|
270
286
|
keepBrowserState: false,
|
|
271
287
|
show: false,
|
|
272
288
|
defaultPopupAction: 'accept',
|
|
289
|
+
use: { actionTimeout: 0 },
|
|
273
290
|
ignoreHTTPSErrors: false, // Adding it here o that context can be set up to ignore the SSL errors
|
|
274
291
|
};
|
|
275
292
|
|
|
@@ -297,6 +314,7 @@ class Playwright extends Helper {
|
|
|
297
314
|
|
|
298
315
|
_setConfig(config) {
|
|
299
316
|
this.options = this._validateConfig(config);
|
|
317
|
+
setRestartStrategy(this.options);
|
|
300
318
|
this.playwrightOptions = {
|
|
301
319
|
headless: !this.options.show,
|
|
302
320
|
...this._getOptionsForBrowser(config),
|
|
@@ -334,9 +352,9 @@ class Playwright extends Helper {
|
|
|
334
352
|
|
|
335
353
|
static _checkRequirements() {
|
|
336
354
|
try {
|
|
337
|
-
|
|
355
|
+
requireWithFallback('playwright', 'playwright-core');
|
|
338
356
|
} catch (e) {
|
|
339
|
-
return ['playwright@^1'];
|
|
357
|
+
return ['playwright@^1.18'];
|
|
340
358
|
}
|
|
341
359
|
}
|
|
342
360
|
|
|
@@ -353,7 +371,7 @@ class Playwright extends Helper {
|
|
|
353
371
|
}
|
|
354
372
|
|
|
355
373
|
_beforeSuite() {
|
|
356
|
-
if (
|
|
374
|
+
if ((restartsSession() || restartsContext()) && !this.options.manualStart && !this.isRunning) {
|
|
357
375
|
this.debugSection('Session', 'Starting singleton browser session');
|
|
358
376
|
return this._startBrowser();
|
|
359
377
|
}
|
|
@@ -371,7 +389,7 @@ class Playwright extends Helper {
|
|
|
371
389
|
},
|
|
372
390
|
});
|
|
373
391
|
|
|
374
|
-
if (
|
|
392
|
+
if (restartsBrowser() && !this.options.manualStart) await this._startBrowser();
|
|
375
393
|
if (!this.isRunning && !this.options.manualStart) await this._startBrowser();
|
|
376
394
|
|
|
377
395
|
this.isAuthenticated = false;
|
|
@@ -393,7 +411,9 @@ class Playwright extends Helper {
|
|
|
393
411
|
if (this.storageState) contextOptions.storageState = this.storageState;
|
|
394
412
|
if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent;
|
|
395
413
|
if (this.options.locale) contextOptions.locale = this.options.locale;
|
|
396
|
-
this.browserContext
|
|
414
|
+
if (!this.browserContext || !restartsSession()) {
|
|
415
|
+
this.browserContext = await this.browser.newContext(contextOptions); // Adding the HTTPSError ignore in the context so that we can ignore those errors
|
|
416
|
+
}
|
|
397
417
|
}
|
|
398
418
|
|
|
399
419
|
let mainPage;
|
|
@@ -421,7 +441,11 @@ class Playwright extends Helper {
|
|
|
421
441
|
return;
|
|
422
442
|
}
|
|
423
443
|
|
|
424
|
-
if (
|
|
444
|
+
if (restartsSession()) {
|
|
445
|
+
return refreshContextSession.bind(this)();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (restartsBrowser()) {
|
|
425
449
|
this.isRunning = false;
|
|
426
450
|
return this._stopBrowser();
|
|
427
451
|
}
|
|
@@ -443,11 +467,10 @@ class Playwright extends Helper {
|
|
|
443
467
|
return this.browser;
|
|
444
468
|
}
|
|
445
469
|
|
|
446
|
-
_afterSuite() {
|
|
447
|
-
}
|
|
470
|
+
_afterSuite() {}
|
|
448
471
|
|
|
449
|
-
_finishTest() {
|
|
450
|
-
if (
|
|
472
|
+
async _finishTest() {
|
|
473
|
+
if ((restartsSession() || restartsContext()) && this.isRunning) return this._stopBrowser();
|
|
451
474
|
}
|
|
452
475
|
|
|
453
476
|
_session() {
|
|
@@ -506,16 +529,16 @@ class Playwright extends Helper {
|
|
|
506
529
|
* First argument is a description of an action.
|
|
507
530
|
* Second argument is async function that gets this helper as parameter.
|
|
508
531
|
*
|
|
509
|
-
* { [`page`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-page.md), [`
|
|
532
|
+
* { [`page`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-page.md), [`browserContext`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-browsercontext.md) [`browser`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-browser.md) } objects from Playwright API are available.
|
|
510
533
|
*
|
|
511
534
|
* ```js
|
|
512
|
-
* I.usePlaywrightTo('emulate offline mode', async ({
|
|
513
|
-
* await
|
|
535
|
+
* I.usePlaywrightTo('emulate offline mode', async ({ browserContext }) => {
|
|
536
|
+
* await browserContext.setOffline(true);
|
|
514
537
|
* });
|
|
515
538
|
* ```
|
|
516
539
|
*
|
|
517
540
|
* @param {string} description used to show in logs.
|
|
518
|
-
* @param {function} fn async
|
|
541
|
+
* @param {function} fn async function that executed with Playwright helper as argument
|
|
519
542
|
*/
|
|
520
543
|
usePlaywrightTo(description, fn) {
|
|
521
544
|
return this._useTo(...arguments);
|
|
@@ -590,7 +613,9 @@ class Playwright extends Helper {
|
|
|
590
613
|
this._addPopupListener(page);
|
|
591
614
|
this.page = page;
|
|
592
615
|
if (!page) return;
|
|
616
|
+
this.browserContext.setDefaultTimeout(0);
|
|
593
617
|
page.setDefaultNavigationTimeout(this.options.getPageTimeout);
|
|
618
|
+
page.setDefaultTimeout(this.options.timeout);
|
|
594
619
|
|
|
595
620
|
page.on('crash', async () => {
|
|
596
621
|
console.log('ERROR: Page has crashed, closing page!');
|
|
@@ -691,7 +716,6 @@ class Playwright extends Helper {
|
|
|
691
716
|
this._setPage(null);
|
|
692
717
|
this.context = null;
|
|
693
718
|
popupStore.clear();
|
|
694
|
-
|
|
695
719
|
await this.browser.close();
|
|
696
720
|
}
|
|
697
721
|
|
|
@@ -839,7 +863,7 @@ class Playwright extends Helper {
|
|
|
839
863
|
* I.moveCursorTo('#submit', 5,5);
|
|
840
864
|
* ```
|
|
841
865
|
*
|
|
842
|
-
* @param {
|
|
866
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
843
867
|
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
844
868
|
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
845
869
|
*
|
|
@@ -862,12 +886,24 @@ class Playwright extends Helper {
|
|
|
862
886
|
* I.dragAndDrop('#dragHandle', '#container');
|
|
863
887
|
* ```
|
|
864
888
|
*
|
|
865
|
-
* @param {
|
|
866
|
-
* @param {
|
|
889
|
+
* @param {string | object} srcElement located by CSS|XPath|strict locator.
|
|
890
|
+
* @param {string | object} destElement located by CSS|XPath|strict locator.
|
|
867
891
|
*
|
|
892
|
+
*
|
|
893
|
+
* [Additional options](https://playwright.dev/docs/api/class-page#page-drag-and-drop) can be passed as 3rd argument.
|
|
894
|
+
*
|
|
895
|
+
* ```js
|
|
896
|
+
* // specify coordinates for source position
|
|
897
|
+
* I.dragAndDrop('img.src', 'img.dst', { sourcePosition: {x: 10, y: 10} })
|
|
898
|
+
* ```
|
|
899
|
+
*
|
|
900
|
+
* > By default option `force: true` is set
|
|
868
901
|
*/
|
|
869
|
-
async dragAndDrop(srcElement, destElement) {
|
|
870
|
-
|
|
902
|
+
async dragAndDrop(srcElement, destElement, options = { force: true }) {
|
|
903
|
+
const src = new Locator(srcElement, 'css');
|
|
904
|
+
const dst = new Locator(destElement, 'css');
|
|
905
|
+
|
|
906
|
+
return this.page.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options);
|
|
871
907
|
}
|
|
872
908
|
|
|
873
909
|
/**
|
|
@@ -924,7 +960,7 @@ class Playwright extends Helper {
|
|
|
924
960
|
* I.scrollTo('#submit', 5, 5);
|
|
925
961
|
* ```
|
|
926
962
|
*
|
|
927
|
-
* @param {
|
|
963
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
928
964
|
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
929
965
|
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
930
966
|
*/
|
|
@@ -1212,7 +1248,7 @@ class Playwright extends Helper {
|
|
|
1212
1248
|
* ```js
|
|
1213
1249
|
* I.seeElement('#modal');
|
|
1214
1250
|
* ```
|
|
1215
|
-
* @param {
|
|
1251
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
1216
1252
|
*
|
|
1217
1253
|
*/
|
|
1218
1254
|
async seeElement(locator) {
|
|
@@ -1228,7 +1264,7 @@ class Playwright extends Helper {
|
|
|
1228
1264
|
* I.dontSeeElement('.modal'); // modal is not shown
|
|
1229
1265
|
* ```
|
|
1230
1266
|
*
|
|
1231
|
-
* @param {
|
|
1267
|
+
* @param {string | object} locator located by CSS|XPath|Strict locator.
|
|
1232
1268
|
*
|
|
1233
1269
|
*/
|
|
1234
1270
|
async dontSeeElement(locator) {
|
|
@@ -1244,7 +1280,7 @@ class Playwright extends Helper {
|
|
|
1244
1280
|
* ```js
|
|
1245
1281
|
* I.seeElementInDOM('#modal');
|
|
1246
1282
|
* ```
|
|
1247
|
-
* @param {
|
|
1283
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
1248
1284
|
*
|
|
1249
1285
|
*/
|
|
1250
1286
|
async seeElementInDOM(locator) {
|
|
@@ -1259,7 +1295,7 @@ class Playwright extends Helper {
|
|
|
1259
1295
|
* I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
|
|
1260
1296
|
* ```
|
|
1261
1297
|
*
|
|
1262
|
-
* @param {
|
|
1298
|
+
* @param {string | object} locator located by CSS|XPath|Strict locator.
|
|
1263
1299
|
*/
|
|
1264
1300
|
async dontSeeElementInDOM(locator) {
|
|
1265
1301
|
const els = await this._locate(locator);
|
|
@@ -1319,14 +1355,25 @@ class Playwright extends Helper {
|
|
|
1319
1355
|
* I.click({css: 'nav a.login'});
|
|
1320
1356
|
* ```
|
|
1321
1357
|
*
|
|
1322
|
-
* @param {
|
|
1323
|
-
* @param {?
|
|
1358
|
+
* @param {string | object} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
1359
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
1324
1360
|
*
|
|
1325
1361
|
*
|
|
1362
|
+
* [Additional options](https://playwright.dev/docs/api/class-page#page-click) for click available as 3rd argument.
|
|
1363
|
+
*
|
|
1364
|
+
* Examples:
|
|
1365
|
+
*
|
|
1366
|
+
* ```js
|
|
1367
|
+
* // click on element at position
|
|
1368
|
+
* I.click('canvas', '.model', { position: { x: 20, y: 40 } })
|
|
1369
|
+
*
|
|
1370
|
+
* // make ctrl-click
|
|
1371
|
+
* I.click('.edit', null, { modifiers: ['Ctrl'] } )
|
|
1372
|
+
* ```
|
|
1326
1373
|
*
|
|
1327
1374
|
*/
|
|
1328
|
-
async click(locator, context = null) {
|
|
1329
|
-
return proceedClick.call(this, locator, context);
|
|
1375
|
+
async click(locator, context = null, opts = {}) {
|
|
1376
|
+
return proceedClick.call(this, locator, context, opts);
|
|
1330
1377
|
}
|
|
1331
1378
|
|
|
1332
1379
|
/**
|
|
@@ -1364,8 +1411,8 @@ class Playwright extends Helper {
|
|
|
1364
1411
|
* I.forceClick({css: 'nav a.login'});
|
|
1365
1412
|
* ```
|
|
1366
1413
|
*
|
|
1367
|
-
* @param {
|
|
1368
|
-
* @param {?
|
|
1414
|
+
* @param {string | object} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
1415
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
1369
1416
|
*
|
|
1370
1417
|
*/
|
|
1371
1418
|
async forceClick(locator, context = null) {
|
|
@@ -1383,8 +1430,8 @@ class Playwright extends Helper {
|
|
|
1383
1430
|
* I.doubleClick('.btn.edit');
|
|
1384
1431
|
* ```
|
|
1385
1432
|
*
|
|
1386
|
-
* @param {
|
|
1387
|
-
* @param {?
|
|
1433
|
+
* @param {string | object} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
1434
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
1388
1435
|
*
|
|
1389
1436
|
*
|
|
1390
1437
|
*
|
|
@@ -1405,8 +1452,8 @@ class Playwright extends Helper {
|
|
|
1405
1452
|
* I.rightClick('Click me', '.context');
|
|
1406
1453
|
* ```
|
|
1407
1454
|
*
|
|
1408
|
-
* @param {
|
|
1409
|
-
* @param {?
|
|
1455
|
+
* @param {string | object} locator clickable element located by CSS|XPath|strict locator.
|
|
1456
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
1410
1457
|
*
|
|
1411
1458
|
*
|
|
1412
1459
|
*
|
|
@@ -1426,18 +1473,23 @@ class Playwright extends Helper {
|
|
|
1426
1473
|
* I.checkOption('I Agree to Terms and Conditions');
|
|
1427
1474
|
* I.checkOption('agree', '//form');
|
|
1428
1475
|
* ```
|
|
1429
|
-
* @param {
|
|
1430
|
-
* @param {?
|
|
1476
|
+
* @param {string | object} field checkbox located by label | name | CSS | XPath | strict locator.
|
|
1477
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
|
|
1478
|
+
*
|
|
1479
|
+
* [Additional options](https://playwright.dev/docs/api/class-elementhandle#element-handle-check) for check available as 3rd argument.
|
|
1480
|
+
*
|
|
1481
|
+
* Examples:
|
|
1482
|
+
*
|
|
1483
|
+
* ```js
|
|
1484
|
+
* // click on element at position
|
|
1485
|
+
* I.checkOption('Agree', '.signup', { position: { x: 5, y: 5 } })
|
|
1486
|
+
* ```
|
|
1487
|
+
* > ⚠️ To avoid flakiness, option `force: true` is set by default
|
|
1431
1488
|
*/
|
|
1432
|
-
async checkOption(field, context = null) {
|
|
1489
|
+
async checkOption(field, context = null, options = { force: true }) {
|
|
1433
1490
|
const elm = await this._locateCheckable(field, context);
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
// Only check if NOT currently checked
|
|
1437
|
-
if (!curentlyChecked) {
|
|
1438
|
-
await elm.click();
|
|
1439
|
-
return this._waitForAction();
|
|
1440
|
-
}
|
|
1491
|
+
await elm.check(options);
|
|
1492
|
+
return this._waitForAction();
|
|
1441
1493
|
}
|
|
1442
1494
|
|
|
1443
1495
|
/**
|
|
@@ -1451,18 +1503,23 @@ class Playwright extends Helper {
|
|
|
1451
1503
|
* I.uncheckOption('I Agree to Terms and Conditions');
|
|
1452
1504
|
* I.uncheckOption('agree', '//form');
|
|
1453
1505
|
* ```
|
|
1454
|
-
* @param {
|
|
1455
|
-
* @param {?
|
|
1506
|
+
* @param {string | object} field checkbox located by label | name | CSS | XPath | strict locator.
|
|
1507
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
|
|
1508
|
+
*
|
|
1509
|
+
* [Additional options](https://playwright.dev/docs/api/class-elementhandle#element-handle-uncheck) for uncheck available as 3rd argument.
|
|
1510
|
+
*
|
|
1511
|
+
* Examples:
|
|
1512
|
+
*
|
|
1513
|
+
* ```js
|
|
1514
|
+
* // click on element at position
|
|
1515
|
+
* I.uncheckOption('Agree', '.signup', { position: { x: 5, y: 5 } })
|
|
1516
|
+
* ```
|
|
1517
|
+
* > ⚠️ To avoid flakiness, option `force: true` is set by default
|
|
1456
1518
|
*/
|
|
1457
|
-
async uncheckOption(field, context = null) {
|
|
1519
|
+
async uncheckOption(field, context = null, options = { force: true }) {
|
|
1458
1520
|
const elm = await this._locateCheckable(field, context);
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
// Only uncheck if currently checked
|
|
1462
|
-
if (curentlyChecked) {
|
|
1463
|
-
await elm.click();
|
|
1464
|
-
return this._waitForAction();
|
|
1465
|
-
}
|
|
1521
|
+
await elm.uncheck(options);
|
|
1522
|
+
return this._waitForAction();
|
|
1466
1523
|
}
|
|
1467
1524
|
|
|
1468
1525
|
/**
|
|
@@ -1474,7 +1531,7 @@ class Playwright extends Helper {
|
|
|
1474
1531
|
* I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
|
|
1475
1532
|
* ```
|
|
1476
1533
|
*
|
|
1477
|
-
* @param {
|
|
1534
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1478
1535
|
*
|
|
1479
1536
|
*/
|
|
1480
1537
|
async seeCheckboxIsChecked(field) {
|
|
@@ -1490,7 +1547,7 @@ class Playwright extends Helper {
|
|
|
1490
1547
|
* I.dontSeeCheckboxIsChecked('agree'); // located by name
|
|
1491
1548
|
* ```
|
|
1492
1549
|
*
|
|
1493
|
-
* @param {
|
|
1550
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1494
1551
|
*
|
|
1495
1552
|
*/
|
|
1496
1553
|
async dontSeeCheckboxIsChecked(field) {
|
|
@@ -1671,8 +1728,8 @@ class Playwright extends Helper {
|
|
|
1671
1728
|
* // or by strict locator
|
|
1672
1729
|
* I.fillField({css: 'form#login input[name=username]'}, 'John');
|
|
1673
1730
|
* ```
|
|
1674
|
-
* @param {
|
|
1675
|
-
* @param {
|
|
1731
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1732
|
+
* @param {string | object} value text value to fill.
|
|
1676
1733
|
*
|
|
1677
1734
|
*
|
|
1678
1735
|
*/
|
|
@@ -1699,7 +1756,7 @@ class Playwright extends Helper {
|
|
|
1699
1756
|
* I.clearField('user[email]');
|
|
1700
1757
|
* I.clearField('#email');
|
|
1701
1758
|
* ```
|
|
1702
|
-
* @param {
|
|
1759
|
+
* @param {string | object} editable field located by label|name|CSS|XPath|strict locator.
|
|
1703
1760
|
*
|
|
1704
1761
|
*/
|
|
1705
1762
|
async clearField(field) {
|
|
@@ -1713,7 +1770,7 @@ class Playwright extends Helper {
|
|
|
1713
1770
|
* ```js
|
|
1714
1771
|
* I.appendField('#myTextField', 'appended');
|
|
1715
1772
|
* ```
|
|
1716
|
-
* @param {
|
|
1773
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator
|
|
1717
1774
|
* @param {string} value text value to append.
|
|
1718
1775
|
*
|
|
1719
1776
|
*
|
|
@@ -1736,7 +1793,7 @@ class Playwright extends Helper {
|
|
|
1736
1793
|
* I.seeInField('form input[type=hidden]','hidden_value');
|
|
1737
1794
|
* I.seeInField('#searchform input','Search');
|
|
1738
1795
|
* ```
|
|
1739
|
-
* @param {
|
|
1796
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1740
1797
|
* @param {string} value value to check.
|
|
1741
1798
|
*
|
|
1742
1799
|
*/
|
|
@@ -1753,7 +1810,7 @@ class Playwright extends Helper {
|
|
|
1753
1810
|
* I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
|
|
1754
1811
|
* ```
|
|
1755
1812
|
*
|
|
1756
|
-
* @param {
|
|
1813
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1757
1814
|
* @param {string} value value to check.
|
|
1758
1815
|
*/
|
|
1759
1816
|
async dontSeeInField(field, value) {
|
|
@@ -1770,7 +1827,7 @@ class Playwright extends Helper {
|
|
|
1770
1827
|
* I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
|
|
1771
1828
|
* ```
|
|
1772
1829
|
*
|
|
1773
|
-
* @param {
|
|
1830
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
1774
1831
|
* @param {string} pathToFile local file path relative to codecept.json config file.
|
|
1775
1832
|
*
|
|
1776
1833
|
*/
|
|
@@ -1805,7 +1862,7 @@ class Playwright extends Helper {
|
|
|
1805
1862
|
* ```js
|
|
1806
1863
|
* I.selectOption('Which OS do you use?', ['Android', 'iOS']);
|
|
1807
1864
|
* ```
|
|
1808
|
-
* @param {
|
|
1865
|
+
* @param {string | object} select field located by label|name|CSS|XPath|strict locator.
|
|
1809
1866
|
* @param {string|Array<*>} option visible text or value of option.
|
|
1810
1867
|
*
|
|
1811
1868
|
*/
|
|
@@ -1846,7 +1903,7 @@ class Playwright extends Helper {
|
|
|
1846
1903
|
* let numOfElements = await I.grabNumberOfVisibleElements('p');
|
|
1847
1904
|
* ```
|
|
1848
1905
|
*
|
|
1849
|
-
* @param {
|
|
1906
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
1850
1907
|
* @returns {Promise<number>} number of visible elements
|
|
1851
1908
|
*
|
|
1852
1909
|
*/
|
|
@@ -1919,7 +1976,7 @@ class Playwright extends Helper {
|
|
|
1919
1976
|
* I.see('Register', {css: 'form.register'}); // use strict locator
|
|
1920
1977
|
* ```
|
|
1921
1978
|
* @param {string} text expected on page.
|
|
1922
|
-
* @param {?
|
|
1979
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
|
|
1923
1980
|
*
|
|
1924
1981
|
*
|
|
1925
1982
|
*/
|
|
@@ -1935,7 +1992,7 @@ class Playwright extends Helper {
|
|
|
1935
1992
|
* ```
|
|
1936
1993
|
*
|
|
1937
1994
|
* @param {string} text element value to check.
|
|
1938
|
-
* @param {
|
|
1995
|
+
* @param {(string | object)?} [context=null] element located by CSS|XPath|strict locator.
|
|
1939
1996
|
*/
|
|
1940
1997
|
async seeTextEquals(text, context = null) {
|
|
1941
1998
|
return proceedSee.call(this, 'assert', text, context, true);
|
|
@@ -1951,7 +2008,7 @@ class Playwright extends Helper {
|
|
|
1951
2008
|
* ```
|
|
1952
2009
|
*
|
|
1953
2010
|
* @param {string} text which is not present.
|
|
1954
|
-
* @param {
|
|
2011
|
+
* @param {string | object} [context] (optional) element located by CSS|XPath|strict locator in which to perfrom search.
|
|
1955
2012
|
*
|
|
1956
2013
|
*
|
|
1957
2014
|
*
|
|
@@ -2041,7 +2098,7 @@ class Playwright extends Helper {
|
|
|
2041
2098
|
* I.seeNumberOfElements('#submitBtn', 1);
|
|
2042
2099
|
* ```
|
|
2043
2100
|
*
|
|
2044
|
-
* @param {
|
|
2101
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2045
2102
|
* @param {number} num number of elements.
|
|
2046
2103
|
*
|
|
2047
2104
|
*
|
|
@@ -2060,7 +2117,7 @@ class Playwright extends Helper {
|
|
|
2060
2117
|
* I.seeNumberOfVisibleElements('.buttons', 3);
|
|
2061
2118
|
* ```
|
|
2062
2119
|
*
|
|
2063
|
-
* @param {
|
|
2120
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2064
2121
|
* @param {number} num number of elements.
|
|
2065
2122
|
*
|
|
2066
2123
|
*
|
|
@@ -2224,7 +2281,7 @@ class Playwright extends Helper {
|
|
|
2224
2281
|
* ```
|
|
2225
2282
|
* If multiple elements found returns first element.
|
|
2226
2283
|
*
|
|
2227
|
-
* @param {
|
|
2284
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2228
2285
|
* @returns {Promise<string>} attribute value
|
|
2229
2286
|
*
|
|
2230
2287
|
*
|
|
@@ -2245,7 +2302,7 @@ class Playwright extends Helper {
|
|
|
2245
2302
|
* let pins = await I.grabTextFromAll('#pin li');
|
|
2246
2303
|
* ```
|
|
2247
2304
|
*
|
|
2248
|
-
* @param {
|
|
2305
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2249
2306
|
* @returns {Promise<string[]>} attribute value
|
|
2250
2307
|
*
|
|
2251
2308
|
*
|
|
@@ -2268,7 +2325,7 @@ class Playwright extends Helper {
|
|
|
2268
2325
|
* ```js
|
|
2269
2326
|
* let email = await I.grabValueFrom('input[name=email]');
|
|
2270
2327
|
* ```
|
|
2271
|
-
* @param {
|
|
2328
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
2272
2329
|
* @returns {Promise<string>} attribute value
|
|
2273
2330
|
*
|
|
2274
2331
|
*/
|
|
@@ -2286,7 +2343,7 @@ class Playwright extends Helper {
|
|
|
2286
2343
|
* ```js
|
|
2287
2344
|
* let inputs = await I.grabValueFromAll('//form/input');
|
|
2288
2345
|
* ```
|
|
2289
|
-
* @param {
|
|
2346
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
2290
2347
|
* @returns {Promise<string[]>} attribute value
|
|
2291
2348
|
*
|
|
2292
2349
|
*/
|
|
@@ -2305,7 +2362,7 @@ class Playwright extends Helper {
|
|
|
2305
2362
|
* let postHTML = await I.grabHTMLFrom('#post');
|
|
2306
2363
|
* ```
|
|
2307
2364
|
*
|
|
2308
|
-
* @param {
|
|
2365
|
+
* @param {string | object} element located by CSS|XPath|strict locator.
|
|
2309
2366
|
* @returns {Promise<string>} HTML code for an element
|
|
2310
2367
|
*
|
|
2311
2368
|
*/
|
|
@@ -2324,7 +2381,7 @@ class Playwright extends Helper {
|
|
|
2324
2381
|
* let postHTMLs = await I.grabHTMLFromAll('.post');
|
|
2325
2382
|
* ```
|
|
2326
2383
|
*
|
|
2327
|
-
* @param {
|
|
2384
|
+
* @param {string | object} element located by CSS|XPath|strict locator.
|
|
2328
2385
|
* @returns {Promise<string[]>} HTML code for an element
|
|
2329
2386
|
*
|
|
2330
2387
|
*/
|
|
@@ -2343,7 +2400,7 @@ class Playwright extends Helper {
|
|
|
2343
2400
|
* const value = await I.grabCssPropertyFrom('h3', 'font-weight');
|
|
2344
2401
|
* ```
|
|
2345
2402
|
*
|
|
2346
|
-
* @param {
|
|
2403
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2347
2404
|
* @param {string} cssProperty CSS property name.
|
|
2348
2405
|
* @returns {Promise<string>} CSS value
|
|
2349
2406
|
*
|
|
@@ -2364,7 +2421,7 @@ class Playwright extends Helper {
|
|
|
2364
2421
|
* const values = await I.grabCssPropertyFromAll('h3', 'font-weight');
|
|
2365
2422
|
* ```
|
|
2366
2423
|
*
|
|
2367
|
-
* @param {
|
|
2424
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2368
2425
|
* @param {string} cssProperty CSS property name.
|
|
2369
2426
|
* @returns {Promise<string[]>} CSS value
|
|
2370
2427
|
*
|
|
@@ -2385,7 +2442,7 @@ class Playwright extends Helper {
|
|
|
2385
2442
|
* I.seeCssPropertiesOnElements('h3', { 'font-weight': "bold"});
|
|
2386
2443
|
* ```
|
|
2387
2444
|
*
|
|
2388
|
-
* @param {
|
|
2445
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
2389
2446
|
* @param {object} cssProperties object with CSS properties and their values to check.
|
|
2390
2447
|
*
|
|
2391
2448
|
*/
|
|
@@ -2430,7 +2487,7 @@ class Playwright extends Helper {
|
|
|
2430
2487
|
* I.seeAttributesOnElements('//form', { method: "post"});
|
|
2431
2488
|
* ```
|
|
2432
2489
|
*
|
|
2433
|
-
* @param {
|
|
2490
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
2434
2491
|
* @param {object} attributes attributes and their values to check.
|
|
2435
2492
|
*
|
|
2436
2493
|
*/
|
|
@@ -2468,7 +2525,7 @@ class Playwright extends Helper {
|
|
|
2468
2525
|
* I.dragSlider('#slider', -70);
|
|
2469
2526
|
* ```
|
|
2470
2527
|
*
|
|
2471
|
-
* @param {
|
|
2528
|
+
* @param {string | object} locator located by label|name|CSS|XPath|strict locator.
|
|
2472
2529
|
* @param {number} offsetX position to drag.
|
|
2473
2530
|
*
|
|
2474
2531
|
*/
|
|
@@ -2498,7 +2555,7 @@ class Playwright extends Helper {
|
|
|
2498
2555
|
* ```js
|
|
2499
2556
|
* let hint = await I.grabAttributeFrom('#tooltip', 'title');
|
|
2500
2557
|
* ```
|
|
2501
|
-
* @param {
|
|
2558
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2502
2559
|
* @param {string} attr attribute name.
|
|
2503
2560
|
* @returns {Promise<string>} attribute value
|
|
2504
2561
|
*
|
|
@@ -2518,7 +2575,7 @@ class Playwright extends Helper {
|
|
|
2518
2575
|
* ```js
|
|
2519
2576
|
* let hints = await I.grabAttributeFromAll('.tooltip', 'title');
|
|
2520
2577
|
* ```
|
|
2521
|
-
* @param {
|
|
2578
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2522
2579
|
* @param {string} attr attribute name.
|
|
2523
2580
|
* @returns {Promise<string[]>} attribute value
|
|
2524
2581
|
*
|
|
@@ -2545,7 +2602,7 @@ class Playwright extends Helper {
|
|
|
2545
2602
|
* I.saveElementScreenshot(`#submit`,'debug.png');
|
|
2546
2603
|
* ```
|
|
2547
2604
|
*
|
|
2548
|
-
* @param {
|
|
2605
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2549
2606
|
* @param {string} fileName file name to save.
|
|
2550
2607
|
*
|
|
2551
2608
|
*
|
|
@@ -2595,6 +2652,53 @@ class Playwright extends Helper {
|
|
|
2595
2652
|
return this.page.screenshot({ path: outputFile, fullPage: fullPageOption, type: 'png' });
|
|
2596
2653
|
}
|
|
2597
2654
|
|
|
2655
|
+
/**
|
|
2656
|
+
* Performs [api request](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get) using
|
|
2657
|
+
* the cookies from the current browser session.
|
|
2658
|
+
*
|
|
2659
|
+
* ```js
|
|
2660
|
+
* const users = await I.makeApiRequest('GET', '/api/users', { params: { page: 1 }});
|
|
2661
|
+
* users[0]
|
|
2662
|
+
* I.makeApiRequest('PATCH', )
|
|
2663
|
+
* ```
|
|
2664
|
+
*
|
|
2665
|
+
* > This is Playwright's built-in alternative to using REST helper's sendGet, sendPost, etc methods.
|
|
2666
|
+
*
|
|
2667
|
+
* @param {string} method HTTP method
|
|
2668
|
+
* @param {string} url endpoint
|
|
2669
|
+
* @param {object} options request options depending on method used
|
|
2670
|
+
* @returns {Promise<object>} response
|
|
2671
|
+
*/
|
|
2672
|
+
async makeApiRequest(method, url, options) {
|
|
2673
|
+
method = method.toLowerCase();
|
|
2674
|
+
const allowedMethods = ['get', 'post', 'patch', 'head', 'fetch', 'delete'];
|
|
2675
|
+
if (!allowedMethods.includes(method)) {
|
|
2676
|
+
throw new Error(`Method ${method} is not allowed, use the one from a list ${allowedMethods} or switch to using REST helper`);
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
if (url.startsWith('/')) { // local url
|
|
2680
|
+
url = this.options.url + url;
|
|
2681
|
+
this.debugSection('URL', url);
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
const response = await this.page.request[method](url, options);
|
|
2685
|
+
this.debugSection('Status', response.status());
|
|
2686
|
+
this.debugSection('Response', await response.text());
|
|
2687
|
+
|
|
2688
|
+
// hook to allow JSON response handle this
|
|
2689
|
+
if (this.config.onResponse) {
|
|
2690
|
+
const axiosResponse = {
|
|
2691
|
+
data: await response.json(),
|
|
2692
|
+
status: response.status(),
|
|
2693
|
+
statusText: response.statusText(),
|
|
2694
|
+
headers: response.headers(),
|
|
2695
|
+
};
|
|
2696
|
+
this.config.onResponse(axiosResponse);
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
return response;
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2598
2702
|
async _failed(test) {
|
|
2599
2703
|
await this._withinEnd();
|
|
2600
2704
|
|
|
@@ -2652,7 +2756,7 @@ class Playwright extends Helper {
|
|
|
2652
2756
|
* Waits for element to become enabled (by default waits for 1sec).
|
|
2653
2757
|
* Element can be located by CSS or XPath.
|
|
2654
2758
|
*
|
|
2655
|
-
* @param {
|
|
2759
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2656
2760
|
* @param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
|
|
2657
2761
|
*/
|
|
2658
2762
|
async waitForEnabled(locator, sec) {
|
|
@@ -2685,7 +2789,7 @@ class Playwright extends Helper {
|
|
|
2685
2789
|
* I.waitForValue('//input', "GoodValue");
|
|
2686
2790
|
* ```
|
|
2687
2791
|
*
|
|
2688
|
-
* @param {
|
|
2792
|
+
* @param {string | object} field input field.
|
|
2689
2793
|
* @param {string }value expected value.
|
|
2690
2794
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2691
2795
|
*
|
|
@@ -2721,7 +2825,7 @@ class Playwright extends Helper {
|
|
|
2721
2825
|
* I.waitNumberOfVisibleElements('a', 3);
|
|
2722
2826
|
* ```
|
|
2723
2827
|
*
|
|
2724
|
-
* @param {
|
|
2828
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2725
2829
|
* @param {number} num number of elements.
|
|
2726
2830
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2727
2831
|
*
|
|
@@ -2762,7 +2866,7 @@ class Playwright extends Helper {
|
|
|
2762
2866
|
* I.waitForClickable('.btn.continue', 5); // wait for 5 secs
|
|
2763
2867
|
* ```
|
|
2764
2868
|
*
|
|
2765
|
-
* @param {
|
|
2869
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2766
2870
|
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
2767
2871
|
*/
|
|
2768
2872
|
async waitForClickable(locator, waitTimeout) {
|
|
@@ -2779,7 +2883,7 @@ class Playwright extends Helper {
|
|
|
2779
2883
|
* I.waitForElement('.btn.continue', 5); // wait for 5 secs
|
|
2780
2884
|
* ```
|
|
2781
2885
|
*
|
|
2782
|
-
* @param {
|
|
2886
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2783
2887
|
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
2784
2888
|
*
|
|
2785
2889
|
*/
|
|
@@ -2802,7 +2906,7 @@ class Playwright extends Helper {
|
|
|
2802
2906
|
* I.waitForVisible('#popup');
|
|
2803
2907
|
* ```
|
|
2804
2908
|
*
|
|
2805
|
-
* @param {
|
|
2909
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2806
2910
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2807
2911
|
*
|
|
2808
2912
|
*
|
|
@@ -2826,7 +2930,7 @@ class Playwright extends Helper {
|
|
|
2826
2930
|
* I.waitForInvisible('#popup');
|
|
2827
2931
|
* ```
|
|
2828
2932
|
*
|
|
2829
|
-
* @param {
|
|
2933
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2830
2934
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2831
2935
|
*/
|
|
2832
2936
|
async waitForInvisible(locator, sec) {
|
|
@@ -2847,7 +2951,7 @@ class Playwright extends Helper {
|
|
|
2847
2951
|
* I.waitToHide('#popup');
|
|
2848
2952
|
* ```
|
|
2849
2953
|
*
|
|
2850
|
-
* @param {
|
|
2954
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2851
2955
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2852
2956
|
*/
|
|
2853
2957
|
async waitToHide(locator, sec) {
|
|
@@ -2936,7 +3040,7 @@ class Playwright extends Helper {
|
|
|
2936
3040
|
*
|
|
2937
3041
|
* @param {string }text to wait for.
|
|
2938
3042
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2939
|
-
* @param {
|
|
3043
|
+
* @param {string | object} [context] (optional) element located by CSS|XPath|strict locator.
|
|
2940
3044
|
*/
|
|
2941
3045
|
async waitForText(text, sec = null, context = null) {
|
|
2942
3046
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -3006,7 +3110,7 @@ class Playwright extends Helper {
|
|
|
3006
3110
|
* I.switchTo(); // switch back to main page
|
|
3007
3111
|
* ```
|
|
3008
3112
|
*
|
|
3009
|
-
* @param {?
|
|
3113
|
+
* @param {?string | object} [locator=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
3010
3114
|
*/
|
|
3011
3115
|
async switchTo(locator) {
|
|
3012
3116
|
if (Number.isInteger(locator)) {
|
|
@@ -3111,7 +3215,7 @@ class Playwright extends Helper {
|
|
|
3111
3215
|
* I.waitForDetached('#popup');
|
|
3112
3216
|
* ```
|
|
3113
3217
|
*
|
|
3114
|
-
* @param {
|
|
3218
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
3115
3219
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
3116
3220
|
*/
|
|
3117
3221
|
async waitForDetached(locator, sec) {
|
|
@@ -3181,7 +3285,7 @@ class Playwright extends Helper {
|
|
|
3181
3285
|
* const width = await I.grabElementBoundingRect('h3', 'width');
|
|
3182
3286
|
* // width == 527
|
|
3183
3287
|
* ```
|
|
3184
|
-
* @param {
|
|
3288
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
3185
3289
|
* @param {string=} elementSize x, y, width or height of the given element.
|
|
3186
3290
|
* @returns {Promise<DOMRect>|Promise<number>} Element bounding rectangle
|
|
3187
3291
|
*
|
|
@@ -3368,8 +3472,7 @@ async function findCheckable(locator, context) {
|
|
|
3368
3472
|
async function proceedIsChecked(assertType, option) {
|
|
3369
3473
|
let els = await findCheckable.call(this, option);
|
|
3370
3474
|
assertElementExists(els, option, 'Checkable');
|
|
3371
|
-
els = await Promise.all(els.map(el => el.
|
|
3372
|
-
els = await Promise.all(els.map(el => el.jsonValue()));
|
|
3475
|
+
els = await Promise.all(els.map(el => el.isChecked()));
|
|
3373
3476
|
const selected = els.reduce((prev, cur) => prev || cur);
|
|
3374
3477
|
return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
|
|
3375
3478
|
}
|
|
@@ -3397,36 +3500,6 @@ async function findFields(locator) {
|
|
|
3397
3500
|
return this._locate({ css: locator });
|
|
3398
3501
|
}
|
|
3399
3502
|
|
|
3400
|
-
async function proceedDragAndDrop(sourceLocator, destinationLocator) {
|
|
3401
|
-
// modern drag and drop in Playwright
|
|
3402
|
-
if (this.page.dragAndDrop) {
|
|
3403
|
-
const source = new Locator(sourceLocator);
|
|
3404
|
-
const dest = new Locator(destinationLocator);
|
|
3405
|
-
if (source.isBasic() && dest.isBasic()) {
|
|
3406
|
-
return this.page.dragAndDrop(source.simplify(), dest.simplify());
|
|
3407
|
-
}
|
|
3408
|
-
}
|
|
3409
|
-
|
|
3410
|
-
const src = await this._locate(sourceLocator);
|
|
3411
|
-
assertElementExists(src, sourceLocator, 'Source Element');
|
|
3412
|
-
|
|
3413
|
-
const dst = await this._locate(destinationLocator);
|
|
3414
|
-
assertElementExists(dst, destinationLocator, 'Destination Element');
|
|
3415
|
-
|
|
3416
|
-
// Note: Using clickablePoint private api becaues the .BoundingBox does not take into account iframe offsets!
|
|
3417
|
-
const dragSource = await clickablePoint(src[0]);
|
|
3418
|
-
const dragDestination = await clickablePoint(dst[0]);
|
|
3419
|
-
|
|
3420
|
-
// Drag start point
|
|
3421
|
-
await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 });
|
|
3422
|
-
await this.page.mouse.down();
|
|
3423
|
-
|
|
3424
|
-
// Drag destination
|
|
3425
|
-
await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 });
|
|
3426
|
-
await this.page.mouse.up();
|
|
3427
|
-
await this._waitForAction();
|
|
3428
|
-
}
|
|
3429
|
-
|
|
3430
3503
|
async function proceedSeeInField(assertType, field, value) {
|
|
3431
3504
|
const els = await findFields.call(this, field);
|
|
3432
3505
|
assertElementExists(els, field, 'Field');
|
|
@@ -3453,14 +3526,15 @@ async function proceedSeeInField(assertType, field, value) {
|
|
|
3453
3526
|
};
|
|
3454
3527
|
|
|
3455
3528
|
if (tag === 'SELECT') {
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3529
|
+
if (await el.getProperty('multiple')) {
|
|
3530
|
+
const selectedOptions = await el.$$('option:checked');
|
|
3531
|
+
if (!selectedOptions.length) return null;
|
|
3532
|
+
|
|
3533
|
+
const options = await filterFieldsByValue(selectedOptions, value, true);
|
|
3534
|
+
return proceedMultiple(options);
|
|
3460
3535
|
}
|
|
3461
3536
|
|
|
3462
|
-
|
|
3463
|
-
return proceedMultiple(options);
|
|
3537
|
+
return el.inputValue();
|
|
3464
3538
|
}
|
|
3465
3539
|
|
|
3466
3540
|
if (tag === 'INPUT') {
|
|
@@ -3476,7 +3550,8 @@ async function proceedSeeInField(assertType, field, value) {
|
|
|
3476
3550
|
}
|
|
3477
3551
|
return proceedMultiple(els[0]);
|
|
3478
3552
|
}
|
|
3479
|
-
|
|
3553
|
+
|
|
3554
|
+
const fieldVal = await el.inputValue();
|
|
3480
3555
|
return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal);
|
|
3481
3556
|
}
|
|
3482
3557
|
|
|
@@ -3507,10 +3582,10 @@ async function filterFieldsBySelectionState(elements, state) {
|
|
|
3507
3582
|
}
|
|
3508
3583
|
|
|
3509
3584
|
async function elementSelected(element) {
|
|
3510
|
-
const type = await element.getProperty('type').then(el => el.jsonValue());
|
|
3585
|
+
const type = await element.getProperty('type').then(el => !!el && el.jsonValue());
|
|
3511
3586
|
|
|
3512
3587
|
if (type === 'checkbox' || type === 'radio') {
|
|
3513
|
-
return element.
|
|
3588
|
+
return element.isChecked();
|
|
3514
3589
|
}
|
|
3515
3590
|
return element.getProperty('selected').then(el => el.jsonValue());
|
|
3516
3591
|
}
|
|
@@ -3558,12 +3633,18 @@ async function targetCreatedHandler(page) {
|
|
|
3558
3633
|
});
|
|
3559
3634
|
});
|
|
3560
3635
|
page.on('console', (msg) => {
|
|
3561
|
-
|
|
3636
|
+
if (!consoleLogStore.includes(msg) && this.options.ignoreLog && !this.options.ignoreLog.includes(msg.type())) {
|
|
3637
|
+
this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg.text && msg.text() || msg._text || '') + msg.args().join(' '));
|
|
3638
|
+
}
|
|
3562
3639
|
consoleLogStore.add(msg);
|
|
3563
3640
|
});
|
|
3564
3641
|
|
|
3565
3642
|
if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && this._getType() === 'Browser') {
|
|
3566
|
-
|
|
3643
|
+
try {
|
|
3644
|
+
await page.setViewportSize(parseWindowSize(this.options.windowSize));
|
|
3645
|
+
} catch (err) {
|
|
3646
|
+
// target can be already closed, ignoring...
|
|
3647
|
+
}
|
|
3567
3648
|
}
|
|
3568
3649
|
}
|
|
3569
3650
|
|
|
@@ -3653,3 +3734,37 @@ async function clickablePoint(el) {
|
|
|
3653
3734
|
} = rect;
|
|
3654
3735
|
return { x: x + width / 2, y: y + height / 2 };
|
|
3655
3736
|
}
|
|
3737
|
+
|
|
3738
|
+
async function refreshContextSession() {
|
|
3739
|
+
// close other sessions
|
|
3740
|
+
try {
|
|
3741
|
+
const contexts = await this.browser.contexts();
|
|
3742
|
+
contexts.shift();
|
|
3743
|
+
|
|
3744
|
+
await Promise.all(contexts.map(c => c.close()));
|
|
3745
|
+
} catch (e) {
|
|
3746
|
+
console.log(e);
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
if (this.page) {
|
|
3750
|
+
const existingPages = await this.browserContext.pages();
|
|
3751
|
+
await this._setPage(existingPages[0]);
|
|
3752
|
+
}
|
|
3753
|
+
|
|
3754
|
+
if (this.options.keepBrowserState) return;
|
|
3755
|
+
|
|
3756
|
+
if (!this.options.keepCookies) {
|
|
3757
|
+
this.debugSection('Session', 'cleaning cookies and localStorage');
|
|
3758
|
+
await this.clearCookie();
|
|
3759
|
+
}
|
|
3760
|
+
const currentUrl = await this.grabCurrentUrl();
|
|
3761
|
+
|
|
3762
|
+
if (currentUrl.startsWith('http')) {
|
|
3763
|
+
await this.executeScript('localStorage.clear();').catch((err) => {
|
|
3764
|
+
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
|
|
3765
|
+
});
|
|
3766
|
+
await this.executeScript('sessionStorage.clear();').catch((err) => {
|
|
3767
|
+
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
|
|
3768
|
+
});
|
|
3769
|
+
}
|
|
3770
|
+
}
|