codeceptjs 3.5.4 → 3.5.5
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 +2887 -0
- package/docs/build/Appium.js +40 -1
- package/docs/build/Nightmare.js +4 -0
- package/docs/build/Playwright.js +15 -8
- package/docs/build/Protractor.js +4 -0
- package/docs/build/Puppeteer.js +17 -6
- package/docs/build/TestCafe.js +2 -0
- package/docs/build/WebDriver.js +4 -0
- package/docs/changelog.md +155 -0
- package/docs/helpers/Appium.md +37 -0
- package/docs/helpers/Nightmare.md +26 -24
- package/docs/helpers/Protractor.md +4 -2
- package/docs/helpers/Puppeteer.md +28 -26
- package/docs/helpers/TestCafe.md +16 -15
- package/docs/helpers/WebDriver.md +31 -29
- package/docs/webapi/executeAsyncScript.mustache +2 -0
- package/docs/webapi/executeScript.mustache +2 -0
- package/lib/codecept.js +1 -0
- package/lib/command/init.js +40 -4
- package/lib/command/run-workers.js +4 -0
- package/lib/command/run.js +6 -0
- package/lib/helper/Appium.js +40 -1
- package/lib/helper/Playwright.js +15 -8
- package/lib/helper/Puppeteer.js +13 -6
- package/lib/pause.js +1 -0
- package/package.json +85 -85
- package/typings/promiseBasedTypes.d.ts +18 -0
- package/typings/types.d.ts +31 -11
package/docs/build/Appium.js
CHANGED
|
@@ -117,6 +117,43 @@ const vendorPrefix = {
|
|
|
117
117
|
* }
|
|
118
118
|
* ```
|
|
119
119
|
*
|
|
120
|
+
* Example Android App using Appiumv2 on BrowserStack:
|
|
121
|
+
*
|
|
122
|
+
* ```js
|
|
123
|
+
* {
|
|
124
|
+
* helpers: {
|
|
125
|
+
* Appium: {
|
|
126
|
+
* appiumV2: true,
|
|
127
|
+
* host: "hub-cloud.browserstack.com",
|
|
128
|
+
* port: 4444,
|
|
129
|
+
* user: process.env.BROWSERSTACK_USER,
|
|
130
|
+
* key: process.env.BROWSERSTACK_KEY,
|
|
131
|
+
* app: `bs://c700ce60cf1gjhgjh3ae8ed9770ghjg5a55b8e022f13c5827cg`,
|
|
132
|
+
* browser: '',
|
|
133
|
+
* desiredCapabilities: {
|
|
134
|
+
* 'appPackage': data.packageName,
|
|
135
|
+
* 'deviceName': process.env.DEVICE || 'Google Pixel 3',
|
|
136
|
+
* 'platformName': process.env.PLATFORM || 'android',
|
|
137
|
+
* 'platformVersion': process.env.OS_VERSION || '10.0',
|
|
138
|
+
* 'automationName': process.env.ENGINE || 'UIAutomator2',
|
|
139
|
+
* 'newCommandTimeout': 300000,
|
|
140
|
+
* 'androidDeviceReadyTimeout': 300000,
|
|
141
|
+
* 'androidInstallTimeout': 90000,
|
|
142
|
+
* 'appWaitDuration': 300000,
|
|
143
|
+
* 'autoGrantPermissions': true,
|
|
144
|
+
* 'gpsEnabled': true,
|
|
145
|
+
* 'isHeadless': false,
|
|
146
|
+
* 'noReset': false,
|
|
147
|
+
* 'noSign': true,
|
|
148
|
+
* 'bstack:options' : {
|
|
149
|
+
* "appiumVersion" : "2.0.1",
|
|
150
|
+
* },
|
|
151
|
+
* }
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* }
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
120
157
|
* Additional configuration params can be used from <https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md>
|
|
121
158
|
*
|
|
122
159
|
* ## Access From Helpers
|
|
@@ -234,7 +271,9 @@ class Appium extends Webdriver {
|
|
|
234
271
|
const _convertedCaps = {};
|
|
235
272
|
for (const [key, value] of Object.entries(capabilities)) {
|
|
236
273
|
if (!key.startsWith(vendorPrefix.appium)) {
|
|
237
|
-
|
|
274
|
+
if (key !== 'platformName') {
|
|
275
|
+
_convertedCaps[`${vendorPrefix.appium}:${key}`] = value;
|
|
276
|
+
}
|
|
238
277
|
} else {
|
|
239
278
|
_convertedCaps[`${key}`] = value;
|
|
240
279
|
}
|
package/docs/build/Nightmare.js
CHANGED
|
@@ -882,6 +882,8 @@ class Nightmare extends Helper {
|
|
|
882
882
|
*
|
|
883
883
|
* @param {string|function} fn function to be executed in browser context.
|
|
884
884
|
* @param {...any} args to be passed to function.
|
|
885
|
+
* @returns {Promise<any>} script return value
|
|
886
|
+
*
|
|
885
887
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
886
888
|
*
|
|
887
889
|
*
|
|
@@ -916,6 +918,8 @@ class Nightmare extends Helper {
|
|
|
916
918
|
*
|
|
917
919
|
* @param {string|function} fn function to be executed in browser context.
|
|
918
920
|
* @param {...any} args to be passed to function.
|
|
921
|
+
* @returns {Promise<any>} script return value
|
|
922
|
+
*
|
|
919
923
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
920
924
|
*
|
|
921
925
|
*
|
package/docs/build/Playwright.js
CHANGED
|
@@ -482,6 +482,7 @@ class Playwright extends Helper {
|
|
|
482
482
|
contextOptions.httpCredentials = this.options.basicAuth;
|
|
483
483
|
this.isAuthenticated = true;
|
|
484
484
|
}
|
|
485
|
+
if (this.options.bypassCSP) contextOptions.bypassCSP = this.options.bypassCSP;
|
|
485
486
|
if (this.options.recordVideo) contextOptions.recordVideo = this.options.recordVideo;
|
|
486
487
|
if (this.storageState) contextOptions.storageState = this.storageState;
|
|
487
488
|
if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent;
|
|
@@ -857,8 +858,8 @@ class Playwright extends Helper {
|
|
|
857
858
|
await this.switchTo(null);
|
|
858
859
|
return frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve());
|
|
859
860
|
}
|
|
860
|
-
await this.switchTo(
|
|
861
|
-
this.withinLocator = new Locator(
|
|
861
|
+
await this.switchTo(frame);
|
|
862
|
+
this.withinLocator = new Locator(frame);
|
|
862
863
|
return;
|
|
863
864
|
}
|
|
864
865
|
|
|
@@ -3497,14 +3498,17 @@ class Playwright extends Helper {
|
|
|
3497
3498
|
|
|
3498
3499
|
// iframe by selector
|
|
3499
3500
|
const els = await this._locate(locator);
|
|
3500
|
-
|
|
3501
|
+
if (!els[0]) {
|
|
3502
|
+
throw new Error(`Element ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
|
|
3503
|
+
}
|
|
3501
3504
|
|
|
3502
3505
|
// get content of the first iframe
|
|
3503
|
-
|
|
3506
|
+
locator = new Locator(locator, 'css');
|
|
3507
|
+
if ((locator.frame && locator.frame === 'iframe') || locator.value.toLowerCase() === 'iframe') {
|
|
3504
3508
|
contentFrame = await this.page.frames()[1];
|
|
3505
3509
|
// get content of the iframe using its name
|
|
3506
|
-
} else if (locator.toLowerCase().includes('name=')) {
|
|
3507
|
-
const frameName = locator.split('=')[1].replace(/"/g, '').replaceAll(/]/g, '');
|
|
3510
|
+
} else if (locator.value.toLowerCase().includes('name=')) {
|
|
3511
|
+
const frameName = locator.value.split('=')[1].replace(/"/g, '').replaceAll(/]/g, '');
|
|
3508
3512
|
contentFrame = await this.page.frame(frameName);
|
|
3509
3513
|
}
|
|
3510
3514
|
|
|
@@ -3512,7 +3516,7 @@ class Playwright extends Helper {
|
|
|
3512
3516
|
this.context = contentFrame;
|
|
3513
3517
|
this.contextLocator = null;
|
|
3514
3518
|
} else {
|
|
3515
|
-
this.context =
|
|
3519
|
+
this.context = this.page.frame(this.page.frames()[1].name());
|
|
3516
3520
|
this.contextLocator = locator;
|
|
3517
3521
|
}
|
|
3518
3522
|
}
|
|
@@ -4526,7 +4530,10 @@ async function elementSelected(element) {
|
|
|
4526
4530
|
|
|
4527
4531
|
function isFrameLocator(locator) {
|
|
4528
4532
|
locator = new Locator(locator);
|
|
4529
|
-
if (locator.isFrame())
|
|
4533
|
+
if (locator.isFrame()) {
|
|
4534
|
+
const _locator = new Locator(locator.value);
|
|
4535
|
+
return _locator.value;
|
|
4536
|
+
}
|
|
4530
4537
|
return false;
|
|
4531
4538
|
}
|
|
4532
4539
|
|
package/docs/build/Protractor.js
CHANGED
|
@@ -1525,6 +1525,8 @@ class Protractor extends Helper {
|
|
|
1525
1525
|
*
|
|
1526
1526
|
* @param {string|function} fn function to be executed in browser context.
|
|
1527
1527
|
* @param {...any} args to be passed to function.
|
|
1528
|
+
* @returns {Promise<any>} script return value
|
|
1529
|
+
*
|
|
1528
1530
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1529
1531
|
*
|
|
1530
1532
|
*/
|
|
@@ -1556,6 +1558,8 @@ class Protractor extends Helper {
|
|
|
1556
1558
|
*
|
|
1557
1559
|
* @param {string|function} fn function to be executed in browser context.
|
|
1558
1560
|
* @param {...any} args to be passed to function.
|
|
1561
|
+
* @returns {Promise<any>} script return value
|
|
1562
|
+
*
|
|
1559
1563
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1560
1564
|
*
|
|
1561
1565
|
*/
|
package/docs/build/Puppeteer.js
CHANGED
|
@@ -612,8 +612,8 @@ class Puppeteer extends Helper {
|
|
|
612
612
|
return this.switchTo(null)
|
|
613
613
|
.then(() => frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve()));
|
|
614
614
|
}
|
|
615
|
-
await this.switchTo(
|
|
616
|
-
this.withinLocator = new Locator(
|
|
615
|
+
await this.switchTo(frame);
|
|
616
|
+
this.withinLocator = new Locator(frame);
|
|
617
617
|
return;
|
|
618
618
|
}
|
|
619
619
|
|
|
@@ -2314,6 +2314,8 @@ class Puppeteer extends Helper {
|
|
|
2314
2314
|
*
|
|
2315
2315
|
* @param {string|function} fn function to be executed in browser context.
|
|
2316
2316
|
* @param {...any} args to be passed to function.
|
|
2317
|
+
* @returns {Promise<any>} script return value
|
|
2318
|
+
*
|
|
2317
2319
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2318
2320
|
*
|
|
2319
2321
|
*
|
|
@@ -2351,6 +2353,8 @@ class Puppeteer extends Helper {
|
|
|
2351
2353
|
*
|
|
2352
2354
|
* @param {string|function} fn function to be executed in browser context.
|
|
2353
2355
|
* @param {...any} args to be passed to function.
|
|
2356
|
+
* @returns {Promise<any>} script return value
|
|
2357
|
+
*
|
|
2354
2358
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2355
2359
|
*
|
|
2356
2360
|
*
|
|
@@ -2942,7 +2946,7 @@ class Puppeteer extends Helper {
|
|
|
2942
2946
|
assertElementExists(els, locator);
|
|
2943
2947
|
|
|
2944
2948
|
return this.waitForFunction(isElementClickable, [els[0]], waitTimeout).catch(async (e) => {
|
|
2945
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
2949
|
+
if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
2946
2950
|
throw new Error(`element ${new Locator(locator).toString()} still not clickable after ${waitTimeout || this.options.waitForTimeout / 1000} sec`);
|
|
2947
2951
|
} else {
|
|
2948
2952
|
throw e;
|
|
@@ -3096,7 +3100,7 @@ class Puppeteer extends Helper {
|
|
|
3096
3100
|
return currUrl.indexOf(urlPart) > -1;
|
|
3097
3101
|
}, { timeout: waitTimeout }, urlPart).catch(async (e) => {
|
|
3098
3102
|
const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
|
|
3099
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
3103
|
+
if (/Waiting failed:/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
3100
3104
|
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
|
|
3101
3105
|
} else {
|
|
3102
3106
|
throw e;
|
|
@@ -3130,7 +3134,7 @@ class Puppeteer extends Helper {
|
|
|
3130
3134
|
return currUrl.indexOf(urlPart) > -1;
|
|
3131
3135
|
}, { timeout: waitTimeout }, urlPart).catch(async (e) => {
|
|
3132
3136
|
const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
|
|
3133
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
3137
|
+
if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
3134
3138
|
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
|
|
3135
3139
|
} else {
|
|
3136
3140
|
throw e;
|
|
@@ -3427,6 +3431,10 @@ async function findElements(matcher, locator) {
|
|
|
3427
3431
|
if (locator.react) return findReact(matcher.executionContext(), locator);
|
|
3428
3432
|
locator = new Locator(locator, 'css');
|
|
3429
3433
|
if (!locator.isXPath()) return matcher.$$(locator.simplify());
|
|
3434
|
+
// puppeteer version < 19.4.0 is no longer supported. This one is backward support.
|
|
3435
|
+
if (puppeteer.default?.defaultBrowserRevision) {
|
|
3436
|
+
return matcher.$$(`xpath/${locator.value}`);
|
|
3437
|
+
}
|
|
3430
3438
|
return matcher.$x(locator.value);
|
|
3431
3439
|
}
|
|
3432
3440
|
|
|
@@ -3681,7 +3689,10 @@ async function elementSelected(element) {
|
|
|
3681
3689
|
|
|
3682
3690
|
function isFrameLocator(locator) {
|
|
3683
3691
|
locator = new Locator(locator);
|
|
3684
|
-
if (locator.isFrame())
|
|
3692
|
+
if (locator.isFrame()) {
|
|
3693
|
+
const _locator = new Locator(locator);
|
|
3694
|
+
return _locator.value;
|
|
3695
|
+
}
|
|
3685
3696
|
return false;
|
|
3686
3697
|
}
|
|
3687
3698
|
|
package/docs/build/TestCafe.js
CHANGED
|
@@ -1270,6 +1270,8 @@ class TestCafe extends Helper {
|
|
|
1270
1270
|
*
|
|
1271
1271
|
* @param {string|function} fn function to be executed in browser context.
|
|
1272
1272
|
* @param {...any} args to be passed to function.
|
|
1273
|
+
* @returns {Promise<any>} script return value
|
|
1274
|
+
*
|
|
1273
1275
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1274
1276
|
*
|
|
1275
1277
|
*
|
package/docs/build/WebDriver.js
CHANGED
|
@@ -2173,6 +2173,8 @@ class WebDriver extends Helper {
|
|
|
2173
2173
|
*
|
|
2174
2174
|
* @param {string|function} fn function to be executed in browser context.
|
|
2175
2175
|
* @param {...any} args to be passed to function.
|
|
2176
|
+
* @returns {Promise<any>} script return value
|
|
2177
|
+
*
|
|
2176
2178
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2177
2179
|
*
|
|
2178
2180
|
*
|
|
@@ -2207,6 +2209,8 @@ class WebDriver extends Helper {
|
|
|
2207
2209
|
*
|
|
2208
2210
|
* @param {string|function} fn function to be executed in browser context.
|
|
2209
2211
|
* @param {...any} args to be passed to function.
|
|
2212
|
+
* @returns {Promise<any>} script return value
|
|
2213
|
+
*
|
|
2210
2214
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2211
2215
|
*
|
|
2212
2216
|
*
|
package/docs/changelog.md
CHANGED
|
@@ -7,6 +7,161 @@ layout: Section
|
|
|
7
7
|
|
|
8
8
|
# Releases
|
|
9
9
|
|
|
10
|
+
## 3.5.5
|
|
11
|
+
|
|
12
|
+
🐛 Bug Fixes
|
|
13
|
+
* fix(browserstack): issue with vendor prefix ([#3845](https://github.com/codeceptjs/CodeceptJS/issues/3845)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
14
|
+
```
|
|
15
|
+
export const caps = {
|
|
16
|
+
androidCaps: {
|
|
17
|
+
appiumV2: true,
|
|
18
|
+
host: "hub-cloud.browserstack.com",
|
|
19
|
+
port: 4444,
|
|
20
|
+
user: process.env.BROWSERSTACK_USER,
|
|
21
|
+
key: process.env.BROWSERSTACK_KEY,
|
|
22
|
+
'app': `bs://c700ce60cf13ae8ed97705a55b8e022f1hjhkjh3c5827c`,
|
|
23
|
+
browser: '',
|
|
24
|
+
desiredCapabilities: {
|
|
25
|
+
'appPackage': data.packageName,
|
|
26
|
+
'deviceName': process.env.DEVICE || 'Google Pixel 3',
|
|
27
|
+
'platformName': process.env.PLATFORM || 'android',
|
|
28
|
+
'platformVersion': process.env.OS_VERSION || '10.0',
|
|
29
|
+
'automationName': process.env.ENGINE || 'UIAutomator2',
|
|
30
|
+
'newCommandTimeout': 300000,
|
|
31
|
+
'androidDeviceReadyTimeout': 300000,
|
|
32
|
+
'androidInstallTimeout': 90000,
|
|
33
|
+
'appWaitDuration': 300000,
|
|
34
|
+
'autoGrantPermissions': true,
|
|
35
|
+
'gpsEnabled': true,
|
|
36
|
+
'isHeadless': false,
|
|
37
|
+
'noReset': false,
|
|
38
|
+
'noSign': true,
|
|
39
|
+
'bstack:options' : {
|
|
40
|
+
"appiumVersion" : "2.0.1",
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
* switchTo/within now supports strict locator ([#3847](https://github.com/codeceptjs/CodeceptJS/issues/3847)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
I.switchTo({ css: 'iframe[id^=number-frame]' }) // support the strict locator
|
|
51
|
+
|
|
52
|
+
I.amOnPage('/iframe');
|
|
53
|
+
within({
|
|
54
|
+
frame: { css: '#number-frame-1234' }, // support the strict locator
|
|
55
|
+
}, () => {
|
|
56
|
+
I.fillField('user[login]', 'User');
|
|
57
|
+
I.fillField('user[email]', 'user@user.com');
|
|
58
|
+
I.fillField('user[password]', 'user@user.com');
|
|
59
|
+
I.click('button');
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
* Improve the IntelliSense when using other languages ([#3848](https://github.com/codeceptjs/CodeceptJS/issues/3848)) - by **[andonary](https://github.com/andonary)**
|
|
64
|
+
```
|
|
65
|
+
include: {
|
|
66
|
+
Je: './steps_file.js'
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
* bypassCSP support for Playwright helper ([#3865](https://github.com/codeceptjs/CodeceptJS/issues/3865)) - by **[sammeel](https://github.com/sammeel)**
|
|
71
|
+
```
|
|
72
|
+
helpers: {
|
|
73
|
+
Playwright: {
|
|
74
|
+
bypassCSP: true
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
* fix: missing requests when recording network ([#3834](https://github.com/codeceptjs/CodeceptJS/issues/3834)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
78
|
+
|
|
79
|
+
🛩️ Features and Improvements
|
|
80
|
+
* Show environment info in verbose mode ([#3858](https://github.com/codeceptjs/CodeceptJS/issues/3858)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Environment information:-
|
|
84
|
+
|
|
85
|
+
codeceptVersion: "3.5.4"
|
|
86
|
+
nodeInfo: 18.16.0
|
|
87
|
+
osInfo: macOS 13.5
|
|
88
|
+
cpuInfo: (8) arm64 Apple M1 Pro
|
|
89
|
+
chromeInfo: 116.0.5845.179
|
|
90
|
+
edgeInfo: 116.0.1938.69
|
|
91
|
+
firefoxInfo: Not Found
|
|
92
|
+
safariInfo: 16.6
|
|
93
|
+
helpers: {
|
|
94
|
+
"Playwright": {
|
|
95
|
+
"url": "https://github.com",
|
|
96
|
+
"show": false,
|
|
97
|
+
"browser": "chromium",
|
|
98
|
+
"waitForNavigation": "load",
|
|
99
|
+
"waitForTimeout": 30000,
|
|
100
|
+
"trace": false,
|
|
101
|
+
"keepTraceForPassedTests": true
|
|
102
|
+
},
|
|
103
|
+
"CDPHelper": {
|
|
104
|
+
"require": "./helpers/CDPHelper.ts"
|
|
105
|
+
},
|
|
106
|
+
"OpenAI": {
|
|
107
|
+
"chunkSize": 8000
|
|
108
|
+
},
|
|
109
|
+
"ExpectHelper": {
|
|
110
|
+
"require": "codeceptjs-expect"
|
|
111
|
+
},
|
|
112
|
+
"REST": {
|
|
113
|
+
"endpoint": "https://reqres.in",
|
|
114
|
+
"timeout": 20000
|
|
115
|
+
},
|
|
116
|
+
"AllureHelper": {
|
|
117
|
+
"require": "./helpers/AllureHelper.ts"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
plugins: {
|
|
121
|
+
"screenshotOnFail": {
|
|
122
|
+
"enabled": true
|
|
123
|
+
},
|
|
124
|
+
"tryTo": {
|
|
125
|
+
"enabled": true
|
|
126
|
+
},
|
|
127
|
+
"retryFailedStep": {
|
|
128
|
+
"enabled": true
|
|
129
|
+
},
|
|
130
|
+
"retryTo": {
|
|
131
|
+
"enabled": true
|
|
132
|
+
},
|
|
133
|
+
"eachElement": {
|
|
134
|
+
"enabled": true
|
|
135
|
+
},
|
|
136
|
+
"pauseOnFail": {}
|
|
137
|
+
}
|
|
138
|
+
***************************************
|
|
139
|
+
If you have questions ask them in our Slack: http://bit.ly/chat-codeceptjs
|
|
140
|
+
Or ask them on our discussion board: https://codecept.discourse.group/
|
|
141
|
+
Please copy environment info when you report issues on GitHub: https://github.com/Codeception/CodeceptJS/issues
|
|
142
|
+
***************************************
|
|
143
|
+
CodeceptJS v3.5.4 #StandWithUkraine
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
* some typings improvements ([#3855](https://github.com/codeceptjs/CodeceptJS/issues/3855)) - by **[nikzupancic](https://github.com/nikzupancic)**
|
|
147
|
+
* support the puppeteer 21.1.1 ([#3856](https://github.com/codeceptjs/CodeceptJS/issues/3856)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
148
|
+
* fix: support secret value for some methods ([#3837](https://github.com/codeceptjs/CodeceptJS/issues/3837)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
await I.amOnPage('/form/field_values');
|
|
152
|
+
await I.dontSeeInField('checkbox[]', secret('not seen one'));
|
|
153
|
+
await I.seeInField('checkbox[]', secret('see test one'));
|
|
154
|
+
await I.dontSeeInField('checkbox[]', secret('not seen two'));
|
|
155
|
+
await I.seeInField('checkbox[]', secret('see test two'));
|
|
156
|
+
await I.dontSeeInField('checkbox[]', secret('not seen three'));
|
|
157
|
+
await I.seeInField('checkbox[]', secret('see test three'));
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
🛩️ **Several bugfixes and improvements for Codecept-UI**
|
|
161
|
+
* Mask the secret value in UI
|
|
162
|
+
* Improve UX/UI
|
|
163
|
+
* PageObjects are now showing in UI
|
|
164
|
+
|
|
10
165
|
## 3.5.4
|
|
11
166
|
|
|
12
167
|
🐛 Bug Fixes:
|
package/docs/helpers/Appium.md
CHANGED
|
@@ -99,6 +99,43 @@ helpers: {
|
|
|
99
99
|
}
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
+
Example Android App using Appiumv2 on BrowserStack:
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
{
|
|
106
|
+
helpers: {
|
|
107
|
+
Appium: {
|
|
108
|
+
appiumV2: true,
|
|
109
|
+
host: "hub-cloud.browserstack.com",
|
|
110
|
+
port: 4444,
|
|
111
|
+
user: process.env.BROWSERSTACK_USER,
|
|
112
|
+
key: process.env.BROWSERSTACK_KEY,
|
|
113
|
+
app: `bs://c700ce60cf1gjhgjh3ae8ed9770ghjg5a55b8e022f13c5827cg`,
|
|
114
|
+
browser: '',
|
|
115
|
+
desiredCapabilities: {
|
|
116
|
+
'appPackage': data.packageName,
|
|
117
|
+
'deviceName': process.env.DEVICE || 'Google Pixel 3',
|
|
118
|
+
'platformName': process.env.PLATFORM || 'android',
|
|
119
|
+
'platformVersion': process.env.OS_VERSION || '10.0',
|
|
120
|
+
'automationName': process.env.ENGINE || 'UIAutomator2',
|
|
121
|
+
'newCommandTimeout': 300000,
|
|
122
|
+
'androidDeviceReadyTimeout': 300000,
|
|
123
|
+
'androidInstallTimeout': 90000,
|
|
124
|
+
'appWaitDuration': 300000,
|
|
125
|
+
'autoGrantPermissions': true,
|
|
126
|
+
'gpsEnabled': true,
|
|
127
|
+
'isHeadless': false,
|
|
128
|
+
'noReset': false,
|
|
129
|
+
'noSign': true,
|
|
130
|
+
'bstack:options' : {
|
|
131
|
+
"appiumVersion" : "2.0.1",
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
102
139
|
Additional configuration params can be used from [https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md][4]
|
|
103
140
|
|
|
104
141
|
## Access From Helpers
|
|
@@ -379,9 +379,10 @@ let val = await I.executeAsyncScript(function(url, done) {
|
|
|
379
379
|
#### Parameters
|
|
380
380
|
|
|
381
381
|
- `args` **...any** to be passed to function.
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
- `fn` **([string][3] | [function][7])** function to be executed in browser context.
|
|
383
|
+
|
|
384
|
+
Returns **[Promise][8]<any>** script return value⚠️ returns a _promise_ which is synchronized internally by recorderWrapper for asynchronous [evaluate][9].
|
|
385
|
+
Unlike NightmareJS implementation calling `done` will return its first argument.
|
|
385
386
|
|
|
386
387
|
### executeScript
|
|
387
388
|
|
|
@@ -412,8 +413,9 @@ let date = await I.executeScript(function(el) {
|
|
|
412
413
|
#### Parameters
|
|
413
414
|
|
|
414
415
|
- `args` **...any** to be passed to function.
|
|
415
|
-
|
|
416
|
-
|
|
416
|
+
- `fn` **([string][3] | [function][7])** function to be executed in browser context.
|
|
417
|
+
|
|
418
|
+
Returns **[Promise][8]<any>** script return value⚠️ returns a _promise_ which is synchronized internally by recorderWrapper for synchronous [evaluate][9]
|
|
417
419
|
|
|
418
420
|
### fillField
|
|
419
421
|
|
|
@@ -452,7 +454,7 @@ let hint = await I.grabAttributeFrom('#tooltip', 'title');
|
|
|
452
454
|
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
|
|
453
455
|
- `attr` **[string][3]** attribute name.
|
|
454
456
|
|
|
455
|
-
Returns **[Promise][
|
|
457
|
+
Returns **[Promise][8]<[string][3]>** attribute value
|
|
456
458
|
|
|
457
459
|
### grabAttributeFromAll
|
|
458
460
|
|
|
@@ -468,7 +470,7 @@ let hints = await I.grabAttributeFromAll('.tooltip', 'title');
|
|
|
468
470
|
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
|
|
469
471
|
- `attr` **[string][3]** attribute name.
|
|
470
472
|
|
|
471
|
-
Returns **[Promise][
|
|
473
|
+
Returns **[Promise][8]<[Array][10]<[string][3]>>** attribute value
|
|
472
474
|
|
|
473
475
|
### grabCookie
|
|
474
476
|
|
|
@@ -485,7 +487,7 @@ assert(cookie.value, '123456');
|
|
|
485
487
|
|
|
486
488
|
- `name` **[string][3]?** cookie name.
|
|
487
489
|
|
|
488
|
-
Returns **([Promise][
|
|
490
|
+
Returns **([Promise][8]<[string][3]> | [Promise][8]<[Array][10]<[string][3]>>)** attribute valueCookie in JSON format. If name not passed returns all cookies for this domain.Multiple cookies can be received by passing query object `I.grabCookie({ secure: true});`. If you'd like get all cookies for all urls, use: `.grabCookie({ url: null }).`
|
|
489
491
|
|
|
490
492
|
### grabCssPropertyFrom
|
|
491
493
|
|
|
@@ -502,7 +504,7 @@ const value = await I.grabCssPropertyFrom('h3', 'font-weight');
|
|
|
502
504
|
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
|
|
503
505
|
- `cssProperty` **[string][3]** CSS property name.
|
|
504
506
|
|
|
505
|
-
Returns **[Promise][
|
|
507
|
+
Returns **[Promise][8]<[string][3]>** CSS value
|
|
506
508
|
|
|
507
509
|
### grabCurrentUrl
|
|
508
510
|
|
|
@@ -514,7 +516,7 @@ let url = await I.grabCurrentUrl();
|
|
|
514
516
|
console.log(`Current URL is [${url}]`);
|
|
515
517
|
```
|
|
516
518
|
|
|
517
|
-
Returns **[Promise][
|
|
519
|
+
Returns **[Promise][8]<[string][3]>** current URL
|
|
518
520
|
|
|
519
521
|
### grabElementBoundingRect
|
|
520
522
|
|
|
@@ -542,7 +544,7 @@ const width = await I.grabElementBoundingRect('h3', 'width');
|
|
|
542
544
|
- `prop`
|
|
543
545
|
- `elementSize` **[string][3]?** x, y, width or height of the given element.
|
|
544
546
|
|
|
545
|
-
Returns **([Promise][
|
|
547
|
+
Returns **([Promise][8]<DOMRect> | [Promise][8]<[number][11]>)** Element bounding rectangle
|
|
546
548
|
|
|
547
549
|
### grabHAR
|
|
548
550
|
|
|
@@ -568,7 +570,7 @@ let postHTML = await I.grabHTMLFrom('#post');
|
|
|
568
570
|
- `locator`
|
|
569
571
|
- `element` **([string][3] | [object][4])** located by CSS|XPath|strict locator.
|
|
570
572
|
|
|
571
|
-
Returns **[Promise][
|
|
573
|
+
Returns **[Promise][8]<[string][3]>** HTML code for an element
|
|
572
574
|
|
|
573
575
|
### grabHTMLFromAll
|
|
574
576
|
|
|
@@ -584,7 +586,7 @@ let postHTMLs = await I.grabHTMLFromAll('.post');
|
|
|
584
586
|
- `locator`
|
|
585
587
|
- `element` **([string][3] | [object][4])** located by CSS|XPath|strict locator.
|
|
586
588
|
|
|
587
|
-
Returns **[Promise][
|
|
589
|
+
Returns **[Promise][8]<[Array][10]<[string][3]>>** HTML code for an element
|
|
588
590
|
|
|
589
591
|
### grabNumberOfVisibleElements
|
|
590
592
|
|
|
@@ -599,7 +601,7 @@ let numOfElements = await I.grabNumberOfVisibleElements('p');
|
|
|
599
601
|
|
|
600
602
|
- `locator` **([string][3] | [object][4])** located by CSS|XPath|strict locator.
|
|
601
603
|
|
|
602
|
-
Returns **[Promise][
|
|
604
|
+
Returns **[Promise][8]<[number][11]>** number of visible elements
|
|
603
605
|
|
|
604
606
|
### grabPageScrollPosition
|
|
605
607
|
|
|
@@ -610,7 +612,7 @@ Resumes test execution, so **should be used inside an async function with `await
|
|
|
610
612
|
let { x, y } = await I.grabPageScrollPosition();
|
|
611
613
|
```
|
|
612
614
|
|
|
613
|
-
Returns **[Promise][
|
|
615
|
+
Returns **[Promise][8]<PageScrollPosition>** scroll position
|
|
614
616
|
|
|
615
617
|
### grabTextFrom
|
|
616
618
|
|
|
@@ -627,7 +629,7 @@ If multiple elements found returns first element.
|
|
|
627
629
|
|
|
628
630
|
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
|
|
629
631
|
|
|
630
|
-
Returns **[Promise][
|
|
632
|
+
Returns **[Promise][8]<[string][3]>** attribute value
|
|
631
633
|
|
|
632
634
|
### grabTextFromAll
|
|
633
635
|
|
|
@@ -642,7 +644,7 @@ let pins = await I.grabTextFromAll('#pin li');
|
|
|
642
644
|
|
|
643
645
|
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
|
|
644
646
|
|
|
645
|
-
Returns **[Promise][
|
|
647
|
+
Returns **[Promise][8]<[Array][10]<[string][3]>>** attribute value
|
|
646
648
|
|
|
647
649
|
### grabTitle
|
|
648
650
|
|
|
@@ -653,7 +655,7 @@ Resumes test execution, so **should be used inside async with `await`** operator
|
|
|
653
655
|
let title = await I.grabTitle();
|
|
654
656
|
```
|
|
655
657
|
|
|
656
|
-
Returns **[Promise][
|
|
658
|
+
Returns **[Promise][8]<[string][3]>** title
|
|
657
659
|
|
|
658
660
|
### grabValueFrom
|
|
659
661
|
|
|
@@ -669,7 +671,7 @@ let email = await I.grabValueFrom('input[name=email]');
|
|
|
669
671
|
|
|
670
672
|
- `locator` **([string][3] | [object][4])** field located by label|name|CSS|XPath|strict locator.
|
|
671
673
|
|
|
672
|
-
Returns **[Promise][
|
|
674
|
+
Returns **[Promise][8]<[string][3]>** attribute value
|
|
673
675
|
|
|
674
676
|
### grabValueFromAll
|
|
675
677
|
|
|
@@ -684,7 +686,7 @@ let inputs = await I.grabValueFromAll('//form/input');
|
|
|
684
686
|
|
|
685
687
|
- `locator` **([string][3] | [object][4])** field located by label|name|CSS|XPath|strict locator.
|
|
686
688
|
|
|
687
|
-
Returns **[Promise][
|
|
689
|
+
Returns **[Promise][8]<[Array][10]<[string][3]>>** attribute value
|
|
688
690
|
|
|
689
691
|
### haveHeader
|
|
690
692
|
|
|
@@ -1159,7 +1161,7 @@ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and
|
|
|
1159
1161
|
|
|
1160
1162
|
#### Parameters
|
|
1161
1163
|
|
|
1162
|
-
- `fn` **([string][3] | [function][
|
|
1164
|
+
- `fn` **([string][3] | [function][7])** to be executed in browser context.
|
|
1163
1165
|
- `argsOrSec` **([Array][10]<any> | [number][11])?** (optional, `1` by default) arguments for function or seconds.
|
|
1164
1166
|
- `sec` **[number][11]?** (optional, `1` by default) time in seconds to wait
|
|
1165
1167
|
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -1239,11 +1241,11 @@ I.waitToHide('#popup');
|
|
|
1239
1241
|
|
|
1240
1242
|
[6]: https://vuejs.org/v2/api/#Vue-nextTick
|
|
1241
1243
|
|
|
1242
|
-
[7]: https://
|
|
1244
|
+
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
|
|
1243
1245
|
|
|
1244
|
-
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/
|
|
1246
|
+
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
1245
1247
|
|
|
1246
|
-
[9]: https://
|
|
1248
|
+
[9]: https://github.com/segmentio/nightmare#evaluatefn-arg1-arg2
|
|
1247
1249
|
|
|
1248
1250
|
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
|
|
1249
1251
|
|
|
@@ -530,7 +530,8 @@ let val = await I.executeAsyncScript(function(url, done) {
|
|
|
530
530
|
|
|
531
531
|
- `fn` **([string][9] | [function][12])** function to be executed in browser context.
|
|
532
532
|
- `args` **...any** to be passed to function.
|
|
533
|
-
|
|
533
|
+
|
|
534
|
+
Returns **[Promise][13]<any>** script return value⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
534
535
|
|
|
535
536
|
### executeScript
|
|
536
537
|
|
|
@@ -562,7 +563,8 @@ let date = await I.executeScript(function(el) {
|
|
|
562
563
|
|
|
563
564
|
- `fn` **([string][9] | [function][12])** function to be executed in browser context.
|
|
564
565
|
- `args` **...any** to be passed to function.
|
|
565
|
-
|
|
566
|
+
|
|
567
|
+
Returns **[Promise][13]<any>** script return value⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
566
568
|
|
|
567
569
|
### fillField
|
|
568
570
|
|