codeceptjs 3.3.8-beta.1 → 3.4.0
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 +47 -0
- package/README.md +31 -32
- package/docs/advanced.md +48 -24
- package/docs/basics.md +115 -40
- package/docs/best.md +2 -2
- package/docs/build/ApiDataFactory.js +14 -9
- package/docs/build/Appium.js +2 -19
- package/docs/build/FileSystem.js +3 -3
- package/docs/build/GraphQL.js +1 -1
- package/docs/build/GraphQLDataFactory.js +3 -3
- package/docs/build/JSONResponse.js +1 -1
- package/docs/build/Mochawesome.js +1 -1
- package/docs/build/Nightmare.js +1 -1
- package/docs/build/Playwright.js +4 -3
- package/docs/build/Protractor.js +1 -1
- package/docs/build/Puppeteer.js +1 -1
- package/docs/build/REST.js +1 -1
- package/docs/build/TestCafe.js +5 -5
- package/docs/build/WebDriver.js +30 -165
- package/docs/changelog.md +49 -2
- package/docs/helpers/ApiDataFactory.md +6 -6
- package/docs/helpers/FileSystem.md +2 -2
- package/docs/helpers/GraphQLDataFactory.md +2 -2
- package/docs/helpers/Playwright.md +2 -1
- package/docs/index.md +1 -1
- package/docs/plugins.md +42 -125
- package/docs/reports.md +0 -56
- package/docs/tutorial.md +271 -0
- package/docs/typescript.md +2 -8
- package/lib/actor.js +2 -1
- package/lib/cli.js +3 -3
- package/lib/codecept.js +2 -1
- package/lib/command/generate.js +3 -1
- package/lib/command/gherkin/snippets.js +8 -4
- package/lib/command/init.js +0 -8
- package/lib/command/run-workers.js +3 -6
- package/lib/command/utils.js +0 -10
- package/lib/command/workers/runTests.js +2 -2
- package/lib/config.js +5 -1
- package/lib/helper/ApiDataFactory.js +14 -9
- package/lib/helper/Appium.js +2 -19
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQL.js +1 -1
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +1 -1
- package/lib/helper/Mochawesome.js +1 -1
- package/lib/helper/Nightmare.js +1 -1
- package/lib/helper/Playwright.js +4 -3
- package/lib/helper/Protractor.js +1 -1
- package/lib/helper/Puppeteer.js +1 -1
- package/lib/helper/REST.js +1 -1
- package/lib/helper/TestCafe.js +5 -5
- package/lib/helper/WebDriver.js +30 -165
- package/lib/helper.js +0 -2
- package/lib/interfaces/bdd.js +1 -1
- package/lib/interfaces/featureConfig.js +1 -0
- package/lib/interfaces/gherkin.js +38 -25
- package/lib/listener/exit.js +2 -2
- package/lib/listener/retry.js +67 -0
- package/lib/listener/steps.js +1 -1
- package/lib/listener/timeout.js +47 -10
- package/lib/mochaFactory.js +3 -3
- package/lib/plugin/allure.js +14 -323
- package/lib/plugin/fakerTransform.js +2 -2
- package/lib/recorder.js +1 -1
- package/lib/scenario.js +25 -18
- package/lib/utils.js +6 -0
- package/lib/workers.js +4 -7
- package/package.json +14 -18
- package/typings/index.d.ts +76 -1
- package/typings/promiseBasedTypes.d.ts +12 -12
- package/typings/types.d.ts +95 -262
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
## 3.4.0
|
|
2
|
+
|
|
3
|
+
* **Updated to latest mocha and modern Cucumber**
|
|
4
|
+
* **Allure plugin moved to [@codeceptjs/allure-legacy](https://github.com/codeceptjs/allure-legacy) package**. This happened because allure-commons package v1 was not updated and caused vulnarabilities. Fixes #3422. We don't plan to maintain allure v2 plugin so it's up to community to take this initiative. Current allure plugin will print a warning message without interfering the run, so it won't accidentally fail your builds.
|
|
5
|
+
* Added ability to **[retry Before](https://codecept.io/basics/#retry-before), BeforeSuite, After, AfterSuite** hooks by @davertmik:
|
|
6
|
+
```js
|
|
7
|
+
Feature('flaky Before & BeforeSuite', { retryBefore: 2, retryBeforeSuite: 3 })
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
* **Flexible [retries configuration](https://codecept.io/basics/#retry-configuration) introduced** by @davertmik:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
retry: [
|
|
14
|
+
{
|
|
15
|
+
// enable this config only for flaky tests
|
|
16
|
+
grep: '@flaky',
|
|
17
|
+
Before: 3 // retry Before 3 times
|
|
18
|
+
Scenario: 3 // retry Scenario 3 times
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
// retry less when running slow tests
|
|
22
|
+
grep: '@slow'
|
|
23
|
+
Scenario: 1
|
|
24
|
+
Before: 1
|
|
25
|
+
}, {
|
|
26
|
+
// retry all BeforeSuite 3 times
|
|
27
|
+
BeforeSuite: 3
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
```
|
|
31
|
+
* **Flexible [timeout configuration](https://codecept.io/advanced/#timeout-configuration)** introduced by @davertmik:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
timeout: [
|
|
35
|
+
10, // default timeout is 10secs
|
|
36
|
+
{ // but increase timeout for slow tests
|
|
37
|
+
grep: '@slow',
|
|
38
|
+
Feature: 50
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
* JsDoc: Removed promise from `I.say`. See #3535 by @danielrentz
|
|
44
|
+
* [Playwright] `handleDownloads` requires now a filename param. See #3511 by @PeterNgTr
|
|
45
|
+
* [WebDriver] Added support for v8, removed support for webdriverio v5 and lower. See #3578 by @PeterNgTr
|
|
46
|
+
|
|
47
|
+
|
|
1
48
|
## 3.3.7
|
|
2
49
|
|
|
3
50
|
🛩️ Features
|
package/README.md
CHANGED
|
@@ -101,8 +101,7 @@ npx codeceptjs def .
|
|
|
101
101
|
Later you can even automagically update Type Definitions to include your own custom [helpers methods](docs/helpers.md).
|
|
102
102
|
|
|
103
103
|
Note:
|
|
104
|
-
- CodeceptJS requires Node.js version `
|
|
105
|
-
- To use the parallel tests execution, requiring Node.js version `11.7` or later.
|
|
104
|
+
- CodeceptJS requires Node.js version `12+` or later.
|
|
106
105
|
|
|
107
106
|
## Usage
|
|
108
107
|
|
|
@@ -294,36 +293,36 @@ When using Typescript, replace `module.exports` with `export` for autocompletion
|
|
|
294
293
|
Thanks all to those who are and will have contributing to this awesome project!
|
|
295
294
|
|
|
296
295
|
[//]: contributor-faces
|
|
297
|
-
<a href="https://github.com/DavertMik"><img src="https://
|
|
298
|
-
<a href="https://github.com/PeterNgTr"><img src="https://
|
|
299
|
-
<a href="https://github.com/Vorobeyko"><img src="https://
|
|
300
|
-
<a href="https://github.com/
|
|
301
|
-
<a href="https://github.com/
|
|
302
|
-
<a href="https://github.com/
|
|
303
|
-
<a href="https://github.com/
|
|
304
|
-
<a href="https://github.com/
|
|
305
|
-
<a href="https://github.com/
|
|
306
|
-
<a href="https://github.com/
|
|
307
|
-
<a href="https://github.com/
|
|
308
|
-
<a href="https://github.com/
|
|
309
|
-
<a href="https://github.com/
|
|
310
|
-
<a href="https://github.com/
|
|
311
|
-
<a href="https://github.com/
|
|
312
|
-
<a href="https://github.com/
|
|
313
|
-
<a href="https://github.com/
|
|
314
|
-
<a href="https://github.com/
|
|
315
|
-
<a href="https://github.com/
|
|
316
|
-
<a href="https://github.com/
|
|
317
|
-
<a href="https://github.com/
|
|
318
|
-
<a href="https://github.com/
|
|
319
|
-
<a href="https://github.com/
|
|
320
|
-
<a href="https://github.com/
|
|
321
|
-
<a href="https://github.com/
|
|
322
|
-
<a href="https://github.com/
|
|
323
|
-
<a href="https://github.com/
|
|
324
|
-
<a href="https://github.com/
|
|
325
|
-
<a href="https://github.com/
|
|
326
|
-
<a href="https://github.com/
|
|
296
|
+
<a href="https://github.com/DavertMik"><img src="https://avatars.githubusercontent.com/u/220264?v=4" title="DavertMik" width="80" height="80"></a>
|
|
297
|
+
<a href="https://github.com/PeterNgTr"><img src="https://avatars.githubusercontent.com/u/7845001?v=4" title="PeterNgTr" width="80" height="80"></a>
|
|
298
|
+
<a href="https://github.com/Vorobeyko"><img src="https://avatars.githubusercontent.com/u/11293201?v=4" title="Vorobeyko" width="80" height="80"></a>
|
|
299
|
+
<a href="https://github.com/reubenmiller"><img src="https://avatars.githubusercontent.com/u/3029781?v=4" title="reubenmiller" width="80" height="80"></a>
|
|
300
|
+
<a href="https://github.com/Arhell"><img src="https://avatars.githubusercontent.com/u/26163841?v=4" title="Arhell" width="80" height="80"></a>
|
|
301
|
+
<a href="https://github.com/APshenkin"><img src="https://avatars.githubusercontent.com/u/14344430?v=4" title="APshenkin" width="80" height="80"></a>
|
|
302
|
+
<a href="https://github.com/fabioel"><img src="https://avatars.githubusercontent.com/u/9824235?v=4" title="fabioel" width="80" height="80"></a>
|
|
303
|
+
<a href="https://github.com/pablopaul"><img src="https://avatars.githubusercontent.com/u/635526?v=4" title="pablopaul" width="80" height="80"></a>
|
|
304
|
+
<a href="https://github.com/Georgegriff"><img src="https://avatars.githubusercontent.com/u/9056958?v=4" title="Georgegriff" width="80" height="80"></a>
|
|
305
|
+
<a href="https://github.com/mirao"><img src="https://avatars.githubusercontent.com/u/12584138?v=4" title="mirao" width="80" height="80"></a>
|
|
306
|
+
<a href="https://github.com/KMKoushik"><img src="https://avatars.githubusercontent.com/u/24666922?v=4" title="KMKoushik" width="80" height="80"></a>
|
|
307
|
+
<a href="https://github.com/nikocanvacom"><img src="https://avatars.githubusercontent.com/u/83254493?v=4" title="nikocanvacom" width="80" height="80"></a>
|
|
308
|
+
<a href="https://github.com/elukoyanov"><img src="https://avatars.githubusercontent.com/u/11647141?v=4" title="elukoyanov" width="80" height="80"></a>
|
|
309
|
+
<a href="https://github.com/gkushang"><img src="https://avatars.githubusercontent.com/u/3663389?v=4" title="gkushang" width="80" height="80"></a>
|
|
310
|
+
<a href="https://github.com/tsuemura"><img src="https://avatars.githubusercontent.com/u/17092259?v=4" title="tsuemura" width="80" height="80"></a>
|
|
311
|
+
<a href="https://github.com/VikalpP"><img src="https://avatars.githubusercontent.com/u/11846339?v=4" title="VikalpP" width="80" height="80"></a>
|
|
312
|
+
<a href="https://github.com/BorisOsipov"><img src="https://avatars.githubusercontent.com/u/6514276?v=4" title="BorisOsipov" width="80" height="80"></a>
|
|
313
|
+
<a href="https://github.com/elaichenkov"><img src="https://avatars.githubusercontent.com/u/29764053?v=4" title="elaichenkov" width="80" height="80"></a>
|
|
314
|
+
<a href="https://github.com/nitschSB"><img src="https://avatars.githubusercontent.com/u/39341455?v=4" title="nitschSB" width="80" height="80"></a>
|
|
315
|
+
<a href="https://github.com/hubidu"><img src="https://avatars.githubusercontent.com/u/13134082?v=4" title="hubidu" width="80" height="80"></a>
|
|
316
|
+
<a href="https://github.com/jploskonka"><img src="https://avatars.githubusercontent.com/u/669483?v=4" title="jploskonka" width="80" height="80"></a>
|
|
317
|
+
<a href="https://github.com/maojunxyz"><img src="https://avatars.githubusercontent.com/u/28778042?v=4" title="maojunxyz" width="80" height="80"></a>
|
|
318
|
+
<a href="https://github.com/abhimanyupandian"><img src="https://avatars.githubusercontent.com/u/36107381?v=4" title="abhimanyupandian" width="80" height="80"></a>
|
|
319
|
+
<a href="https://github.com/martomo"><img src="https://avatars.githubusercontent.com/u/1850135?v=4" title="martomo" width="80" height="80"></a>
|
|
320
|
+
<a href="https://github.com/denis-sokolov"><img src="https://avatars.githubusercontent.com/u/113721?v=4" title="denis-sokolov" width="80" height="80"></a>
|
|
321
|
+
<a href="https://github.com/lennym"><img src="https://avatars.githubusercontent.com/u/117398?v=4" title="lennym" width="80" height="80"></a>
|
|
322
|
+
<a href="https://github.com/petehouston"><img src="https://avatars.githubusercontent.com/u/9006720?v=4" title="petehouston" width="80" height="80"></a>
|
|
323
|
+
<a href="https://github.com/Holorium"><img src="https://avatars.githubusercontent.com/u/10815542?v=4" title="Holorium" width="80" height="80"></a>
|
|
324
|
+
<a href="https://github.com/jancorvus"><img src="https://avatars.githubusercontent.com/u/67001310?v=4" title="jancorvus" width="80" height="80"></a>
|
|
325
|
+
<a href="https://github.com/ngraf"><img src="https://avatars.githubusercontent.com/u/7094389?v=4" title="ngraf" width="80" height="80"></a>
|
|
327
326
|
|
|
328
327
|
[//]: contributor-faces
|
|
329
328
|
|
package/docs/advanced.md
CHANGED
|
@@ -186,7 +186,7 @@ You can use this options for build your own [plugins](https://codecept.io/hooks/
|
|
|
186
186
|
});
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
## Timeout
|
|
189
|
+
## Timeout
|
|
190
190
|
|
|
191
191
|
Tests can get stuck due to various reasons such as network connection issues, crashed browser, etc.
|
|
192
192
|
This can make tests process hang. To prevent these situations timeouts can be used. Timeouts can be set explicitly for flaky parts of code, or implicitly in a config.
|
|
@@ -236,38 +236,62 @@ A timeout for a group of tests can be set on Feature level via options.
|
|
|
236
236
|
Feature('flaky tests', { timeout: 30 })
|
|
237
237
|
```
|
|
238
238
|
|
|
239
|
-
###
|
|
239
|
+
### Timeout Confguration
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
<Badge text="Updated in 3.4" type="warning"/>
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
Timeout rules can be set globally via config.
|
|
244
|
+
|
|
245
|
+
To set a timeout for all running tests provide a **number of seconds** to `timeout` config option:
|
|
244
246
|
|
|
245
|
-
```js
|
|
246
|
-
// in codecept.confg.js:
|
|
247
|
-
{ // ...
|
|
248
|
-
timeout: 30, // limit all tests in all suites to 30 secs
|
|
249
|
-
|
|
250
|
-
plugins: {
|
|
251
|
-
stepTimeout: {
|
|
252
|
-
enabled: true,
|
|
253
|
-
timeout: 10, // limit all steps except waiters to 10 secs
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
247
|
|
|
248
|
+
```js
|
|
249
|
+
// inside codecept.conf.js or codecept.conf.ts
|
|
250
|
+
timeout: 30, // limit all tests in all suites to 30 secs
|
|
258
251
|
```
|
|
259
252
|
|
|
260
|
-
|
|
253
|
+
It is possible to tune this configuration for a different groups of tests passing options as array and using `grep` option to filter tests:
|
|
261
254
|
|
|
262
255
|
```js
|
|
263
|
-
//
|
|
264
|
-
Feature('tests with timeout', { timeout: 10 });
|
|
256
|
+
// inside codecept.conf.js or codecept.conf.ts
|
|
265
257
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
258
|
+
timeout: [
|
|
259
|
+
10, // default timeout is 10secs
|
|
260
|
+
|
|
261
|
+
// but increase timeout for slow tests
|
|
262
|
+
{
|
|
263
|
+
grep: '@slow',
|
|
264
|
+
Feature: 50
|
|
265
|
+
},
|
|
266
|
+
]
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
> ℹ️ `grep` value can be string or regexp
|
|
270
|
+
|
|
271
|
+
It is possible to set a timeout for Scenario or Feature:
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
// inside codecept.conf.js or codecept.conf.ts
|
|
275
|
+
timeout: [
|
|
276
|
+
|
|
277
|
+
// timeout for Feature with @slow in title
|
|
278
|
+
{
|
|
279
|
+
grep: '@slow',
|
|
280
|
+
Feature: 50
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
// timeout for Scenario with 'flaky0' .. `flaky1` in title
|
|
284
|
+
{
|
|
285
|
+
// regexp can be passed to grep
|
|
286
|
+
grep: /flaky[0-9]/,
|
|
287
|
+
Scenario: 10
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
// timeout for all suites
|
|
291
|
+
{
|
|
292
|
+
Feature: 20
|
|
293
|
+
}
|
|
294
|
+
]
|
|
271
295
|
```
|
|
272
296
|
|
|
273
297
|
Global timeouts will be overridden by explicit timeouts of a test or steps.
|
package/docs/basics.md
CHANGED
|
@@ -345,7 +345,7 @@ If you face that error please make sure that all async functions are called with
|
|
|
345
345
|
|
|
346
346
|
## Running Tests
|
|
347
347
|
|
|
348
|
-
To launch tests use the `run` command, and to execute tests in [multiple
|
|
348
|
+
To launch tests use the `run` command, and to execute tests in [multiple threads](/advanced/parallel) using `run-workers` command.
|
|
349
349
|
|
|
350
350
|
### Level of Detail
|
|
351
351
|
|
|
@@ -394,7 +394,7 @@ It is recommended to [filter tests by tags](/advanced/#tags).
|
|
|
394
394
|
|
|
395
395
|
### Parallel Run
|
|
396
396
|
|
|
397
|
-
|
|
397
|
+
Tests can be executed in parallel mode by using [NodeJS workers](https://nodejs.org/api/worker_threads.html). Use `run-workers` command with the number of workers (threads) to split tests into different workers.
|
|
398
398
|
|
|
399
399
|
```
|
|
400
400
|
npx codeceptjs run-workers 3
|
|
@@ -532,13 +532,55 @@ This can be configured in [screenshotOnFail Plugin](/plugins/#screenshotonfail)
|
|
|
532
532
|
|
|
533
533
|
To see how the test was executed, use [stepByStepReport Plugin](/plugins/#stepbystepreport). It saves a screenshot of each passed step and shows them in a nice slideshow.
|
|
534
534
|
|
|
535
|
+
## Before
|
|
536
|
+
|
|
537
|
+
Common preparation steps like opening a web page or logging in a user, can be placed in the `Before` or `Background` hooks:
|
|
538
|
+
|
|
539
|
+
```js
|
|
540
|
+
Feature('CodeceptJS Demonstration');
|
|
541
|
+
|
|
542
|
+
Before(({ I }) => { // or Background
|
|
543
|
+
I.amOnPage('/documentation');
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
Scenario('test some forms', ({ I }) => {
|
|
547
|
+
I.click('Create User');
|
|
548
|
+
I.see('User is valid');
|
|
549
|
+
I.dontSeeInCurrentUrl('/documentation');
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
Scenario('test title', ({ I }) => {
|
|
553
|
+
I.seeInTitle('Example application');
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Same as `Before` you can use `After` to run teardown for each scenario.
|
|
558
|
+
|
|
559
|
+
## BeforeSuite
|
|
560
|
+
|
|
561
|
+
If you need to run complex a setup before all tests and have to teardown this afterwards, you can use the `BeforeSuite` and `AfterSuite` functions.
|
|
562
|
+
`BeforeSuite` and `AfterSuite` have access to the `I` object, but `BeforeSuite/AfterSuite` don't have any access to the browser, because it's not running at this moment.
|
|
563
|
+
You can use them to execute handlers that will setup your environment. `BeforeSuite/AfterSuite` will work only for the file it was declared in (so you can declare different setups for files)
|
|
564
|
+
|
|
565
|
+
```js
|
|
566
|
+
BeforeSuite(({ I }) => {
|
|
567
|
+
I.syncDown('testfolder');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
AfterSuite(({ I }) => {
|
|
571
|
+
I.syncUp('testfolder');
|
|
572
|
+
I.clearDir('testfolder');
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
535
576
|
## Retries
|
|
536
577
|
|
|
537
578
|
### Auto Retry
|
|
538
579
|
|
|
539
|
-
|
|
580
|
+
Each failed step is auto-retried by default via [retryFailedStep Plugin](/plugins/#retryfailedstep).
|
|
581
|
+
If this is not expected, this plugin can be disabled in a config.
|
|
540
582
|
|
|
541
|
-
> **[retryFailedStep plugin](/plugins/#retryfailedstep) is enabled by default**
|
|
583
|
+
> **[retryFailedStep plugin](/plugins/#retryfailedstep) is enabled by default** incide global configuration
|
|
542
584
|
|
|
543
585
|
### Retry Step
|
|
544
586
|
|
|
@@ -608,69 +650,102 @@ Scenario('Really complex', { retries: 2 },({ I }) => {});
|
|
|
608
650
|
This scenario will be restarted two times on a failure.
|
|
609
651
|
Unlike retry step, there is no `when` condition supported for retries on a scenario level.
|
|
610
652
|
|
|
653
|
+
### Retry Before <Badge text="Since 3.4" type="warning"/>
|
|
654
|
+
|
|
655
|
+
To retry `Before`, `BeforeSuite`, `After`, `AfterSuite` hooks, add corresponding option to a `Feature`:
|
|
656
|
+
|
|
657
|
+
* `retryBefore`
|
|
658
|
+
* `retryBeforeSuite`
|
|
659
|
+
* `retryAfter`
|
|
660
|
+
* `retryAfterSuite`
|
|
661
|
+
|
|
662
|
+
For instance, to retry Before hook 3 times:
|
|
663
|
+
|
|
664
|
+
```js
|
|
665
|
+
Feature('this have a flaky Befure', { retryBefore: 3 })
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
Multiple options of different values can be set at the same time
|
|
669
|
+
|
|
611
670
|
### Retry Feature
|
|
612
671
|
|
|
613
672
|
To set this option for all scenarios in a file, add `retry` to a feature:
|
|
614
673
|
|
|
615
674
|
```js
|
|
616
675
|
Feature('Complex JS Stuff').retry(3);
|
|
676
|
+
// or
|
|
677
|
+
Feature('Complex JS Stuff', { retries: 3 })
|
|
617
678
|
```
|
|
618
679
|
|
|
619
680
|
Every Scenario inside this feature will be rerun 3 times.
|
|
620
681
|
You can make an exception for a specific scenario by passing the `retries` option to a Scenario.
|
|
621
682
|
|
|
622
|
-
### Retry
|
|
623
|
-
|
|
624
|
-
On the highest level of the "retry pyramid" there is an option to retry a complete run multiple times.
|
|
625
|
-
Even this is the slowest option of all, it can be helpful to detect flaky tests.
|
|
683
|
+
### Retry Configuration <Badge text="Since 3.4" type="warning"/>
|
|
626
684
|
|
|
627
|
-
|
|
685
|
+
It is possible to set retry rules globally via `retry` config option. The configuration is flexible and allows multiple formats.
|
|
686
|
+
The simplest config would be:
|
|
628
687
|
|
|
688
|
+
```js
|
|
689
|
+
// inside codecept.conf.js
|
|
690
|
+
retry: 3
|
|
629
691
|
```
|
|
630
|
-
npx codeceptjs run-rerun
|
|
631
|
-
```
|
|
632
|
-
|
|
633
692
|
|
|
634
|
-
|
|
693
|
+
This will enable Feature Retry for all executed feature, retrying failing tests 3 times.
|
|
635
694
|
|
|
636
|
-
|
|
695
|
+
An object can be used to tune retries of a Before/After hook, Scenario or Feature
|
|
637
696
|
|
|
638
697
|
```js
|
|
639
|
-
|
|
698
|
+
// inside codecept.conf.js
|
|
699
|
+
retry: {
|
|
700
|
+
Feature: ...,
|
|
701
|
+
Scenario: ...,
|
|
702
|
+
Before: ...,
|
|
703
|
+
BeforeSuite: ...,
|
|
704
|
+
After: ...,
|
|
705
|
+
AfterSuite: ...,
|
|
706
|
+
}
|
|
707
|
+
```
|
|
640
708
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
709
|
+
Multiple retry configs can be added via array. To use different retry configs for different subset of tests use `grep` option inside a retry config:
|
|
710
|
+
|
|
711
|
+
```js
|
|
712
|
+
// inside codecept.conf.js
|
|
713
|
+
retry: [
|
|
714
|
+
{
|
|
715
|
+
// enable this config only for flaky tests
|
|
716
|
+
grep: '@flaky',
|
|
717
|
+
Before: 3
|
|
718
|
+
Scenario: 3
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
// retry less when running slow tests
|
|
722
|
+
grep: '@slow'
|
|
723
|
+
Scenario: 1
|
|
724
|
+
Before: 1
|
|
725
|
+
}, {
|
|
726
|
+
// retry all BeforeSuite
|
|
727
|
+
BeforeSuite: 3
|
|
728
|
+
}
|
|
729
|
+
]
|
|
730
|
+
```
|
|
644
731
|
|
|
645
|
-
|
|
646
|
-
I.click('Create User');
|
|
647
|
-
I.see('User is valid');
|
|
648
|
-
I.dontSeeInCurrentUrl('/documentation');
|
|
649
|
-
});
|
|
732
|
+
When using `grep` with `Before`, `After`, `BeforeSuite`, `AfterSuite`, a suite title will be checked for included value.
|
|
650
733
|
|
|
651
|
-
|
|
652
|
-
I.seeInTitle('Example application');
|
|
653
|
-
});
|
|
654
|
-
```
|
|
734
|
+
> ℹ️ `grep` value can be string or regexp
|
|
655
735
|
|
|
656
|
-
|
|
736
|
+
Rules are applied in the order of array element, so the last option will override a previous one. Global retries config can be overridden in a file as described previously.
|
|
657
737
|
|
|
658
|
-
|
|
738
|
+
### Retry Run
|
|
659
739
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
You can use them to execute handlers that will setup your environment. `BeforeSuite/AfterSuite` will work only for the file it was declared in (so you can declare different setups for files)
|
|
740
|
+
On the highest level of the "retry pyramid" there is an option to retry a complete run multiple times.
|
|
741
|
+
Even this is the slowest option of all, it can be helpful to detect flaky tests.
|
|
663
742
|
|
|
664
|
-
|
|
665
|
-
BeforeSuite(({ I }) => {
|
|
666
|
-
I.syncDown('testfolder');
|
|
667
|
-
});
|
|
743
|
+
[`run-rerun`](https://codecept.io/commands/#run-rerun) command will restart the run multiple times to values you provide. You can set minimal and maximal number of restarts in configuration file.
|
|
668
744
|
|
|
669
|
-
AfterSuite(({ I }) => {
|
|
670
|
-
I.syncUp('testfolder');
|
|
671
|
-
I.clearDir('testfolder');
|
|
672
|
-
});
|
|
673
745
|
```
|
|
746
|
+
npx codeceptjs run-rerun
|
|
747
|
+
```
|
|
748
|
+
|
|
674
749
|
|
|
675
750
|
[Here are some ideas](https://github.com/codeceptjs/CodeceptJS/pull/231#issuecomment-249554933) on where to use BeforeSuite hooks.
|
|
676
751
|
|
package/docs/best.md
CHANGED
|
@@ -74,7 +74,7 @@ When a project is growing and more and more tests are required, it's time to thi
|
|
|
74
74
|
Here is a recommended strategy what to store where:
|
|
75
75
|
|
|
76
76
|
* Move site-wide actions into an **Actor** file (`custom_steps.js` file). Such actions like `login`, using site-wide common controls, like drop-downs, rich text editors, calendars.
|
|
77
|
-
* Move page-based actions and selectors into **Page Object**. All
|
|
77
|
+
* Move page-based actions and selectors into **Page Object**. All activities made on that page can go into methods of page object. If you test Single Page Application a PageObject should represent a screen of your application.
|
|
78
78
|
* When site-wide widgets are used, interactions with them should be placed in **Page Fragments**. This should be applied to global navigation, modals, widgets.
|
|
79
79
|
* A custom action that requires some low-level driver access, should be placed into a **Helper**. For instance, database connections, complex mouse actions, email testing, filesystem, services access.
|
|
80
80
|
|
|
@@ -215,7 +215,7 @@ include: {
|
|
|
215
215
|
* When you need to customize access to API and go beyond what ApiDataFactory provides, implement DAO:
|
|
216
216
|
|
|
217
217
|
```js
|
|
218
|
-
const faker = require('@faker-js/faker');
|
|
218
|
+
const { faker } = require('@faker-js/faker');
|
|
219
219
|
const { I } = inject();
|
|
220
220
|
const { output } = require('codeceptjs');
|
|
221
221
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
-
const Helper = require('
|
|
3
|
+
const Helper = require('@codeceptjs/helper');
|
|
4
4
|
const REST = require('./REST');
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -46,8 +46,8 @@ const REST = require('./REST');
|
|
|
46
46
|
* ```js
|
|
47
47
|
* // tests/factories/posts.js
|
|
48
48
|
*
|
|
49
|
-
* const Factory = require('rosie')
|
|
50
|
-
* const faker = require('@faker-js/faker');
|
|
49
|
+
* const { Factory } = require('rosie');
|
|
50
|
+
* const { faker } = require('@faker-js/faker');
|
|
51
51
|
*
|
|
52
52
|
* module.exports = new Factory()
|
|
53
53
|
* // no need to set id, it will be set by REST API
|
|
@@ -230,7 +230,7 @@ class ApiDataFactory extends Helper {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
_after() {
|
|
233
|
-
if (!this.config.cleanup) {
|
|
233
|
+
if (!this.config.cleanup || this.config.cleanup === false) {
|
|
234
234
|
return Promise.resolve();
|
|
235
235
|
}
|
|
236
236
|
const promises = [];
|
|
@@ -244,7 +244,6 @@ class ApiDataFactory extends Helper {
|
|
|
244
244
|
promises.push(this._requestDelete(factoryName, createdItems[id]));
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
-
|
|
248
247
|
return Promise.all(promises);
|
|
249
248
|
}
|
|
250
249
|
|
|
@@ -262,8 +261,8 @@ class ApiDataFactory extends Helper {
|
|
|
262
261
|
* ```
|
|
263
262
|
*
|
|
264
263
|
* @param {*} factory factory to use
|
|
265
|
-
* @param {*} params predefined parameters
|
|
266
|
-
* @param {*} options options for programmatically generate the attributes
|
|
264
|
+
* @param {*} [params] predefined parameters
|
|
265
|
+
* @param {*} [options] options for programmatically generate the attributes
|
|
267
266
|
* @returns {Promise<*>}
|
|
268
267
|
*/
|
|
269
268
|
have(factory, params, options) {
|
|
@@ -288,8 +287,8 @@ class ApiDataFactory extends Helper {
|
|
|
288
287
|
*
|
|
289
288
|
* @param {*} factory
|
|
290
289
|
* @param {*} times
|
|
291
|
-
* @param {*} params
|
|
292
|
-
* @param {*} options
|
|
290
|
+
* @param {*} [params]
|
|
291
|
+
* @param {*} [options]
|
|
293
292
|
*/
|
|
294
293
|
haveMultiple(factory, times, params, options) {
|
|
295
294
|
const promises = [];
|
|
@@ -379,7 +378,9 @@ Current file error: ${err.message}`);
|
|
|
379
378
|
|
|
380
379
|
if (!request) {
|
|
381
380
|
const method = Object.keys(this.factories[factory].delete)[0];
|
|
381
|
+
|
|
382
382
|
const url = this.factories[factory].delete[method].replace('{id}', id);
|
|
383
|
+
|
|
383
384
|
request = {
|
|
384
385
|
method,
|
|
385
386
|
url,
|
|
@@ -388,6 +389,10 @@ Current file error: ${err.message}`);
|
|
|
388
389
|
|
|
389
390
|
request.baseURL = this.config.endpoint;
|
|
390
391
|
|
|
392
|
+
if (request.url.match(/^undefined/)) {
|
|
393
|
+
return this.debugSection('Please configure the delete request in your ApiDataFactory helper', 'delete: () => ({ method: \'DELETE\', url: \'/api/users\' })');
|
|
394
|
+
}
|
|
395
|
+
|
|
391
396
|
return this.restHelper._executeRequest(request).then(() => {
|
|
392
397
|
const idx = this.created[factory].indexOf(id);
|
|
393
398
|
this.debugSection('Deleted Id', `Id: ${id}`);
|
package/docs/build/Appium.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
let webdriverio;
|
|
2
|
-
let wdioV4;
|
|
3
2
|
|
|
4
3
|
const fs = require('fs');
|
|
5
4
|
const axios = require('axios').default;
|
|
@@ -131,6 +130,7 @@ class Appium extends Webdriver {
|
|
|
131
130
|
* @augments WebDriver
|
|
132
131
|
*/
|
|
133
132
|
|
|
133
|
+
// @ts-ignore
|
|
134
134
|
constructor(config) {
|
|
135
135
|
super(config);
|
|
136
136
|
|
|
@@ -138,7 +138,6 @@ class Appium extends Webdriver {
|
|
|
138
138
|
this.axios = axios.create();
|
|
139
139
|
|
|
140
140
|
webdriverio = require('webdriverio');
|
|
141
|
-
(!webdriverio.VERSION || webdriverio.VERSION.indexOf('4') !== 0) ? wdioV4 = false : wdioV4 = true;
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
_validateConfig(config) {
|
|
@@ -516,10 +515,6 @@ class Appium extends Webdriver {
|
|
|
516
515
|
async removeApp(appId, bundleId) {
|
|
517
516
|
onlyForApps.call(this, supportedPlatform.android);
|
|
518
517
|
|
|
519
|
-
if (wdioV4) {
|
|
520
|
-
return this.browser.removeApp(bundleId);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
518
|
return this.axios({
|
|
524
519
|
method: 'post',
|
|
525
520
|
url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
|
|
@@ -610,19 +605,13 @@ class Appium extends Webdriver {
|
|
|
610
605
|
*/
|
|
611
606
|
async seeOrientationIs(orientation) {
|
|
612
607
|
onlyForApps.call(this);
|
|
613
|
-
let currentOrientation;
|
|
614
|
-
|
|
615
|
-
if (wdioV4) {
|
|
616
|
-
const res = await this.browser.orientation();
|
|
617
|
-
currentOrientation = res;
|
|
618
|
-
}
|
|
619
608
|
|
|
620
609
|
const res = await this.axios({
|
|
621
610
|
method: 'get',
|
|
622
611
|
url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
|
|
623
612
|
});
|
|
624
613
|
|
|
625
|
-
currentOrientation = res.data.value;
|
|
614
|
+
const currentOrientation = res.data.value;
|
|
626
615
|
return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation);
|
|
627
616
|
}
|
|
628
617
|
|
|
@@ -640,9 +629,6 @@ class Appium extends Webdriver {
|
|
|
640
629
|
*/
|
|
641
630
|
async setOrientation(orientation) {
|
|
642
631
|
onlyForApps.call(this);
|
|
643
|
-
if (wdioV4) {
|
|
644
|
-
return this.browser.setOrientation(orientation);
|
|
645
|
-
}
|
|
646
632
|
|
|
647
633
|
return this.axios({
|
|
648
634
|
method: 'post',
|
|
@@ -916,9 +902,6 @@ class Appium extends Webdriver {
|
|
|
916
902
|
*/
|
|
917
903
|
async sendDeviceKeyEvent(keyValue) {
|
|
918
904
|
onlyForApps.call(this, supportedPlatform.android);
|
|
919
|
-
if (wdioV4) {
|
|
920
|
-
return this.browser.sendKeyEvent(keyValue);
|
|
921
|
-
}
|
|
922
905
|
return this.browser.pressKeyCode(keyValue);
|
|
923
906
|
}
|
|
924
907
|
|
package/docs/build/FileSystem.js
CHANGED
|
@@ -2,7 +2,7 @@ const assert = require('assert');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
|
|
5
|
-
const Helper = require('
|
|
5
|
+
const Helper = require('@codeceptjs/helper');
|
|
6
6
|
const { fileExists } = require('../utils');
|
|
7
7
|
const { fileIncludes } = require('../assert/include');
|
|
8
8
|
const { fileEquals } = require('../assert/equal');
|
|
@@ -71,10 +71,10 @@ class FileSystem extends Helper {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
* Waits for file to be present in current directory.
|
|
74
|
+
* Waits for the file to be present in the current directory.
|
|
75
75
|
*
|
|
76
76
|
* ```js
|
|
77
|
-
* I.handleDownloads();
|
|
77
|
+
* I.handleDownloads('downloads/largeFilesName.txt');
|
|
78
78
|
* I.click('Download large File');
|
|
79
79
|
* I.amInPath('output/downloads');
|
|
80
80
|
* I.waitForFile('largeFilesName.txt', 10); // wait 10 seconds for file
|
package/docs/build/GraphQL.js
CHANGED