codeceptjs 3.5.7-beta.1 → 3.5.8

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/README.md CHANGED
@@ -7,10 +7,14 @@
7
7
 
8
8
  Build Status:
9
9
 
10
+ Appium Helper:
11
+ [![Appium V2 Tests - Android](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_Android.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_Android.yml)
12
+ [![Appium V2 Tests - iOS](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_iOS.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appiumV2_iOS.yml)
13
+
14
+ Web Helper:
10
15
  [![Playwright Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/playwright.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/playwright.yml)
11
16
  [![Puppeteer Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/puppeteer.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/puppeteer.yml)
12
17
  [![WebDriver Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml)
13
- [![Appium Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium.yml)
14
18
  [![TestCafe Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/testcafe.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/testcafe.yml)
15
19
 
16
20
  # CodeceptJS [![Made in Ukraine](https://img.shields.io/badge/made_in-ukraine-ffd700.svg?labelColor=0057b7)](https://stand-with-ukraine.pp.ua)
package/docs/advanced.md CHANGED
@@ -150,7 +150,7 @@ For **Visual Studio Code**, add the following configuration in launch.json:
150
150
  "request": "launch",
151
151
  "name": "codeceptjs",
152
152
  "args": ["run", "--grep", "@your_test_tag"],
153
- "program": "${workspaceFolder}/node_modules/.bin/codeceptjs"
153
+ "program": "${workspaceFolder}/node_modules/codeceptjs/bin/codecept.js"
154
154
  }
155
155
  ```
156
156
 
@@ -183,6 +183,11 @@ class Appium extends Webdriver {
183
183
  this.axios = axios.create();
184
184
 
185
185
  webdriverio = require('webdriverio');
186
+ if (!config.appiumV2) {
187
+ console.log('The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Please migrating to Appium 2.x by adding appiumV2: true to your config.');
188
+ console.log('More info: https://bit.ly/appium-v2-migration');
189
+ console.log('This Appium 1.x support will be removed in next major release.');
190
+ }
186
191
  }
187
192
 
188
193
  _validateConfig(config) {
@@ -916,11 +921,12 @@ class Appium extends Webdriver {
916
921
  * I.setNetworkConnection(4) // airplane mode off, wifi off, data on
917
922
  * I.setNetworkConnection(6) // airplane mode off, wifi on, data on
918
923
  * ```
919
- * See corresponding [webdriverio reference](http://webdriver.io/api/mobile/setNetworkConnection.html).
920
- *
921
- * @return {Promise<{}>}
924
+ * See corresponding [webdriverio reference](https://webdriver.io/docs/api/chromium/#setnetworkconnection).
922
925
  *
923
926
  * Appium: support only Android
927
+ *
928
+ * @param {number} value The network connection mode bitmask
929
+ * @return {Promise<number>}
924
930
  */
925
931
  async setNetworkConnection(value) {
926
932
  onlyForApps.call(this, supportedPlatform.android);
@@ -116,6 +116,10 @@ const config = {};
116
116
  * npm i playwright-core@^1.18 --save
117
117
  * ```
118
118
  *
119
+ * Breaking Changes: if you use Playwright v1.38 and later, it will no longer download browsers automatically.
120
+ *
121
+ * Run `npx playwright install` to download browsers after `npm install`.
122
+ *
119
123
  * 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.
120
124
  *
121
125
  *
@@ -1061,6 +1065,38 @@ class Playwright extends Helper {
1061
1065
  await el.blur(options);
1062
1066
  return this._waitForAction();
1063
1067
  }
1068
+ /**
1069
+ * Return the checked status of given element.
1070
+ *
1071
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1072
+ * @param {object} [options] See https://playwright.dev/docs/api/class-locator#locator-is-checked
1073
+ * @return {Promise<boolean>}
1074
+ *
1075
+ */
1076
+
1077
+ async grabCheckedElementStatus(locator, options = {}) {
1078
+ const supportedTypes = ['checkbox', 'radio'];
1079
+ const el = await this._locateElement(locator);
1080
+ const type = await el.getAttribute('type');
1081
+
1082
+ if (supportedTypes.includes(type)) {
1083
+ return el.isChecked(options);
1084
+ }
1085
+ throw new Error(`Element is not a ${supportedTypes.join(' or ')} input`);
1086
+ }
1087
+ /**
1088
+ * Return the disabled status of given element.
1089
+ *
1090
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1091
+ * @param {object} [options] See https://playwright.dev/docs/api/class-locator#locator-is-disabled
1092
+ * @return {Promise<boolean>}
1093
+ *
1094
+ */
1095
+
1096
+ async grabDisabledElementStatus(locator, options = {}) {
1097
+ const el = await this._locateElement(locator);
1098
+ return el.isDisabled(options);
1099
+ }
1064
1100
 
1065
1101
  /**
1066
1102
  * Drag an item to a destination element.
@@ -3486,6 +3522,7 @@ class Playwright extends Helper {
3486
3522
  let count = 0;
3487
3523
  do {
3488
3524
  waiter = await _contextObject.locator(`:has-text('${text}')`).first().isVisible();
3525
+ if (waiter) break;
3489
3526
  await this.wait(1);
3490
3527
  count += 1000;
3491
3528
  } while (count <= waitTimeout);
@@ -4,6 +4,7 @@ const fsExtra = require('fs-extra');
4
4
  const path = require('path');
5
5
 
6
6
  const Helper = require('@codeceptjs/helper');
7
+ const { v4: uuidv4 } = require('uuid');
7
8
  const Locator = require('../locator');
8
9
  const recorder = require('../recorder');
9
10
  const store = require('../store');
@@ -19,6 +20,7 @@ const {
19
20
  fileExists,
20
21
  chunkArray,
21
22
  toCamelCase,
23
+ clearString,
22
24
  convertCssPropertiesToCamelCase,
23
25
  screenshotOutputFolder,
24
26
  getNormalizedKeyAttributeValue,
@@ -57,6 +59,8 @@ const consoleLogStore = new Console();
57
59
  * @prop {boolean} [disableScreenshots=false] - don't save screenshot on failure.
58
60
  * @prop {boolean} [fullPageScreenshots=false] - make full page screenshots on failure.
59
61
  * @prop {boolean} [uniqueScreenshotNames=false] - option to prevent screenshot override if you have scenarios with the same name in different suites.
62
+ * @prop {boolean} [trace=false] - record [tracing information](https://pptr.dev/api/puppeteer.tracing) with screenshots.
63
+ * @prop {boolean} [keepTraceForPassedTests=false] - save trace for passed tests.
60
64
  * @prop {boolean} [keepBrowserState=false] - keep browser state between tests when `restart` is set to false.
61
65
  * @prop {boolean} [keepCookies=false] - keep cookies between tests when `restart` is set to false.
62
66
  * @prop {number} [waitForAction=100] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
@@ -92,6 +96,14 @@ const config = {};
92
96
  *
93
97
  * <!-- configuration -->
94
98
  *
99
+ * #### Trace Recording Customization
100
+ *
101
+ * Trace recording provides complete information on test execution and includes screenshots, and network requests logged during run.
102
+ * Traces will be saved to `output/trace`
103
+ *
104
+ * * `trace`: enables trace recording for failed tests; trace are saved into `output/trace` folder
105
+ * * `keepTraceForPassedTests`: - save trace for passed tests
106
+ *
95
107
  * #### Example #1: Wait for 0 network connections.
96
108
  *
97
109
  * ```js
@@ -281,8 +293,9 @@ class Puppeteer extends Helper {
281
293
  }
282
294
  }
283
295
 
284
- async _before() {
296
+ async _before(test) {
285
297
  this.sessionPages = {};
298
+ this.currentRunningTest = test;
286
299
  recorder.retry({
287
300
  retries: 3,
288
301
  when: err => {
@@ -666,6 +679,14 @@ class Puppeteer extends Helper {
666
679
  }
667
680
  }
668
681
 
682
+ if (this.options.trace) {
683
+ const fileName = `${`${global.output_dir}${path.sep}trace${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.json`;
684
+ const dir = path.dirname(fileName);
685
+ if (!fileExists(dir)) fs.mkdirSync(dir);
686
+ await this.page.tracing.start({ screenshots: true, path: fileName });
687
+ this.currentRunningTest.artifacts.trace = fileName;
688
+ }
689
+
669
690
  await this.page.goto(url, { waitUntil: this.options.waitForNavigation });
670
691
 
671
692
  const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)));
@@ -2787,8 +2808,30 @@ class Puppeteer extends Helper {
2787
2808
  }
2788
2809
  }
2789
2810
 
2790
- async _failed() {
2811
+ async _failed(test) {
2812
+ await this._withinEnd();
2813
+
2814
+ if (this.options.trace) {
2815
+ await this.page.tracing.stop();
2816
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.failed.json');
2817
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName);
2818
+ test.artifacts.trace = _traceName;
2819
+ }
2820
+ }
2821
+
2822
+ async _passed(test) {
2791
2823
  await this._withinEnd();
2824
+
2825
+ if (this.options.trace) {
2826
+ await this.page.tracing.stop();
2827
+ if (this.options.keepTraceForPassedTests) {
2828
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.passed.json');
2829
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName);
2830
+ test.artifacts.trace = _traceName;
2831
+ } else {
2832
+ fs.unlinkSync(this.currentRunningTest.artifacts.trace);
2833
+ }
2834
+ }
2792
2835
  }
2793
2836
 
2794
2837
  /**
package/docs/changelog.md CHANGED
@@ -7,6 +7,189 @@ layout: Section
7
7
 
8
8
  # Releases
9
9
 
10
+ ## 3.5.8
11
+
12
+ Thanks all to those who contributed to make this release!
13
+
14
+ 🐛 *Bug Fixes*
15
+ fix(appium): type of setNetworkConnection() ([#3994](https://github.com/codeceptjs/CodeceptJS/issues/3994)) - by **[mirao](https://github.com/mirao)**
16
+ fix: improve the way to show deprecated appium v1 message ([#3992](https://github.com/codeceptjs/CodeceptJS/issues/3992)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
17
+ fix: missing exit condition of some wait functions - by **[kobenguyent](https://github.com/kobenguyent)**
18
+
19
+ ## 3.5.7
20
+
21
+ Thanks all to those who contributed to make this release!
22
+
23
+ 🐛 *Bug Fixes*
24
+ * Bump playwright to 1.39.0 - run `npx playwright install` to install the browsers as starting from 1.39.0 browsers are not installed automatically ([#3924](https://github.com/codeceptjs/CodeceptJS/issues/3924)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
25
+ * fix(playwright): some wait functions draw error due to switchTo iframe ([#3918](https://github.com/codeceptjs/CodeceptJS/issues/3918)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
26
+ * fix(appium): AppiumTestDistribution/appium-device-farm requires 'platformName' ([#3950](https://github.com/codeceptjs/CodeceptJS/issues/3950)) - by **[rock-tran](https://github.com/rock-tran)**
27
+ * fix: autologin with empty fetch ([#3947](https://github.com/codeceptjs/CodeceptJS/issues/3947)) - by **[andonary](https://github.com/andonary)**
28
+ * fix(cli): customLocator draws error in dry-mode ([#3940](https://github.com/codeceptjs/CodeceptJS/issues/3940)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
29
+ * fix: ensure docs include **[returns](https://github.com/returns)** Promise<void> where appropriate ([#3954](https://github.com/codeceptjs/CodeceptJS/issues/3954)) - by **[fwouts](https://github.com/fwouts)**
30
+ * fix: long text in data table cuts off ([#3936](https://github.com/codeceptjs/CodeceptJS/issues/3936)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
31
+ ```
32
+ #language: de
33
+ Funktionalität: Faker examples
34
+
35
+ Szenariogrundriss: Atualizar senha do usuário
36
+ Angenommen que estou logado via REST com o usuário "<customer>"
37
+ | protocol | https: |
38
+ | hostname | https://cucumber.io/docs/gherkin/languages/ |
39
+
40
+
41
+ Faker examples --
42
+ Atualizar senha do usuário {"product":"{{vehicle.vehicle}}","customer":"Dr. {{name.findName}}","price":"{{commerce.price}}","cashier":"cashier 2"}
43
+ On Angenommen: que estou logado via rest com o usuário "dr. {{name.find name}}"
44
+ protocol | https:
45
+ hostname | https://cucumber.io/docs/gherkin/languages/
46
+
47
+ Dr. {{name.findName}}
48
+ ✔ OK in 13ms
49
+
50
+ ```
51
+ * fix(playwright): move to waitFor ([#3933](https://github.com/codeceptjs/CodeceptJS/issues/3933)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
52
+ * fix: relax grabCookie type ([#3919](https://github.com/codeceptjs/CodeceptJS/issues/3919)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
53
+ * fix: proceedSee error when being called inside within ([#3939](https://github.com/codeceptjs/CodeceptJS/issues/3939)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
54
+ * fix: rename haveRequestHeaders of ppt and pw helpers ([#3937](https://github.com/codeceptjs/CodeceptJS/issues/3937)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
55
+ ```
56
+ Renamed haveRequestHeaders of Puppeteer, Playwright helper so that it would not confuse the REST helper.
57
+ Puppeteer: setPuppeteerRequestHeaders
58
+ Playwright: setPlaywrightRequestHeaders
59
+ ```
60
+ * improvement: handle the way to load apifactory nicely ([#3941](https://github.com/codeceptjs/CodeceptJS/issues/3941)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
61
+ ```
62
+ With this fix, we could now use the following syntax:
63
+
64
+ export = new Factory()
65
+ .attr('name', () => faker.name.findName())
66
+ .attr('job', () => 'leader');
67
+
68
+ export default new Factory()
69
+ .attr('name', () => faker.name.findName())
70
+ .attr('job', () => 'leader');
71
+
72
+ modules.export = new Factory()
73
+ .attr('name', () => faker.name.findName())
74
+ .attr('job', () => 'leader');
75
+ ```
76
+
77
+ 📖 *Documentation*
78
+ * docs(appium): update to v2 ([#3932](https://github.com/codeceptjs/CodeceptJS/issues/3932)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
79
+ * docs: improve BDD Gherkin docs ([#3938](https://github.com/codeceptjs/CodeceptJS/issues/3938)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
80
+ * Other docs improvements
81
+
82
+ 🛩️ *Features*
83
+ * feat(puppeteer): support trace recording - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
84
+ ```
85
+ [Trace Recording Customization]
86
+ Trace recording provides complete information on test execution and includes screenshots, and network requests logged during run. Traces will be saved to output/trace
87
+
88
+ trace: enables trace recording for failed tests; trace are saved into output/trace folder
89
+ keepTraceForPassedTests: - save trace for passed tests
90
+ ```
91
+ * feat: expect helper ([#3923](https://github.com/codeceptjs/CodeceptJS/issues/3923)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
92
+ ```
93
+ * This helper allows performing assertions based on Chai.
94
+ *
95
+ * ### Examples
96
+ *
97
+ * Zero-configuration when paired with other helpers like REST, Playwright:
98
+ *
99
+ * ```js
100
+ * // inside codecept.conf.js
101
+ *{
102
+ * helpers: {
103
+ * Playwright: {...},
104
+ * ExpectHelper: {},
105
+ * }
106
+
107
+ Expect Helper
108
+ #expectEqual
109
+ #expectNotEqual
110
+ #expectContain
111
+ #expectNotContain
112
+ #expectStartsWith
113
+ #expectNotStartsWith
114
+ #expectEndsWith
115
+ #expectNotEndsWith
116
+ #expectJsonSchema
117
+ #expectHasProperty
118
+ #expectHasAProperty
119
+ #expectToBeA
120
+ #expectToBeAn
121
+ #expectMatchRegex
122
+ #expectLengthOf
123
+ #expectTrue
124
+ #expectEmpty
125
+ #expectFalse
126
+ #expectAbove
127
+ #expectBelow
128
+ #expectLengthAboveThan
129
+ #expectLengthBelowThan
130
+ #expectLengthBelowThan
131
+ #expectDeepMembers
132
+ #expectDeepIncludeMembers
133
+ #expectDeepEqualExcluding
134
+ #expectLengthBelowThan
135
+ ```
136
+ * feat: run-workers with multiple browsers output folders - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
137
+ - ![Screenshot 2023-11-04 at 10 49 56](https://github.com/codeceptjs/CodeceptJS/assets/7845001/8eaecc54-de14-4597-b148-1e087bec3c76)
138
+ - ![Screenshot 2023-11-03 at 15 56 38](https://github.com/codeceptjs/CodeceptJS/assets/7845001/715aed17-3535-48df-80dd-84f7024f08e3)
139
+ * feat: introduce new Playwright methods - by **[hatufacci](https://github.com/hatufacci)**
140
+ ```
141
+ - grabCheckedElementStatus
142
+ - grabDisabledElementStatus
143
+ ```
144
+ * feat: gherkin supports i18n ([#3934](https://github.com/codeceptjs/CodeceptJS/issues/3934)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
145
+ ```
146
+ #language: de
147
+ Funktionalität: Checkout-Prozess
148
+ Um Produkte zu kaufen
149
+ Als Kunde
150
+ Möchte ich in der Lage sein, mehrere Produkte zu kaufen
151
+
152
+ **[i18n](https://github.com/i18n)**
153
+ Szenariogrundriss: Bestellrabatt
154
+ Angenommen ich habe ein Produkt mit einem Preis von <price>$ in meinem Warenkorb
155
+ Und der Rabatt für Bestellungen über $20 beträgt 10 %
156
+ Wenn ich zur Kasse gehe
157
+ Dann sollte ich den Gesamtpreis von "<total>" $ sehen
158
+
159
+ Beispiele:
160
+ | price | total |
161
+ | 10 | 10.0 |
162
+ ```
163
+ * feat(autoLogin): improve the check method ([#3935](https://github.com/codeceptjs/CodeceptJS/issues/3935)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)**
164
+ ```
165
+ Instead of asserting on page elements for the current user in check, you can use the session you saved in fetch
166
+
167
+ autoLogin: {
168
+ enabled: true,
169
+ saveToFile: true,
170
+ inject: 'login',
171
+ users: {
172
+ admin: {
173
+ login: async (I) => { // If you use async function in the autoLogin plugin
174
+ const phrase = await I.grabTextFrom('#phrase')
175
+ I.fillField('username', 'admin'),
176
+ I.fillField('password', 'password')
177
+ I.fillField('phrase', phrase)
178
+ },
179
+ check: (I, session) => {
180
+ // Throwing an error in `check` will make CodeceptJS perform the login step for the user
181
+ if (session.profile.email !== the.email.you.expect@some-mail.com) {
182
+ throw new Error ('Wrong user signed in');
183
+ }
184
+ },
185
+ }
186
+ }
187
+ }
188
+ Scenario('login', async ( {I, login} ) => {
189
+ await login('admin') // you should use `await`
190
+ })
191
+ ```
192
+
10
193
  ## 3.5.6
11
194
 
12
195
  Thanks all to those who contributed to make this release!