codeceptjs 3.2.1 → 3.3.0-beta.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 +67 -0
- package/docs/advanced.md +3 -3
- package/docs/api.md +227 -188
- package/docs/basics.md +26 -1
- package/docs/bdd.md +2 -2
- package/docs/build/ApiDataFactory.js +13 -6
- package/docs/build/Appium.js +98 -36
- package/docs/build/FileSystem.js +11 -1
- 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 +282 -151
- 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 +70 -70
- package/docs/changelog.md +17 -0
- package/docs/configuration.md +8 -8
- package/docs/custom-helpers.md +1 -1
- package/docs/data.md +9 -9
- package/docs/helpers/ApiDataFactory.md +7 -0
- package/docs/helpers/Appium.md +240 -198
- package/docs/helpers/FileSystem.md +11 -1
- package/docs/helpers/JSONResponse.md +230 -0
- package/docs/helpers/Playwright.md +283 -216
- package/docs/helpers/Puppeteer.md +9 -1
- package/docs/helpers/REST.md +30 -9
- package/docs/installation.md +3 -1
- package/docs/internal-api.md +265 -0
- package/docs/mobile.md +11 -11
- package/docs/nightmare.md +3 -3
- package/docs/pageobjects.md +2 -0
- package/docs/playwright.md +73 -18
- package/docs/plugins.md +138 -38
- package/docs/puppeteer.md +28 -12
- package/docs/quickstart.md +2 -3
- package/docs/reports.md +44 -3
- package/docs/testcafe.md +1 -1
- package/docs/translation.md +2 -2
- package/docs/videos.md +2 -2
- package/docs/visual.md +2 -2
- package/docs/vue.md +1 -1
- package/docs/webdriver.md +92 -4
- package/lib/actor.js +2 -2
- package/lib/cli.js +25 -20
- package/lib/command/init.js +5 -15
- package/lib/command/workers/runTests.js +25 -7
- package/lib/config.js +17 -13
- package/lib/helper/ApiDataFactory.js +13 -6
- package/lib/helper/Appium.js +65 -3
- package/lib/helper/FileSystem.js +11 -1
- package/lib/helper/GraphQL.js +11 -0
- package/lib/helper/JSONResponse.js +297 -0
- package/lib/helper/Playwright.js +220 -89
- package/lib/helper/Puppeteer.js +12 -3
- package/lib/helper/REST.js +36 -0
- package/lib/helper/WebDriver.js +1 -1
- 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/listener/timeout.js +4 -3
- package/lib/plugin/allure.js +12 -0
- package/lib/plugin/autoLogin.js +1 -1
- package/lib/plugin/eachElement.js +127 -0
- package/lib/plugin/stepTimeout.js +5 -4
- package/lib/plugin/tryTo.js +6 -0
- package/lib/recorder.js +2 -1
- package/lib/step.js +57 -2
- package/lib/utils.js +20 -0
- package/package.json +24 -22
- package/translations/pt-BR.js +8 -0
- package/typings/index.d.ts +4 -0
- package/typings/types.d.ts +345 -110
package/docs/build/Playwright.js
CHANGED
|
@@ -14,12 +14,12 @@ const {
|
|
|
14
14
|
ucfirst,
|
|
15
15
|
fileExists,
|
|
16
16
|
chunkArray,
|
|
17
|
-
toCamelCase,
|
|
18
17
|
convertCssPropertiesToCamelCase,
|
|
19
18
|
screenshotOutputFolder,
|
|
20
19
|
getNormalizedKeyAttributeValue,
|
|
21
20
|
isModifierKey,
|
|
22
21
|
clearString,
|
|
22
|
+
requireWithFallback,
|
|
23
23
|
} = require('../utils');
|
|
24
24
|
const {
|
|
25
25
|
isColorProperty,
|
|
@@ -39,6 +39,9 @@ const popupStore = new Popup();
|
|
|
39
39
|
const consoleLogStore = new Console();
|
|
40
40
|
const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron'];
|
|
41
41
|
|
|
42
|
+
const {
|
|
43
|
+
setRestartStrategy, restartsSession, restartsContext, restartsBrowser,
|
|
44
|
+
} = require('./extras/PlaywrightRestartOpts');
|
|
42
45
|
const { createValueEngine, createDisabledEngine } = require('./extras/PlaywrightPropEngine');
|
|
43
46
|
|
|
44
47
|
/**
|
|
@@ -50,12 +53,18 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
50
53
|
*
|
|
51
54
|
* This helper works with a browser out of the box with no additional tools required to install.
|
|
52
55
|
*
|
|
53
|
-
* Requires `playwright` package version ^1 to be installed:
|
|
56
|
+
* Requires `playwright` or `playwright-core` package version ^1 to be installed:
|
|
54
57
|
*
|
|
55
58
|
* ```
|
|
56
|
-
* npm i playwright@^1 --save
|
|
59
|
+
* npm i playwright@^1.18 --save
|
|
60
|
+
* ```
|
|
61
|
+
* or
|
|
62
|
+
* ```
|
|
63
|
+
* npm i playwright-core@^1.18 --save
|
|
57
64
|
* ```
|
|
58
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
|
+
*
|
|
59
68
|
* ## Configuration
|
|
60
69
|
*
|
|
61
70
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -63,17 +72,21 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
63
72
|
* * `url`: base url of website to be tested
|
|
64
73
|
* * `browser`: a browser to test on, either: `chromium`, `firefox`, `webkit`, `electron`. Default: chromium.
|
|
65
74
|
* * `show`: (optional, default: false) - show browser window.
|
|
66
|
-
* * `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 .
|
|
67
80
|
* * `disableScreenshots`: (optional, default: false) - don't save screenshot on failure.
|
|
68
81
|
* * `emulate`: (optional, default: {}) launch browser in device emulation mode.
|
|
69
82
|
* * `video`: (optional, default: false) enables video recording for failed tests; videos are saved into `output/videos` folder
|
|
70
83
|
* * `trace`: (optional, default: false) record [tracing information](https://playwright.dev/docs/trace-viewer) with screenshots and snapshots.
|
|
71
84
|
* * `fullPageScreenshots` (optional, default: false) - make full page screenshots on failure.
|
|
72
85
|
* * `uniqueScreenshotNames`: (optional, default: false) - option to prevent screenshot override if you have scenarios with the same name in different suites.
|
|
73
|
-
* * `keepBrowserState`: (optional, default: false) - keep browser state between tests when `restart` is set to
|
|
74
|
-
* * `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'.
|
|
75
88
|
* * `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
76
|
-
* * `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/
|
|
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).
|
|
77
90
|
* * `pressKeyDelay`: (optional, default: '10'). Delay between key presses in ms. Used when calling Playwrights page.type(...) in fillField/appendField
|
|
78
91
|
* * `getPageTimeout` (optional, default: '0') config option to set maximum navigation time in milliseconds.
|
|
79
92
|
* * `waitForTimeout`: (optional) default wait* timeout in ms. Default: 1000.
|
|
@@ -84,6 +97,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
84
97
|
* * `manualStart`: (optional, default: false) - do not start browser before a test, start it manually inside a helper with `this.helpers["Playwright"]._startBrowser()`.
|
|
85
98
|
* * `chromium`: (optional) pass additional chromium options
|
|
86
99
|
* * `electron`: (optional) pass additional electron options
|
|
100
|
+
* * `channel`: (optional) While Playwright can operate against the stock Google Chrome and Microsoft Edge browsers available on the machine. In particular, current Playwright version will support Stable and Beta channels of these browsers. See [Google Chrome & Microsoft Edge](https://playwright.dev/docs/browsers/#google-chrome--microsoft-edge).
|
|
87
101
|
*
|
|
88
102
|
* #### Video Recording Customization
|
|
89
103
|
*
|
|
@@ -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,10 +314,16 @@ 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),
|
|
303
321
|
};
|
|
322
|
+
|
|
323
|
+
if (this.options.channel && this.options.browser === 'chromium') {
|
|
324
|
+
this.playwrightOptions.channel = this.options.channel;
|
|
325
|
+
}
|
|
326
|
+
|
|
304
327
|
if (this.options.video) {
|
|
305
328
|
this.options.recordVideo = { size: parseWindowSize(this.options.windowSize) };
|
|
306
329
|
}
|
|
@@ -329,9 +352,9 @@ class Playwright extends Helper {
|
|
|
329
352
|
|
|
330
353
|
static _checkRequirements() {
|
|
331
354
|
try {
|
|
332
|
-
|
|
355
|
+
requireWithFallback('playwright', 'playwright-core');
|
|
333
356
|
} catch (e) {
|
|
334
|
-
return ['playwright@^1'];
|
|
357
|
+
return ['playwright@^1.18'];
|
|
335
358
|
}
|
|
336
359
|
}
|
|
337
360
|
|
|
@@ -348,14 +371,25 @@ class Playwright extends Helper {
|
|
|
348
371
|
}
|
|
349
372
|
|
|
350
373
|
_beforeSuite() {
|
|
351
|
-
if (
|
|
374
|
+
if ((restartsSession() || restartsContext()) && !this.options.manualStart && !this.isRunning) {
|
|
352
375
|
this.debugSection('Session', 'Starting singleton browser session');
|
|
353
376
|
return this._startBrowser();
|
|
354
377
|
}
|
|
355
378
|
}
|
|
356
379
|
|
|
357
380
|
async _before() {
|
|
358
|
-
|
|
381
|
+
recorder.retry({
|
|
382
|
+
retries: 5,
|
|
383
|
+
when: err => {
|
|
384
|
+
if (!err || typeof (err.message) !== 'string') {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
// ignore context errors
|
|
388
|
+
return err.message.includes('context');
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
if (restartsBrowser() && !this.options.manualStart) await this._startBrowser();
|
|
359
393
|
if (!this.isRunning && !this.options.manualStart) await this._startBrowser();
|
|
360
394
|
|
|
361
395
|
this.isAuthenticated = false;
|
|
@@ -377,7 +411,9 @@ class Playwright extends Helper {
|
|
|
377
411
|
if (this.storageState) contextOptions.storageState = this.storageState;
|
|
378
412
|
if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent;
|
|
379
413
|
if (this.options.locale) contextOptions.locale = this.options.locale;
|
|
380
|
-
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
|
+
}
|
|
381
417
|
}
|
|
382
418
|
|
|
383
419
|
let mainPage;
|
|
@@ -405,7 +441,11 @@ class Playwright extends Helper {
|
|
|
405
441
|
return;
|
|
406
442
|
}
|
|
407
443
|
|
|
408
|
-
if (
|
|
444
|
+
if (restartsSession()) {
|
|
445
|
+
return refreshContextSession.bind(this)();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (restartsBrowser()) {
|
|
409
449
|
this.isRunning = false;
|
|
410
450
|
return this._stopBrowser();
|
|
411
451
|
}
|
|
@@ -427,11 +467,10 @@ class Playwright extends Helper {
|
|
|
427
467
|
return this.browser;
|
|
428
468
|
}
|
|
429
469
|
|
|
430
|
-
_afterSuite() {
|
|
431
|
-
}
|
|
470
|
+
_afterSuite() {}
|
|
432
471
|
|
|
433
|
-
_finishTest() {
|
|
434
|
-
if (
|
|
472
|
+
async _finishTest() {
|
|
473
|
+
if ((restartsSession() || restartsContext()) && this.isRunning) return this._stopBrowser();
|
|
435
474
|
}
|
|
436
475
|
|
|
437
476
|
_session() {
|
|
@@ -490,16 +529,16 @@ class Playwright extends Helper {
|
|
|
490
529
|
* First argument is a description of an action.
|
|
491
530
|
* Second argument is async function that gets this helper as parameter.
|
|
492
531
|
*
|
|
493
|
-
* { [`page`](https://github.com/microsoft/playwright/blob/
|
|
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.
|
|
494
533
|
*
|
|
495
534
|
* ```js
|
|
496
|
-
* I.usePlaywrightTo('emulate offline mode', async ({
|
|
497
|
-
* await
|
|
535
|
+
* I.usePlaywrightTo('emulate offline mode', async ({ browserContext }) => {
|
|
536
|
+
* await browserContext.setOffline(true);
|
|
498
537
|
* });
|
|
499
538
|
* ```
|
|
500
539
|
*
|
|
501
540
|
* @param {string} description used to show in logs.
|
|
502
|
-
* @param {function} fn async
|
|
541
|
+
* @param {function} fn async function that executed with Playwright helper as argument
|
|
503
542
|
*/
|
|
504
543
|
usePlaywrightTo(description, fn) {
|
|
505
544
|
return this._useTo(...arguments);
|
|
@@ -574,7 +613,9 @@ class Playwright extends Helper {
|
|
|
574
613
|
this._addPopupListener(page);
|
|
575
614
|
this.page = page;
|
|
576
615
|
if (!page) return;
|
|
616
|
+
this.browserContext.setDefaultTimeout(0);
|
|
577
617
|
page.setDefaultNavigationTimeout(this.options.getPageTimeout);
|
|
618
|
+
page.setDefaultTimeout(this.options.timeout);
|
|
578
619
|
|
|
579
620
|
page.on('crash', async () => {
|
|
580
621
|
console.log('ERROR: Page has crashed, closing page!');
|
|
@@ -675,7 +716,6 @@ class Playwright extends Helper {
|
|
|
675
716
|
this._setPage(null);
|
|
676
717
|
this.context = null;
|
|
677
718
|
popupStore.clear();
|
|
678
|
-
|
|
679
719
|
await this.browser.close();
|
|
680
720
|
}
|
|
681
721
|
|
|
@@ -823,7 +863,7 @@ class Playwright extends Helper {
|
|
|
823
863
|
* I.moveCursorTo('#submit', 5,5);
|
|
824
864
|
* ```
|
|
825
865
|
*
|
|
826
|
-
* @param {
|
|
866
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
827
867
|
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
828
868
|
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
829
869
|
*
|
|
@@ -846,12 +886,24 @@ class Playwright extends Helper {
|
|
|
846
886
|
* I.dragAndDrop('#dragHandle', '#container');
|
|
847
887
|
* ```
|
|
848
888
|
*
|
|
849
|
-
* @param {
|
|
850
|
-
* @param {
|
|
889
|
+
* @param {string | object} srcElement located by CSS|XPath|strict locator.
|
|
890
|
+
* @param {string | object} destElement located by CSS|XPath|strict locator.
|
|
851
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
|
|
852
901
|
*/
|
|
853
|
-
async dragAndDrop(srcElement, destElement) {
|
|
854
|
-
|
|
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);
|
|
855
907
|
}
|
|
856
908
|
|
|
857
909
|
/**
|
|
@@ -908,7 +960,7 @@ class Playwright extends Helper {
|
|
|
908
960
|
* I.scrollTo('#submit', 5, 5);
|
|
909
961
|
* ```
|
|
910
962
|
*
|
|
911
|
-
* @param {
|
|
963
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
912
964
|
* @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
|
|
913
965
|
* @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
|
|
914
966
|
*/
|
|
@@ -1158,7 +1210,7 @@ class Playwright extends Helper {
|
|
|
1158
1210
|
* I.openNewTab();
|
|
1159
1211
|
* ```
|
|
1160
1212
|
*
|
|
1161
|
-
* You can pass in [page options](https://github.com/microsoft/playwright/blob/
|
|
1213
|
+
* You can pass in [page options](https://github.com/microsoft/playwright/blob/main/docs/api.md#browsernewpageoptions) to emulate device on this page
|
|
1162
1214
|
*
|
|
1163
1215
|
* ```js
|
|
1164
1216
|
* // enable mobile
|
|
@@ -1196,7 +1248,7 @@ class Playwright extends Helper {
|
|
|
1196
1248
|
* ```js
|
|
1197
1249
|
* I.seeElement('#modal');
|
|
1198
1250
|
* ```
|
|
1199
|
-
* @param {
|
|
1251
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
1200
1252
|
*
|
|
1201
1253
|
*/
|
|
1202
1254
|
async seeElement(locator) {
|
|
@@ -1212,7 +1264,7 @@ class Playwright extends Helper {
|
|
|
1212
1264
|
* I.dontSeeElement('.modal'); // modal is not shown
|
|
1213
1265
|
* ```
|
|
1214
1266
|
*
|
|
1215
|
-
* @param {
|
|
1267
|
+
* @param {string | object} locator located by CSS|XPath|Strict locator.
|
|
1216
1268
|
*
|
|
1217
1269
|
*/
|
|
1218
1270
|
async dontSeeElement(locator) {
|
|
@@ -1228,7 +1280,7 @@ class Playwright extends Helper {
|
|
|
1228
1280
|
* ```js
|
|
1229
1281
|
* I.seeElementInDOM('#modal');
|
|
1230
1282
|
* ```
|
|
1231
|
-
* @param {
|
|
1283
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
1232
1284
|
*
|
|
1233
1285
|
*/
|
|
1234
1286
|
async seeElementInDOM(locator) {
|
|
@@ -1243,7 +1295,7 @@ class Playwright extends Helper {
|
|
|
1243
1295
|
* I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
|
|
1244
1296
|
* ```
|
|
1245
1297
|
*
|
|
1246
|
-
* @param {
|
|
1298
|
+
* @param {string | object} locator located by CSS|XPath|Strict locator.
|
|
1247
1299
|
*/
|
|
1248
1300
|
async dontSeeElementInDOM(locator) {
|
|
1249
1301
|
const els = await this._locate(locator);
|
|
@@ -1303,14 +1355,25 @@ class Playwright extends Helper {
|
|
|
1303
1355
|
* I.click({css: 'nav a.login'});
|
|
1304
1356
|
* ```
|
|
1305
1357
|
*
|
|
1306
|
-
* @param {
|
|
1307
|
-
* @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.
|
|
1308
1360
|
*
|
|
1309
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
|
+
* ```
|
|
1310
1373
|
*
|
|
1311
1374
|
*/
|
|
1312
|
-
async click(locator, context = null) {
|
|
1313
|
-
return proceedClick.call(this, locator, context);
|
|
1375
|
+
async click(locator, context = null, opts = {}) {
|
|
1376
|
+
return proceedClick.call(this, locator, context, opts);
|
|
1314
1377
|
}
|
|
1315
1378
|
|
|
1316
1379
|
/**
|
|
@@ -1348,8 +1411,8 @@ class Playwright extends Helper {
|
|
|
1348
1411
|
* I.forceClick({css: 'nav a.login'});
|
|
1349
1412
|
* ```
|
|
1350
1413
|
*
|
|
1351
|
-
* @param {
|
|
1352
|
-
* @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.
|
|
1353
1416
|
*
|
|
1354
1417
|
*/
|
|
1355
1418
|
async forceClick(locator, context = null) {
|
|
@@ -1367,8 +1430,8 @@ class Playwright extends Helper {
|
|
|
1367
1430
|
* I.doubleClick('.btn.edit');
|
|
1368
1431
|
* ```
|
|
1369
1432
|
*
|
|
1370
|
-
* @param {
|
|
1371
|
-
* @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.
|
|
1372
1435
|
*
|
|
1373
1436
|
*
|
|
1374
1437
|
*
|
|
@@ -1389,8 +1452,8 @@ class Playwright extends Helper {
|
|
|
1389
1452
|
* I.rightClick('Click me', '.context');
|
|
1390
1453
|
* ```
|
|
1391
1454
|
*
|
|
1392
|
-
* @param {
|
|
1393
|
-
* @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.
|
|
1394
1457
|
*
|
|
1395
1458
|
*
|
|
1396
1459
|
*
|
|
@@ -1410,18 +1473,23 @@ class Playwright extends Helper {
|
|
|
1410
1473
|
* I.checkOption('I Agree to Terms and Conditions');
|
|
1411
1474
|
* I.checkOption('agree', '//form');
|
|
1412
1475
|
* ```
|
|
1413
|
-
* @param {
|
|
1414
|
-
* @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
|
|
1415
1488
|
*/
|
|
1416
|
-
async checkOption(field, context = null) {
|
|
1489
|
+
async checkOption(field, context = null, options = { force: true }) {
|
|
1417
1490
|
const elm = await this._locateCheckable(field, context);
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
// Only check if NOT currently checked
|
|
1421
|
-
if (!curentlyChecked) {
|
|
1422
|
-
await elm.click();
|
|
1423
|
-
return this._waitForAction();
|
|
1424
|
-
}
|
|
1491
|
+
await elm.check(options);
|
|
1492
|
+
return this._waitForAction();
|
|
1425
1493
|
}
|
|
1426
1494
|
|
|
1427
1495
|
/**
|
|
@@ -1435,18 +1503,23 @@ class Playwright extends Helper {
|
|
|
1435
1503
|
* I.uncheckOption('I Agree to Terms and Conditions');
|
|
1436
1504
|
* I.uncheckOption('agree', '//form');
|
|
1437
1505
|
* ```
|
|
1438
|
-
* @param {
|
|
1439
|
-
* @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
|
|
1440
1518
|
*/
|
|
1441
|
-
async uncheckOption(field, context = null) {
|
|
1519
|
+
async uncheckOption(field, context = null, options = { force: true }) {
|
|
1442
1520
|
const elm = await this._locateCheckable(field, context);
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
// Only uncheck if currently checked
|
|
1446
|
-
if (curentlyChecked) {
|
|
1447
|
-
await elm.click();
|
|
1448
|
-
return this._waitForAction();
|
|
1449
|
-
}
|
|
1521
|
+
await elm.uncheck(options);
|
|
1522
|
+
return this._waitForAction();
|
|
1450
1523
|
}
|
|
1451
1524
|
|
|
1452
1525
|
/**
|
|
@@ -1458,7 +1531,7 @@ class Playwright extends Helper {
|
|
|
1458
1531
|
* I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
|
|
1459
1532
|
* ```
|
|
1460
1533
|
*
|
|
1461
|
-
* @param {
|
|
1534
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1462
1535
|
*
|
|
1463
1536
|
*/
|
|
1464
1537
|
async seeCheckboxIsChecked(field) {
|
|
@@ -1474,7 +1547,7 @@ class Playwright extends Helper {
|
|
|
1474
1547
|
* I.dontSeeCheckboxIsChecked('agree'); // located by name
|
|
1475
1548
|
* ```
|
|
1476
1549
|
*
|
|
1477
|
-
* @param {
|
|
1550
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1478
1551
|
*
|
|
1479
1552
|
*/
|
|
1480
1553
|
async dontSeeCheckboxIsChecked(field) {
|
|
@@ -1655,8 +1728,8 @@ class Playwright extends Helper {
|
|
|
1655
1728
|
* // or by strict locator
|
|
1656
1729
|
* I.fillField({css: 'form#login input[name=username]'}, 'John');
|
|
1657
1730
|
* ```
|
|
1658
|
-
* @param {
|
|
1659
|
-
* @param {
|
|
1731
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1732
|
+
* @param {string | object} value text value to fill.
|
|
1660
1733
|
*
|
|
1661
1734
|
*
|
|
1662
1735
|
*/
|
|
@@ -1683,7 +1756,7 @@ class Playwright extends Helper {
|
|
|
1683
1756
|
* I.clearField('user[email]');
|
|
1684
1757
|
* I.clearField('#email');
|
|
1685
1758
|
* ```
|
|
1686
|
-
* @param {
|
|
1759
|
+
* @param {string | object} editable field located by label|name|CSS|XPath|strict locator.
|
|
1687
1760
|
*
|
|
1688
1761
|
*/
|
|
1689
1762
|
async clearField(field) {
|
|
@@ -1697,7 +1770,7 @@ class Playwright extends Helper {
|
|
|
1697
1770
|
* ```js
|
|
1698
1771
|
* I.appendField('#myTextField', 'appended');
|
|
1699
1772
|
* ```
|
|
1700
|
-
* @param {
|
|
1773
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator
|
|
1701
1774
|
* @param {string} value text value to append.
|
|
1702
1775
|
*
|
|
1703
1776
|
*
|
|
@@ -1720,7 +1793,7 @@ class Playwright extends Helper {
|
|
|
1720
1793
|
* I.seeInField('form input[type=hidden]','hidden_value');
|
|
1721
1794
|
* I.seeInField('#searchform input','Search');
|
|
1722
1795
|
* ```
|
|
1723
|
-
* @param {
|
|
1796
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1724
1797
|
* @param {string} value value to check.
|
|
1725
1798
|
*
|
|
1726
1799
|
*/
|
|
@@ -1737,7 +1810,7 @@ class Playwright extends Helper {
|
|
|
1737
1810
|
* I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
|
|
1738
1811
|
* ```
|
|
1739
1812
|
*
|
|
1740
|
-
* @param {
|
|
1813
|
+
* @param {string | object} field located by label|name|CSS|XPath|strict locator.
|
|
1741
1814
|
* @param {string} value value to check.
|
|
1742
1815
|
*/
|
|
1743
1816
|
async dontSeeInField(field, value) {
|
|
@@ -1754,7 +1827,7 @@ class Playwright extends Helper {
|
|
|
1754
1827
|
* I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
|
|
1755
1828
|
* ```
|
|
1756
1829
|
*
|
|
1757
|
-
* @param {
|
|
1830
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
1758
1831
|
* @param {string} pathToFile local file path relative to codecept.json config file.
|
|
1759
1832
|
*
|
|
1760
1833
|
*/
|
|
@@ -1789,7 +1862,7 @@ class Playwright extends Helper {
|
|
|
1789
1862
|
* ```js
|
|
1790
1863
|
* I.selectOption('Which OS do you use?', ['Android', 'iOS']);
|
|
1791
1864
|
* ```
|
|
1792
|
-
* @param {
|
|
1865
|
+
* @param {string | object} select field located by label|name|CSS|XPath|strict locator.
|
|
1793
1866
|
* @param {string|Array<*>} option visible text or value of option.
|
|
1794
1867
|
*
|
|
1795
1868
|
*/
|
|
@@ -1830,7 +1903,7 @@ class Playwright extends Helper {
|
|
|
1830
1903
|
* let numOfElements = await I.grabNumberOfVisibleElements('p');
|
|
1831
1904
|
* ```
|
|
1832
1905
|
*
|
|
1833
|
-
* @param {
|
|
1906
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
1834
1907
|
* @returns {Promise<number>} number of visible elements
|
|
1835
1908
|
*
|
|
1836
1909
|
*/
|
|
@@ -1903,7 +1976,7 @@ class Playwright extends Helper {
|
|
|
1903
1976
|
* I.see('Register', {css: 'form.register'}); // use strict locator
|
|
1904
1977
|
* ```
|
|
1905
1978
|
* @param {string} text expected on page.
|
|
1906
|
-
* @param {?
|
|
1979
|
+
* @param {?string | object} [context=null] (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
|
|
1907
1980
|
*
|
|
1908
1981
|
*
|
|
1909
1982
|
*/
|
|
@@ -1919,7 +1992,7 @@ class Playwright extends Helper {
|
|
|
1919
1992
|
* ```
|
|
1920
1993
|
*
|
|
1921
1994
|
* @param {string} text element value to check.
|
|
1922
|
-
* @param {
|
|
1995
|
+
* @param {(string | object)?} [context=null] element located by CSS|XPath|strict locator.
|
|
1923
1996
|
*/
|
|
1924
1997
|
async seeTextEquals(text, context = null) {
|
|
1925
1998
|
return proceedSee.call(this, 'assert', text, context, true);
|
|
@@ -1935,7 +2008,7 @@ class Playwright extends Helper {
|
|
|
1935
2008
|
* ```
|
|
1936
2009
|
*
|
|
1937
2010
|
* @param {string} text which is not present.
|
|
1938
|
-
* @param {
|
|
2011
|
+
* @param {string | object} [context] (optional) element located by CSS|XPath|strict locator in which to perfrom search.
|
|
1939
2012
|
*
|
|
1940
2013
|
*
|
|
1941
2014
|
*
|
|
@@ -2025,7 +2098,7 @@ class Playwright extends Helper {
|
|
|
2025
2098
|
* I.seeNumberOfElements('#submitBtn', 1);
|
|
2026
2099
|
* ```
|
|
2027
2100
|
*
|
|
2028
|
-
* @param {
|
|
2101
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2029
2102
|
* @param {number} num number of elements.
|
|
2030
2103
|
*
|
|
2031
2104
|
*
|
|
@@ -2044,7 +2117,7 @@ class Playwright extends Helper {
|
|
|
2044
2117
|
* I.seeNumberOfVisibleElements('.buttons', 3);
|
|
2045
2118
|
* ```
|
|
2046
2119
|
*
|
|
2047
|
-
* @param {
|
|
2120
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2048
2121
|
* @param {number} num number of elements.
|
|
2049
2122
|
*
|
|
2050
2123
|
*
|
|
@@ -2146,7 +2219,7 @@ class Playwright extends Helper {
|
|
|
2146
2219
|
*/
|
|
2147
2220
|
async clearCookie() {
|
|
2148
2221
|
// Playwright currently doesn't support to delete a certain cookie
|
|
2149
|
-
// https://github.com/microsoft/playwright/blob/
|
|
2222
|
+
// https://github.com/microsoft/playwright/blob/main/docs/api.md#class-browsercontext
|
|
2150
2223
|
if (!this.browserContext) return;
|
|
2151
2224
|
return this.browserContext.clearCookies();
|
|
2152
2225
|
}
|
|
@@ -2208,7 +2281,7 @@ class Playwright extends Helper {
|
|
|
2208
2281
|
* ```
|
|
2209
2282
|
* If multiple elements found returns first element.
|
|
2210
2283
|
*
|
|
2211
|
-
* @param {
|
|
2284
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2212
2285
|
* @returns {Promise<string>} attribute value
|
|
2213
2286
|
*
|
|
2214
2287
|
*
|
|
@@ -2229,7 +2302,7 @@ class Playwright extends Helper {
|
|
|
2229
2302
|
* let pins = await I.grabTextFromAll('#pin li');
|
|
2230
2303
|
* ```
|
|
2231
2304
|
*
|
|
2232
|
-
* @param {
|
|
2305
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2233
2306
|
* @returns {Promise<string[]>} attribute value
|
|
2234
2307
|
*
|
|
2235
2308
|
*
|
|
@@ -2252,7 +2325,7 @@ class Playwright extends Helper {
|
|
|
2252
2325
|
* ```js
|
|
2253
2326
|
* let email = await I.grabValueFrom('input[name=email]');
|
|
2254
2327
|
* ```
|
|
2255
|
-
* @param {
|
|
2328
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
2256
2329
|
* @returns {Promise<string>} attribute value
|
|
2257
2330
|
*
|
|
2258
2331
|
*/
|
|
@@ -2270,7 +2343,7 @@ class Playwright extends Helper {
|
|
|
2270
2343
|
* ```js
|
|
2271
2344
|
* let inputs = await I.grabValueFromAll('//form/input');
|
|
2272
2345
|
* ```
|
|
2273
|
-
* @param {
|
|
2346
|
+
* @param {string | object} locator field located by label|name|CSS|XPath|strict locator.
|
|
2274
2347
|
* @returns {Promise<string[]>} attribute value
|
|
2275
2348
|
*
|
|
2276
2349
|
*/
|
|
@@ -2289,7 +2362,7 @@ class Playwright extends Helper {
|
|
|
2289
2362
|
* let postHTML = await I.grabHTMLFrom('#post');
|
|
2290
2363
|
* ```
|
|
2291
2364
|
*
|
|
2292
|
-
* @param {
|
|
2365
|
+
* @param {string | object} element located by CSS|XPath|strict locator.
|
|
2293
2366
|
* @returns {Promise<string>} HTML code for an element
|
|
2294
2367
|
*
|
|
2295
2368
|
*/
|
|
@@ -2308,7 +2381,7 @@ class Playwright extends Helper {
|
|
|
2308
2381
|
* let postHTMLs = await I.grabHTMLFromAll('.post');
|
|
2309
2382
|
* ```
|
|
2310
2383
|
*
|
|
2311
|
-
* @param {
|
|
2384
|
+
* @param {string | object} element located by CSS|XPath|strict locator.
|
|
2312
2385
|
* @returns {Promise<string[]>} HTML code for an element
|
|
2313
2386
|
*
|
|
2314
2387
|
*/
|
|
@@ -2327,7 +2400,7 @@ class Playwright extends Helper {
|
|
|
2327
2400
|
* const value = await I.grabCssPropertyFrom('h3', 'font-weight');
|
|
2328
2401
|
* ```
|
|
2329
2402
|
*
|
|
2330
|
-
* @param {
|
|
2403
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2331
2404
|
* @param {string} cssProperty CSS property name.
|
|
2332
2405
|
* @returns {Promise<string>} CSS value
|
|
2333
2406
|
*
|
|
@@ -2348,7 +2421,7 @@ class Playwright extends Helper {
|
|
|
2348
2421
|
* const values = await I.grabCssPropertyFromAll('h3', 'font-weight');
|
|
2349
2422
|
* ```
|
|
2350
2423
|
*
|
|
2351
|
-
* @param {
|
|
2424
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2352
2425
|
* @param {string} cssProperty CSS property name.
|
|
2353
2426
|
* @returns {Promise<string[]>} CSS value
|
|
2354
2427
|
*
|
|
@@ -2369,7 +2442,7 @@ class Playwright extends Helper {
|
|
|
2369
2442
|
* I.seeCssPropertiesOnElements('h3', { 'font-weight': "bold"});
|
|
2370
2443
|
* ```
|
|
2371
2444
|
*
|
|
2372
|
-
* @param {
|
|
2445
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
2373
2446
|
* @param {object} cssProperties object with CSS properties and their values to check.
|
|
2374
2447
|
*
|
|
2375
2448
|
*/
|
|
@@ -2414,7 +2487,7 @@ class Playwright extends Helper {
|
|
|
2414
2487
|
* I.seeAttributesOnElements('//form', { method: "post"});
|
|
2415
2488
|
* ```
|
|
2416
2489
|
*
|
|
2417
|
-
* @param {
|
|
2490
|
+
* @param {string | object} locator located by CSS|XPath|strict locator.
|
|
2418
2491
|
* @param {object} attributes attributes and their values to check.
|
|
2419
2492
|
*
|
|
2420
2493
|
*/
|
|
@@ -2452,7 +2525,7 @@ class Playwright extends Helper {
|
|
|
2452
2525
|
* I.dragSlider('#slider', -70);
|
|
2453
2526
|
* ```
|
|
2454
2527
|
*
|
|
2455
|
-
* @param {
|
|
2528
|
+
* @param {string | object} locator located by label|name|CSS|XPath|strict locator.
|
|
2456
2529
|
* @param {number} offsetX position to drag.
|
|
2457
2530
|
*
|
|
2458
2531
|
*/
|
|
@@ -2482,7 +2555,7 @@ class Playwright extends Helper {
|
|
|
2482
2555
|
* ```js
|
|
2483
2556
|
* let hint = await I.grabAttributeFrom('#tooltip', 'title');
|
|
2484
2557
|
* ```
|
|
2485
|
-
* @param {
|
|
2558
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2486
2559
|
* @param {string} attr attribute name.
|
|
2487
2560
|
* @returns {Promise<string>} attribute value
|
|
2488
2561
|
*
|
|
@@ -2502,7 +2575,7 @@ class Playwright extends Helper {
|
|
|
2502
2575
|
* ```js
|
|
2503
2576
|
* let hints = await I.grabAttributeFromAll('.tooltip', 'title');
|
|
2504
2577
|
* ```
|
|
2505
|
-
* @param {
|
|
2578
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2506
2579
|
* @param {string} attr attribute name.
|
|
2507
2580
|
* @returns {Promise<string[]>} attribute value
|
|
2508
2581
|
*
|
|
@@ -2529,7 +2602,7 @@ class Playwright extends Helper {
|
|
|
2529
2602
|
* I.saveElementScreenshot(`#submit`,'debug.png');
|
|
2530
2603
|
* ```
|
|
2531
2604
|
*
|
|
2532
|
-
* @param {
|
|
2605
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2533
2606
|
* @param {string} fileName file name to save.
|
|
2534
2607
|
*
|
|
2535
2608
|
*
|
|
@@ -2579,6 +2652,53 @@ class Playwright extends Helper {
|
|
|
2579
2652
|
return this.page.screenshot({ path: outputFile, fullPage: fullPageOption, type: 'png' });
|
|
2580
2653
|
}
|
|
2581
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
|
+
|
|
2582
2702
|
async _failed(test) {
|
|
2583
2703
|
await this._withinEnd();
|
|
2584
2704
|
|
|
@@ -2591,7 +2711,7 @@ class Playwright extends Helper {
|
|
|
2591
2711
|
}
|
|
2592
2712
|
|
|
2593
2713
|
if (this.options.trace) {
|
|
2594
|
-
const path = `${global.output_dir}/trace/${clearString(test.title)
|
|
2714
|
+
const path = `${`${global.output_dir}/trace/${clearString(test.title)}`.slice(0, 251)}.zip`;
|
|
2595
2715
|
await this.browserContext.tracing.stop({ path });
|
|
2596
2716
|
test.artifacts.trace = path;
|
|
2597
2717
|
}
|
|
@@ -2636,7 +2756,7 @@ class Playwright extends Helper {
|
|
|
2636
2756
|
* Waits for element to become enabled (by default waits for 1sec).
|
|
2637
2757
|
* Element can be located by CSS or XPath.
|
|
2638
2758
|
*
|
|
2639
|
-
* @param {
|
|
2759
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2640
2760
|
* @param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
|
|
2641
2761
|
*/
|
|
2642
2762
|
async waitForEnabled(locator, sec) {
|
|
@@ -2669,7 +2789,7 @@ class Playwright extends Helper {
|
|
|
2669
2789
|
* I.waitForValue('//input', "GoodValue");
|
|
2670
2790
|
* ```
|
|
2671
2791
|
*
|
|
2672
|
-
* @param {
|
|
2792
|
+
* @param {string | object} field input field.
|
|
2673
2793
|
* @param {string }value expected value.
|
|
2674
2794
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2675
2795
|
*
|
|
@@ -2705,7 +2825,7 @@ class Playwright extends Helper {
|
|
|
2705
2825
|
* I.waitNumberOfVisibleElements('a', 3);
|
|
2706
2826
|
* ```
|
|
2707
2827
|
*
|
|
2708
|
-
* @param {
|
|
2828
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2709
2829
|
* @param {number} num number of elements.
|
|
2710
2830
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2711
2831
|
*
|
|
@@ -2746,7 +2866,7 @@ class Playwright extends Helper {
|
|
|
2746
2866
|
* I.waitForClickable('.btn.continue', 5); // wait for 5 secs
|
|
2747
2867
|
* ```
|
|
2748
2868
|
*
|
|
2749
|
-
* @param {
|
|
2869
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2750
2870
|
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
2751
2871
|
*/
|
|
2752
2872
|
async waitForClickable(locator, waitTimeout) {
|
|
@@ -2763,7 +2883,7 @@ class Playwright extends Helper {
|
|
|
2763
2883
|
* I.waitForElement('.btn.continue', 5); // wait for 5 secs
|
|
2764
2884
|
* ```
|
|
2765
2885
|
*
|
|
2766
|
-
* @param {
|
|
2886
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2767
2887
|
* @param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
2768
2888
|
*
|
|
2769
2889
|
*/
|
|
@@ -2786,7 +2906,7 @@ class Playwright extends Helper {
|
|
|
2786
2906
|
* I.waitForVisible('#popup');
|
|
2787
2907
|
* ```
|
|
2788
2908
|
*
|
|
2789
|
-
* @param {
|
|
2909
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2790
2910
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2791
2911
|
*
|
|
2792
2912
|
*
|
|
@@ -2810,7 +2930,7 @@ class Playwright extends Helper {
|
|
|
2810
2930
|
* I.waitForInvisible('#popup');
|
|
2811
2931
|
* ```
|
|
2812
2932
|
*
|
|
2813
|
-
* @param {
|
|
2933
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2814
2934
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2815
2935
|
*/
|
|
2816
2936
|
async waitForInvisible(locator, sec) {
|
|
@@ -2831,7 +2951,7 @@ class Playwright extends Helper {
|
|
|
2831
2951
|
* I.waitToHide('#popup');
|
|
2832
2952
|
* ```
|
|
2833
2953
|
*
|
|
2834
|
-
* @param {
|
|
2954
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
2835
2955
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2836
2956
|
*/
|
|
2837
2957
|
async waitToHide(locator, sec) {
|
|
@@ -2920,7 +3040,7 @@ class Playwright extends Helper {
|
|
|
2920
3040
|
*
|
|
2921
3041
|
* @param {string }text to wait for.
|
|
2922
3042
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
2923
|
-
* @param {
|
|
3043
|
+
* @param {string | object} [context] (optional) element located by CSS|XPath|strict locator.
|
|
2924
3044
|
*/
|
|
2925
3045
|
async waitForText(text, sec = null, context = null) {
|
|
2926
3046
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
@@ -2990,7 +3110,7 @@ class Playwright extends Helper {
|
|
|
2990
3110
|
* I.switchTo(); // switch back to main page
|
|
2991
3111
|
* ```
|
|
2992
3112
|
*
|
|
2993
|
-
* @param {?
|
|
3113
|
+
* @param {?string | object} [locator=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
2994
3114
|
*/
|
|
2995
3115
|
async switchTo(locator) {
|
|
2996
3116
|
if (Number.isInteger(locator)) {
|
|
@@ -3095,7 +3215,7 @@ class Playwright extends Helper {
|
|
|
3095
3215
|
* I.waitForDetached('#popup');
|
|
3096
3216
|
* ```
|
|
3097
3217
|
*
|
|
3098
|
-
* @param {
|
|
3218
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
3099
3219
|
* @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
3100
3220
|
*/
|
|
3101
3221
|
async waitForDetached(locator, sec) {
|
|
@@ -3165,7 +3285,7 @@ class Playwright extends Helper {
|
|
|
3165
3285
|
* const width = await I.grabElementBoundingRect('h3', 'width');
|
|
3166
3286
|
* // width == 527
|
|
3167
3287
|
* ```
|
|
3168
|
-
* @param {
|
|
3288
|
+
* @param {string | object} locator element located by CSS|XPath|strict locator.
|
|
3169
3289
|
* @param {string=} elementSize x, y, width or height of the given element.
|
|
3170
3290
|
* @returns {Promise<DOMRect>|Promise<number>} Element bounding rectangle
|
|
3171
3291
|
*
|
|
@@ -3352,8 +3472,7 @@ async function findCheckable(locator, context) {
|
|
|
3352
3472
|
async function proceedIsChecked(assertType, option) {
|
|
3353
3473
|
let els = await findCheckable.call(this, option);
|
|
3354
3474
|
assertElementExists(els, option, 'Checkable');
|
|
3355
|
-
els = await Promise.all(els.map(el => el.
|
|
3356
|
-
els = await Promise.all(els.map(el => el.jsonValue()));
|
|
3475
|
+
els = await Promise.all(els.map(el => el.isChecked()));
|
|
3357
3476
|
const selected = els.reduce((prev, cur) => prev || cur);
|
|
3358
3477
|
return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
|
|
3359
3478
|
}
|
|
@@ -3381,36 +3500,6 @@ async function findFields(locator) {
|
|
|
3381
3500
|
return this._locate({ css: locator });
|
|
3382
3501
|
}
|
|
3383
3502
|
|
|
3384
|
-
async function proceedDragAndDrop(sourceLocator, destinationLocator) {
|
|
3385
|
-
// modern drag and drop in Playwright
|
|
3386
|
-
if (this.page.dragAndDrop) {
|
|
3387
|
-
const source = new Locator(sourceLocator);
|
|
3388
|
-
const dest = new Locator(destinationLocator);
|
|
3389
|
-
if (source.isBasic() && dest.isBasic()) {
|
|
3390
|
-
return this.page.dragAndDrop(source.simplify(), dest.simplify());
|
|
3391
|
-
}
|
|
3392
|
-
}
|
|
3393
|
-
|
|
3394
|
-
const src = await this._locate(sourceLocator);
|
|
3395
|
-
assertElementExists(src, sourceLocator, 'Source Element');
|
|
3396
|
-
|
|
3397
|
-
const dst = await this._locate(destinationLocator);
|
|
3398
|
-
assertElementExists(dst, destinationLocator, 'Destination Element');
|
|
3399
|
-
|
|
3400
|
-
// Note: Using clickablePoint private api becaues the .BoundingBox does not take into account iframe offsets!
|
|
3401
|
-
const dragSource = await clickablePoint(src[0]);
|
|
3402
|
-
const dragDestination = await clickablePoint(dst[0]);
|
|
3403
|
-
|
|
3404
|
-
// Drag start point
|
|
3405
|
-
await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 });
|
|
3406
|
-
await this.page.mouse.down();
|
|
3407
|
-
|
|
3408
|
-
// Drag destination
|
|
3409
|
-
await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 });
|
|
3410
|
-
await this.page.mouse.up();
|
|
3411
|
-
await this._waitForAction();
|
|
3412
|
-
}
|
|
3413
|
-
|
|
3414
3503
|
async function proceedSeeInField(assertType, field, value) {
|
|
3415
3504
|
const els = await findFields.call(this, field);
|
|
3416
3505
|
assertElementExists(els, field, 'Field');
|
|
@@ -3437,14 +3526,15 @@ async function proceedSeeInField(assertType, field, value) {
|
|
|
3437
3526
|
};
|
|
3438
3527
|
|
|
3439
3528
|
if (tag === 'SELECT') {
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
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);
|
|
3444
3535
|
}
|
|
3445
3536
|
|
|
3446
|
-
|
|
3447
|
-
return proceedMultiple(options);
|
|
3537
|
+
return el.inputValue();
|
|
3448
3538
|
}
|
|
3449
3539
|
|
|
3450
3540
|
if (tag === 'INPUT') {
|
|
@@ -3460,7 +3550,8 @@ async function proceedSeeInField(assertType, field, value) {
|
|
|
3460
3550
|
}
|
|
3461
3551
|
return proceedMultiple(els[0]);
|
|
3462
3552
|
}
|
|
3463
|
-
|
|
3553
|
+
|
|
3554
|
+
const fieldVal = await el.inputValue();
|
|
3464
3555
|
return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal);
|
|
3465
3556
|
}
|
|
3466
3557
|
|
|
@@ -3491,10 +3582,10 @@ async function filterFieldsBySelectionState(elements, state) {
|
|
|
3491
3582
|
}
|
|
3492
3583
|
|
|
3493
3584
|
async function elementSelected(element) {
|
|
3494
|
-
const type = await element.getProperty('type').then(el => el.jsonValue());
|
|
3585
|
+
const type = await element.getProperty('type').then(el => !!el && el.jsonValue());
|
|
3495
3586
|
|
|
3496
3587
|
if (type === 'checkbox' || type === 'radio') {
|
|
3497
|
-
return element.
|
|
3588
|
+
return element.isChecked();
|
|
3498
3589
|
}
|
|
3499
3590
|
return element.getProperty('selected').then(el => el.jsonValue());
|
|
3500
3591
|
}
|
|
@@ -3542,12 +3633,18 @@ async function targetCreatedHandler(page) {
|
|
|
3542
3633
|
});
|
|
3543
3634
|
});
|
|
3544
3635
|
page.on('console', (msg) => {
|
|
3545
|
-
|
|
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
|
+
}
|
|
3546
3639
|
consoleLogStore.add(msg);
|
|
3547
3640
|
});
|
|
3548
3641
|
|
|
3549
3642
|
if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && this._getType() === 'Browser') {
|
|
3550
|
-
|
|
3643
|
+
try {
|
|
3644
|
+
await page.setViewportSize(parseWindowSize(this.options.windowSize));
|
|
3645
|
+
} catch (err) {
|
|
3646
|
+
// target can be already closed, ignoring...
|
|
3647
|
+
}
|
|
3551
3648
|
}
|
|
3552
3649
|
}
|
|
3553
3650
|
|
|
@@ -3637,3 +3734,37 @@ async function clickablePoint(el) {
|
|
|
3637
3734
|
} = rect;
|
|
3638
3735
|
return { x: x + width / 2, y: y + height / 2 };
|
|
3639
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
|
+
}
|