codeceptjs 3.4.0-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/docs/build/ApiDataFactory.js +8 -3
- package/docs/build/FileSystem.js +1 -1
- package/docs/build/GraphQL.js +1 -1
- package/docs/build/GraphQLDataFactory.js +1 -1
- 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 +1 -1
- 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 +1 -1
- package/docs/build/WebDriver.js +1 -1
- package/docs/changelog.md +49 -2
- package/docs/plugins.md +42 -150
- package/docs/tutorial.md +271 -0
- package/lib/helper/ApiDataFactory.js +7 -2
- package/package.json +2 -2
- package/typings/index.d.ts +12 -2
|
@@ -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
|
/**
|
|
@@ -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
|
|
|
@@ -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/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');
|
package/docs/build/GraphQL.js
CHANGED
package/docs/build/Nightmare.js
CHANGED
|
@@ -2,7 +2,7 @@ const path = require('path');
|
|
|
2
2
|
|
|
3
3
|
const urlResolve = require('url').resolve;
|
|
4
4
|
|
|
5
|
-
const Helper = require('
|
|
5
|
+
const Helper = require('@codeceptjs/helper');
|
|
6
6
|
const { includes: stringIncludes } = require('../assert/include');
|
|
7
7
|
const { urlEquals } = require('../assert/equal');
|
|
8
8
|
const { equals } = require('../assert/equal');
|
package/docs/build/Playwright.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
|
|
4
|
-
const Helper = require('
|
|
4
|
+
const Helper = require('@codeceptjs/helper');
|
|
5
5
|
const Locator = require('../locator');
|
|
6
6
|
const recorder = require('../recorder');
|
|
7
7
|
const stringIncludes = require('../assert/include').includes;
|
package/docs/build/Protractor.js
CHANGED
|
@@ -6,7 +6,7 @@ let ProtractorExpectedConditions;
|
|
|
6
6
|
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
|
-
const Helper = require('
|
|
9
|
+
const Helper = require('@codeceptjs/helper');
|
|
10
10
|
const stringIncludes = require('../assert/include').includes;
|
|
11
11
|
const { urlEquals, equals } = require('../assert/equal');
|
|
12
12
|
const { empty } = require('../assert/empty');
|
package/docs/build/Puppeteer.js
CHANGED
|
@@ -3,7 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const fsExtra = require('fs-extra');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
-
const Helper = require('
|
|
6
|
+
const Helper = require('@codeceptjs/helper');
|
|
7
7
|
const Locator = require('../locator');
|
|
8
8
|
const recorder = require('../recorder');
|
|
9
9
|
const stringIncludes = require('../assert/include').includes;
|
package/docs/build/REST.js
CHANGED
package/docs/build/TestCafe.js
CHANGED
|
@@ -6,6 +6,7 @@ const qrcode = require('qrcode-terminal');
|
|
|
6
6
|
const createTestCafe = require('testcafe');
|
|
7
7
|
const { Selector, ClientFunction } = require('testcafe');
|
|
8
8
|
|
|
9
|
+
const Helper = require('@codeceptjs/helper');
|
|
9
10
|
const ElementNotFound = require('./errors/ElementNotFound');
|
|
10
11
|
const testControllerHolder = require('./testcafe/testControllerHolder');
|
|
11
12
|
const {
|
|
@@ -22,7 +23,6 @@ const {
|
|
|
22
23
|
xpathLocator,
|
|
23
24
|
} = require('../utils');
|
|
24
25
|
const Locator = require('../locator');
|
|
25
|
-
const Helper = require('../helper');
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Client Functions
|
package/docs/build/WebDriver.js
CHANGED
|
@@ -4,7 +4,7 @@ const assert = require('assert');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
|
|
7
|
-
const Helper = require('
|
|
7
|
+
const Helper = require('@codeceptjs/helper');
|
|
8
8
|
const stringIncludes = require('../assert/include').includes;
|
|
9
9
|
const { urlEquals, equals } = require('../assert/equal');
|
|
10
10
|
const { debug } = require('../output');
|
package/docs/changelog.md
CHANGED
|
@@ -7,6 +7,53 @@ layout: Section
|
|
|
7
7
|
|
|
8
8
|
# Releases
|
|
9
9
|
|
|
10
|
+
## 3.4.0
|
|
11
|
+
|
|
12
|
+
* **Updated to latest mocha and modern Cucumber**
|
|
13
|
+
* **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](https://github.com/codeceptjs/CodeceptJS/issues/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.
|
|
14
|
+
* Added ability to **[retry Before](https://codecept.io/basics/#retry-before), BeforeSuite, After, AfterSuite** hooks by **[davertmik](https://github.com/davertmik)**:
|
|
15
|
+
```js
|
|
16
|
+
Feature('flaky Before & BeforeSuite', { retryBefore: 2, retryBeforeSuite: 3 })
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
* **Flexible [retries configuration](https://codecept.io/basics/#retry-configuration) introduced** by **[davertmik](https://github.com/davertmik)**:
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
retry: [
|
|
23
|
+
{
|
|
24
|
+
// enable this config only for flaky tests
|
|
25
|
+
grep: '@flaky',
|
|
26
|
+
Before: 3 // retry Before 3 times
|
|
27
|
+
Scenario: 3 // retry Scenario 3 times
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// retry less when running slow tests
|
|
31
|
+
grep: '@slow'
|
|
32
|
+
Scenario: 1
|
|
33
|
+
Before: 1
|
|
34
|
+
}, {
|
|
35
|
+
// retry all BeforeSuite 3 times
|
|
36
|
+
BeforeSuite: 3
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
```
|
|
40
|
+
* **Flexible [timeout configuration](https://codecept.io/advanced/#timeout-configuration)** introduced by **[davertmik](https://github.com/davertmik)**:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
timeout: [
|
|
44
|
+
10, // default timeout is 10secs
|
|
45
|
+
{ // but increase timeout for slow tests
|
|
46
|
+
grep: '@slow',
|
|
47
|
+
Feature: 50
|
|
48
|
+
},
|
|
49
|
+
]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
* JsDoc: Removed promise from `I.say`. See [#3535](https://github.com/codeceptjs/CodeceptJS/issues/3535) by **[danielrentz](https://github.com/danielrentz)**
|
|
53
|
+
* **[Playwright]** `handleDownloads` requires now a filename param. See [#3511](https://github.com/codeceptjs/CodeceptJS/issues/3511) by **[PeterNgTr](https://github.com/PeterNgTr)**
|
|
54
|
+
* **[WebDriver]** Added support for v8, removed support for webdriverio v5 and lower. See [#3578](https://github.com/codeceptjs/CodeceptJS/issues/3578) by **[PeterNgTr](https://github.com/PeterNgTr)**
|
|
55
|
+
|
|
56
|
+
|
|
10
57
|
## 3.3.7
|
|
11
58
|
|
|
12
59
|
🛩️ Features
|
|
@@ -37,8 +84,8 @@ layout: Section
|
|
|
37
84
|
|
|
38
85
|
📖 Documentation
|
|
39
86
|
|
|
40
|
-
* Updated [
|
|
41
|
-
* Added [Translation](/
|
|
87
|
+
* Updated [Quickstart](https://codecept.io/quickstart/) with detailed explanation of questions in init
|
|
88
|
+
* Added [Translation](/translation/) guide
|
|
42
89
|
* Updated [TypeScript](https://bit.ly/3XIMq6n) guide for promise-based typings
|
|
43
90
|
* Reordered guides list on a website
|
|
44
91
|
|
package/docs/plugins.md
CHANGED
|
@@ -7,98 +7,6 @@ title: Plugins
|
|
|
7
7
|
|
|
8
8
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
9
9
|
|
|
10
|
-
## allure
|
|
11
|
-
|
|
12
|
-
Allure reporter
|
|
13
|
-
|
|
14
|
-
> ⚠️ This plugin was moved to its [own package][1]
|
|
15
|
-
|
|
16
|
-
![][2]
|
|
17
|
-
|
|
18
|
-
Enables Allure reporter.
|
|
19
|
-
|
|
20
|
-
#### Usage
|
|
21
|
-
|
|
22
|
-
To start please install `allure-commandline` package (which requires Java 8)
|
|
23
|
-
|
|
24
|
-
npm install -g allure-commandline --save-dev
|
|
25
|
-
|
|
26
|
-
Add this plugin to config file:
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
"plugins": {
|
|
30
|
-
"allure": {}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Run tests with allure plugin enabled:
|
|
35
|
-
|
|
36
|
-
npx codeceptjs run --plugins allure
|
|
37
|
-
|
|
38
|
-
By default, allure reports are saved to `output` directory.
|
|
39
|
-
Launch Allure server and see the report like on a screenshot above:
|
|
40
|
-
|
|
41
|
-
allure serve output
|
|
42
|
-
|
|
43
|
-
#### Configuration
|
|
44
|
-
|
|
45
|
-
- `outputDir` - a directory where allure reports should be stored. Standard output directory is set by default.
|
|
46
|
-
- `enableScreenshotDiffPlugin` - a boolean flag for add screenshot diff to report.
|
|
47
|
-
To attach, tou need to attach three files to the report - "diff.png", "actual.png", "expected.png".
|
|
48
|
-
See [Allure Screenshot Plugin][3]
|
|
49
|
-
|
|
50
|
-
#### Public API
|
|
51
|
-
|
|
52
|
-
There are few public API methods which can be accessed from other plugins.
|
|
53
|
-
|
|
54
|
-
```js
|
|
55
|
-
const allure = codeceptjs.container.plugins('allure');
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
`allure` object has following methods:
|
|
59
|
-
|
|
60
|
-
- `addAttachment(name, buffer, type)` - add an attachment to current test / suite
|
|
61
|
-
- `addLabel(name, value)` - adds a label to current test
|
|
62
|
-
- `addParameter(kind, name, value)` - adds a parameter to current test
|
|
63
|
-
- `createStep(name, stepFunc)` - create a step, stepFunc could consist an attachment
|
|
64
|
-
Example of usage:
|
|
65
|
-
|
|
66
|
-
```js
|
|
67
|
-
allure.createStep('New created step', () => {
|
|
68
|
-
allure.addAttachment(
|
|
69
|
-
'Request params',
|
|
70
|
-
'{"clientId":123, "name":"Tom", "age":29}',
|
|
71
|
-
'application/json'
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
![Created Step Image][4]
|
|
77
|
-
|
|
78
|
-
- `addScreenDiff(name, expectedImg, actualImg, diffImg)` - add a special screen diff block to the current test case
|
|
79
|
-
image must be a string representing the contents of the expected image file encoded in base64
|
|
80
|
-
Example of usage:
|
|
81
|
-
|
|
82
|
-
```js
|
|
83
|
-
const expectedImg = fs.readFileSync('expectedImg.png', { encoding: 'base64' });
|
|
84
|
-
...
|
|
85
|
-
allure.addScreenDiff('Screen Diff', expectedImg, actualImg, diffImg);
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
![Overlay][5]
|
|
89
|
-
![Diff][6]
|
|
90
|
-
|
|
91
|
-
- `severity(value)` - adds severity label
|
|
92
|
-
- `epic(value)` - adds epic label
|
|
93
|
-
- `feature(value)` - adds feature label
|
|
94
|
-
- `story(value)` - adds story label
|
|
95
|
-
- `issue(value)` - adds issue label
|
|
96
|
-
- `setDescription(description, type)` - sets a description
|
|
97
|
-
|
|
98
|
-
### Parameters
|
|
99
|
-
|
|
100
|
-
- `config`
|
|
101
|
-
|
|
102
10
|
## autoDelay
|
|
103
11
|
|
|
104
12
|
Sometimes it takes some time for a page to respond to user's actions.
|
|
@@ -464,7 +372,7 @@ Possible config options:
|
|
|
464
372
|
|
|
465
373
|
## customLocator
|
|
466
374
|
|
|
467
|
-
Creates a [custom locator][
|
|
375
|
+
Creates a [custom locator][1] by using special attributes in HTML.
|
|
468
376
|
|
|
469
377
|
If you have a convention to use `data-test-id` or `data-qa` attributes to mark active elements for e2e tests,
|
|
470
378
|
you can enable this plugin to simplify matching elements with these attributes:
|
|
@@ -614,9 +522,9 @@ This method works with WebDriver, Playwright, Puppeteer, Appium helpers.
|
|
|
614
522
|
Function parameter `el` represents a matched element.
|
|
615
523
|
Depending on a helper API of `el` can be different. Refer to API of corresponding browser testing engine for a complete API list:
|
|
616
524
|
|
|
617
|
-
- [Playwright ElementHandle][
|
|
618
|
-
- [Puppeteer][
|
|
619
|
-
- [webdriverio element][
|
|
525
|
+
- [Playwright ElementHandle][2]
|
|
526
|
+
- [Puppeteer][3]
|
|
527
|
+
- [webdriverio element][4]
|
|
620
528
|
|
|
621
529
|
#### Configuration
|
|
622
530
|
|
|
@@ -630,17 +538,17 @@ const eachElement = codeceptjs.container.plugins('eachElement');
|
|
|
630
538
|
|
|
631
539
|
### Parameters
|
|
632
540
|
|
|
633
|
-
- `purpose` **[string][
|
|
541
|
+
- `purpose` **[string][5]**
|
|
634
542
|
- `locator` **CodeceptJS.LocatorOrString**
|
|
635
|
-
- `fn` **[Function][
|
|
543
|
+
- `fn` **[Function][6]**
|
|
636
544
|
|
|
637
|
-
Returns **([Promise][
|
|
545
|
+
Returns **([Promise][7]<any> | [undefined][8])**
|
|
638
546
|
|
|
639
547
|
## fakerTransform
|
|
640
548
|
|
|
641
|
-
Use the [faker.js][
|
|
549
|
+
Use the [faker.js][9] package to generate fake data inside examples on your gherkin tests
|
|
642
550
|
|
|
643
|
-
![Faker.js][
|
|
551
|
+
![Faker.js][10]
|
|
644
552
|
|
|
645
553
|
#### Usage
|
|
646
554
|
|
|
@@ -678,7 +586,7 @@ Scenario Outline: ...
|
|
|
678
586
|
|
|
679
587
|
## pauseOnFail
|
|
680
588
|
|
|
681
|
-
Automatically launches [interactive pause][
|
|
589
|
+
Automatically launches [interactive pause][11] when a test fails.
|
|
682
590
|
|
|
683
591
|
Useful for debugging flaky tests on local environment.
|
|
684
592
|
Add this plugin to config file:
|
|
@@ -694,10 +602,6 @@ Enable it manually on each run via `-p` option:
|
|
|
694
602
|
|
|
695
603
|
npx codeceptjs run -p pauseOnFail
|
|
696
604
|
|
|
697
|
-
## reporter
|
|
698
|
-
|
|
699
|
-
Type: Allure
|
|
700
|
-
|
|
701
605
|
## retryFailedStep
|
|
702
606
|
|
|
703
607
|
Retries each failed step in a test.
|
|
@@ -865,14 +769,14 @@ Possible config options:
|
|
|
865
769
|
|
|
866
770
|
## selenoid
|
|
867
771
|
|
|
868
|
-
[Selenoid][
|
|
772
|
+
[Selenoid][12] plugin automatically starts browsers and video recording.
|
|
869
773
|
Works with WebDriver helper.
|
|
870
774
|
|
|
871
775
|
### Prerequisite
|
|
872
776
|
|
|
873
777
|
This plugin **requires Docker** to be installed.
|
|
874
778
|
|
|
875
|
-
> If you have issues starting Selenoid with this plugin consider using the official [Configuration Manager][
|
|
779
|
+
> If you have issues starting Selenoid with this plugin consider using the official [Configuration Manager][13] tool from Selenoid
|
|
876
780
|
|
|
877
781
|
### Usage
|
|
878
782
|
|
|
@@ -901,7 +805,7 @@ plugins: {
|
|
|
901
805
|
}
|
|
902
806
|
```
|
|
903
807
|
|
|
904
|
-
When `autoCreate` is enabled it will pull the [latest Selenoid from DockerHub][
|
|
808
|
+
When `autoCreate` is enabled it will pull the [latest Selenoid from DockerHub][14] and start Selenoid automatically.
|
|
905
809
|
It will also create `browsers.json` file required by Selenoid.
|
|
906
810
|
|
|
907
811
|
In automatic mode the latest version of browser will be used for tests. It is recommended to specify exact version of each browser inside `browsers.json` file.
|
|
@@ -913,10 +817,10 @@ In automatic mode the latest version of browser will be used for tests. It is re
|
|
|
913
817
|
While this plugin can create containers for you for better control it is recommended to create and launch containers manually.
|
|
914
818
|
This is especially useful for Continous Integration server as you can configure scaling for Selenoid containers.
|
|
915
819
|
|
|
916
|
-
> Use [Selenoid Configuration Manager][
|
|
820
|
+
> Use [Selenoid Configuration Manager][13] to create and start containers semi-automatically.
|
|
917
821
|
|
|
918
822
|
1. Create `browsers.json` file in the same directory `codecept.conf.js` is located
|
|
919
|
-
[Refer to Selenoid documentation][
|
|
823
|
+
[Refer to Selenoid documentation][15] to know more about browsers.json.
|
|
920
824
|
|
|
921
825
|
_Sample browsers.json_
|
|
922
826
|
|
|
@@ -941,7 +845,7 @@ _Sample browsers.json_
|
|
|
941
845
|
|
|
942
846
|
2. Create Selenoid container
|
|
943
847
|
|
|
944
|
-
Run the following command to create a container. To know more [refer here][
|
|
848
|
+
Run the following command to create a container. To know more [refer here][16]
|
|
945
849
|
|
|
946
850
|
```bash
|
|
947
851
|
docker create \
|
|
@@ -974,7 +878,7 @@ When `allure` plugin is enabled a video is attached to report automatically.
|
|
|
974
878
|
| enableVideo | Enable video recording and use `video` folder of output (default: false) |
|
|
975
879
|
| enableLog | Enable log recording and use `logs` folder of output (default: false) |
|
|
976
880
|
| deletePassed | Delete video and logs of passed tests (default : true) |
|
|
977
|
-
| additionalParams | example: `additionalParams: '--env TEST=test'` [Refer here][
|
|
881
|
+
| additionalParams | example: `additionalParams: '--env TEST=test'` [Refer here][17] to know more |
|
|
978
882
|
|
|
979
883
|
### Parameters
|
|
980
884
|
|
|
@@ -982,7 +886,7 @@ When `allure` plugin is enabled a video is attached to report automatically.
|
|
|
982
886
|
|
|
983
887
|
## stepByStepReport
|
|
984
888
|
|
|
985
|
-
![step-by-step-report][
|
|
889
|
+
![step-by-step-report][18]
|
|
986
890
|
|
|
987
891
|
Generates step by step report for a test.
|
|
988
892
|
After each step in a test a screenshot is created. After test executed screenshots are combined into slideshow.
|
|
@@ -1163,7 +1067,7 @@ This plugin allows to run webdriverio services like:
|
|
|
1163
1067
|
- browserstack
|
|
1164
1068
|
- appium
|
|
1165
1069
|
|
|
1166
|
-
A complete list of all available services can be found on [webdriverio website][
|
|
1070
|
+
A complete list of all available services can be found on [webdriverio website][19].
|
|
1167
1071
|
|
|
1168
1072
|
#### Setup
|
|
1169
1073
|
|
|
@@ -1175,7 +1079,7 @@ See examples below:
|
|
|
1175
1079
|
|
|
1176
1080
|
#### Selenium Standalone Service
|
|
1177
1081
|
|
|
1178
|
-
Install `@wdio/selenium-standalone-service` package, as [described here][
|
|
1082
|
+
Install `@wdio/selenium-standalone-service` package, as [described here][20].
|
|
1179
1083
|
It is important to make sure it is compatible with current webdriverio version.
|
|
1180
1084
|
|
|
1181
1085
|
Enable `wdio` plugin in plugins list and add `selenium-standalone` service:
|
|
@@ -1194,7 +1098,7 @@ Please note, this service can be used with Protractor helper as well!
|
|
|
1194
1098
|
|
|
1195
1099
|
#### Sauce Service
|
|
1196
1100
|
|
|
1197
|
-
Install `@wdio/sauce-service` package, as [described here][
|
|
1101
|
+
Install `@wdio/sauce-service` package, as [described here][21].
|
|
1198
1102
|
It is important to make sure it is compatible with current webdriverio version.
|
|
1199
1103
|
|
|
1200
1104
|
Enable `wdio` plugin in plugins list and add `sauce` service:
|
|
@@ -1224,56 +1128,44 @@ In the same manner additional services from webdriverio can be installed, enable
|
|
|
1224
1128
|
|
|
1225
1129
|
- `config`
|
|
1226
1130
|
|
|
1227
|
-
[1]: https://
|
|
1228
|
-
|
|
1229
|
-
[2]: https://user-images.githubusercontent.com/220264/45676511-8e052800-bb3a-11e8-8cbb-db5f73de2add.png
|
|
1230
|
-
|
|
1231
|
-
[3]: https://github.com/allure-framework/allure2/blob/master/plugins/screen-diff-plugin/README.md
|
|
1232
|
-
|
|
1233
|
-
[4]: https://user-images.githubusercontent.com/63167966/139339384-e6e70a62-3638-406d-a224-f32473071428.png
|
|
1234
|
-
|
|
1235
|
-
[5]: https://user-images.githubusercontent.com/63167966/215404458-9a325668-819e-4289-9b42-5807c49ebddb.png
|
|
1236
|
-
|
|
1237
|
-
[6]: https://user-images.githubusercontent.com/63167966/215404645-73b09da0-9e6d-4352-a123-80c22f7014cd.png
|
|
1238
|
-
|
|
1239
|
-
[7]: https://codecept.io/locators#custom-locators
|
|
1131
|
+
[1]: https://codecept.io/locators#custom-locators
|
|
1240
1132
|
|
|
1241
|
-
[
|
|
1133
|
+
[2]: https://playwright.dev/docs/api/class-elementhandle
|
|
1242
1134
|
|
|
1243
|
-
[
|
|
1135
|
+
[3]: https://pptr.dev/#?product=Puppeteer&show=api-class-elementhandle
|
|
1244
1136
|
|
|
1245
|
-
[
|
|
1137
|
+
[4]: https://webdriver.io/docs/api
|
|
1246
1138
|
|
|
1247
|
-
[
|
|
1139
|
+
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
|
1248
1140
|
|
|
1249
|
-
[
|
|
1141
|
+
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
|
|
1250
1142
|
|
|
1251
|
-
[
|
|
1143
|
+
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
1252
1144
|
|
|
1253
|
-
[
|
|
1145
|
+
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined
|
|
1254
1146
|
|
|
1255
|
-
[
|
|
1147
|
+
[9]: https://www.npmjs.com/package/faker
|
|
1256
1148
|
|
|
1257
|
-
[
|
|
1149
|
+
[10]: https://raw.githubusercontent.com/Marak/faker.js/master/logo.png
|
|
1258
1150
|
|
|
1259
|
-
[
|
|
1151
|
+
[11]: /basics/#pause
|
|
1260
1152
|
|
|
1261
|
-
[
|
|
1153
|
+
[12]: https://aerokube.com/selenoid/
|
|
1262
1154
|
|
|
1263
|
-
[
|
|
1155
|
+
[13]: https://aerokube.com/cm/latest/
|
|
1264
1156
|
|
|
1265
|
-
[
|
|
1157
|
+
[14]: https://hub.docker.com/u/selenoid
|
|
1266
1158
|
|
|
1267
|
-
[
|
|
1159
|
+
[15]: https://aerokube.com/selenoid/latest/#_prepare_configuration
|
|
1268
1160
|
|
|
1269
|
-
[
|
|
1161
|
+
[16]: https://aerokube.com/selenoid/latest/#_option_2_start_selenoid_container
|
|
1270
1162
|
|
|
1271
|
-
[
|
|
1163
|
+
[17]: https://docs.docker.com/engine/reference/commandline/create/
|
|
1272
1164
|
|
|
1273
|
-
[
|
|
1165
|
+
[18]: https://codecept.io/img/codeceptjs-slideshow.gif
|
|
1274
1166
|
|
|
1275
|
-
[
|
|
1167
|
+
[19]: https://webdriver.io
|
|
1276
1168
|
|
|
1277
|
-
[
|
|
1169
|
+
[20]: https://webdriver.io/docs/selenium-standalone-service.html
|
|
1278
1170
|
|
|
1279
|
-
[
|
|
1171
|
+
[21]: https://webdriver.io/docs/sauce-service.html
|
package/docs/tutorial.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /tutorial
|
|
3
|
+
title: CoeceptJS Complete Tutorial
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
**[CodeceptJS](https://codecept.io) is a popular open-source testing framework** for JavaScript. It is designed to simplify writing and maintain end-to-end tests for web applications, using a readable and intuitive syntax. To run tests in browser it uses **[Playwright](https://playwright.dev)** library from Microsoft.
|
|
7
|
+
|
|
8
|
+
CodeceptJS was started in 2015 and is widely used by organizations of all sizes, from startups to large enterprises.
|
|
9
|
+
|
|
10
|
+
## Let's get CodeceptJS installed!
|
|
11
|
+
|
|
12
|
+
To install CodeceptJS, you will need to have Node.js and npm (the Node.js package manager) installed on your system. You can check if you already have these tools installed by running the following commands in a terminal:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node --version
|
|
16
|
+
npm --version
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If either of these commands return an error, you will need to install Node.js and npm before you can install CodeceptJS. You can download and install the latest version of Node.js from the official website, which includes npm.
|
|
20
|
+
|
|
21
|
+
To install CodeceptJS create a new folder and run command form terminal:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
npx create-codeceptjs .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If you run the npx create-codeceptjs . command, it will install CodeceptJS with Playwright in the current directory.
|
|
28
|
+
|
|
29
|
+
> The `npx` command is a tool that comes with npm (the Node.js package manager) and it allows you to run npm packages without having to install them globally on your system.
|
|
30
|
+
|
|
31
|
+
It may take some time as it downloads browsers: Chrome, Firefox and Safari and creates a demo project.
|
|
32
|
+
|
|
33
|
+
But we are here to write a checkout test, right?
|
|
34
|
+
|
|
35
|
+
Let's initialize a new project for that!
|
|
36
|
+
|
|
37
|
+
Run
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
npx codeceptjs init
|
|
41
|
+
```
|
|
42
|
+
Agree on defaults (press Enter for every question asked). When asked for base site URL, provide a URL of a ecommerce website you are testing. For instance, it could be: `https://myshop.com` if you test already published website or `http://localhost` if you run the website locally.
|
|
43
|
+
|
|
44
|
+
When asked for a test name and suite name write "Checkout". It will create the following dirctory structure:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
.
|
|
48
|
+
├── codecept.conf.js
|
|
49
|
+
├── package.json
|
|
50
|
+
└── Checkout_test.js
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `codecept.conf.js` file in the root of the project directory contains the global configuration settings for CodeceptJS.
|
|
54
|
+
|
|
55
|
+
Now open a test:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
Feature('Checkout');
|
|
59
|
+
|
|
60
|
+
Scenario('test something', ({ I }) => {
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
Inside the Scenario block you write a test.
|
|
64
|
+
|
|
65
|
+
Add `I.amOnPage('/')` into it. It will open the browser on a URL you specified as a base.
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
Feature('Checkout');
|
|
69
|
+
|
|
70
|
+
Scenario('test something', ({ I }) => {
|
|
71
|
+
I.amOnPage('/')
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
But you may want to ask...
|
|
75
|
+
|
|
76
|
+
## What is I?
|
|
77
|
+
|
|
78
|
+
Glad you asked!
|
|
79
|
+
|
|
80
|
+
In CodeceptJS, the `I` object is used to represent the user performing actions in a test scenario. It provides a number of methods (also known as actions) that can be used to simulate user interactions with the application under test.
|
|
81
|
+
|
|
82
|
+
Some of the most popular actions of the I object are:
|
|
83
|
+
|
|
84
|
+
* `I.amOnPage(url)`: This action navigates the user to the specified URL.
|
|
85
|
+
* `I.click(locator)`: This action simulates a click on the element identified by the given locator.
|
|
86
|
+
* `I.fillField(field, value)`: This action fills the specified field with the given value.
|
|
87
|
+
* `I.see(text, context)`: This action checks that the given text is visible on the page (or in the specified context).
|
|
88
|
+
* `I.selectOption(select, option)`: This action selects the specified option from the given select dropdown.
|
|
89
|
+
* `I.waitForElement(locator, timeout)`: This action waits for the specified element to appear on the page, up to the given timeout.
|
|
90
|
+
* `I.waitForText(text, timeout, context)`: This action waits for the given text to appear on the page (or in the specified context), up to the given timeout.
|
|
91
|
+
|
|
92
|
+
We will need to use them to navigate into Checkout process. How do we navigate web? Sure by clicking on links!
|
|
93
|
+
|
|
94
|
+
Let's use `I.click()` for that.
|
|
95
|
+
|
|
96
|
+
But how we can access elements on a webpage?
|
|
97
|
+
|
|
98
|
+
CodeceptJS is smart enough to locate clickable elements by their visible text. For instance, if on your ecommerce website you have a product 'Coffee Cup' with that exact name you can use
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
I.click('Coffee Cup');
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
But sometimes elements are not as easy to locate, so you can use CSS or XPath locators to locate them.
|
|
105
|
+
|
|
106
|
+
For instance, locating Coffee Cup via CSS can take into accont HTML structure of a page and element attributes. For instance, it can be like this:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
I.click('div.products a.product-name[title="Coffee Cup"]');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
In this example, the `div.products` part of the selector specifies a div element with the `products` class, and the `a.product-name[title="Coffee Cup"]` part specifies an a element with `the product-name` class and the `title` attribute set to Coffee Cup.
|
|
113
|
+
|
|
114
|
+
You can read more about HTML and CSS locators, and basically that's all what you need to know to start writing a checkout test!
|
|
115
|
+
|
|
116
|
+
## Get back to Checkout
|
|
117
|
+
|
|
118
|
+
Let's see how a regular checkout script may look in CodeceptJS:
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
Scenario('test the checkout form', async ({ I }) => {
|
|
122
|
+
// we select one product and switched to checkout project
|
|
123
|
+
I.amOnPage('/');
|
|
124
|
+
I.click('Coffee Cup');
|
|
125
|
+
I.click('Purchase');
|
|
126
|
+
I.click('Checkout');
|
|
127
|
+
|
|
128
|
+
// fill in the shipping address
|
|
129
|
+
I.fillField('First Name', 'John');
|
|
130
|
+
I.fillField('Last Name', 'Doe');
|
|
131
|
+
I.fillField('Address', '123 Main St.');
|
|
132
|
+
I.fillField('City', 'New York');
|
|
133
|
+
I.selectOption('State', 'New York');
|
|
134
|
+
I.fillField('Zip Code', '10001');
|
|
135
|
+
|
|
136
|
+
// select a payment method
|
|
137
|
+
I.click('#credit-card-option');
|
|
138
|
+
I.fillField('Card Number', '1234-5678-9012-3456');
|
|
139
|
+
I.fillField('Expiration Date', '12/22');
|
|
140
|
+
I.fillField('Security Code', '123');
|
|
141
|
+
|
|
142
|
+
// click the checkout button
|
|
143
|
+
I.click('Checkout');
|
|
144
|
+
|
|
145
|
+
// verify that the checkout was successful
|
|
146
|
+
I.see('Your order has been placed successfully!');
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
Sure, in relaity your script might be more complicated. As you have noticed, we used CSS locator `'#credit-card-option'` to get select a payment option. However, the test is simple and you can follow user steps through it.
|
|
150
|
+
|
|
151
|
+
Please note, that you shouldn't use a real credit card number here. Good news, you don't need to. Payment providers like Strip provide dummy card numbers for testing purposes.
|
|
152
|
+
|
|
153
|
+
Run the test with next command:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
npx codeceptjs run --debug -p pauseOnFail
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
What are special options here?
|
|
160
|
+
|
|
161
|
+
* `--debug` flag is used to output additional information to the console, such as the details of each step in the test, the values of variables, and the results of test assertions. This can help you to identify and fix any issues in your tests.
|
|
162
|
+
* `-p pauseOnFail` option is also used to keep the browser opened even if a test fails. It will help us to identify to which point test was executed and what can be improved.
|
|
163
|
+
|
|
164
|
+
Add more test steps if needed, update locators, and notify business owners that all that purchases are made by you so your collegues won't call you in the night asking when you want to get a coffee cup 😀 Also the good idea is to run tests on staging website, to not interfere with business process.
|
|
165
|
+
|
|
166
|
+
What a test is complete you can run it with:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
npx codeceptjs run
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
If you are annoyed to see a browser window you can use `HEADLESS` environment variable:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
HEADLESS=true codeceptjs run
|
|
176
|
+
```
|
|
177
|
+
for Windows users HEADLESS should be set in a different manner:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
set HEADLESS=true&& codeceptjs run
|
|
181
|
+
```
|
|
182
|
+
The tests will pass but no browser is shown, so you can watch YouTube videos while it goes!
|
|
183
|
+
|
|
184
|
+
## Refactoring
|
|
185
|
+
|
|
186
|
+
What if you need to check more purchases? Should you copy paste your code for that?
|
|
187
|
+
|
|
188
|
+
No! You can use Page Object pattern to put repeating interactions into the reusable functions.
|
|
189
|
+
|
|
190
|
+
You can create a page object via next command:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
npx codeceptjs gpo
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Sure, we will call it `Checkout`. It will be created in `./pages/Checkout.js` file. You should enable it in `codecept.conf.js` inside `include` section:
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
include: {
|
|
200
|
+
...
|
|
201
|
+
checkoutPage: './pages/Checkout.js',
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
Now open this file:
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
const { I } = inject();
|
|
209
|
+
|
|
210
|
+
module.exports = {
|
|
211
|
+
|
|
212
|
+
// insert your locators and methods here
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Feels really empty. What should we do about it? Should we write more code? No, we already have it. Let's copy code blocks from a test we have it and place them under a corredponnding function names:
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
connst { I } = inject();
|
|
220
|
+
|
|
221
|
+
module.exports = {
|
|
222
|
+
|
|
223
|
+
fillShippingAddress(name, address, city, state, zip) {
|
|
224
|
+
I.fillField('Name', name);
|
|
225
|
+
I.fillField('Address', address);
|
|
226
|
+
I.fillField('City', city);
|
|
227
|
+
I.fillField('State', state);
|
|
228
|
+
I.fillField('Zip', zip);
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
fillValidCreditCard() {
|
|
232
|
+
I.click('#credit-card-option');
|
|
233
|
+
I.fillField('Card Number', '1234-5678-9012-3456');
|
|
234
|
+
I.fillField('Expiration Date', '12/22');
|
|
235
|
+
I.fillField('Security Code', '123');
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
checkout() {
|
|
239
|
+
I.click('Checkout');
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
After that we can update our test to use the created page object. Note, that we import Checkout PageObject by its name `checkoutPage` we previously defined in a config.
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
Scenario('test the checkout form', async ({I, checkoutPage}) => {
|
|
248
|
+
I.amOnPage('/');
|
|
249
|
+
I.click('Coffee Cup');
|
|
250
|
+
I.click('Purchase');
|
|
251
|
+
I.click('Checkout');
|
|
252
|
+
|
|
253
|
+
// fill in the shipping address using the page object
|
|
254
|
+
checkoutPage.fillShippingAddress('John', 'Doe', '123 Main St.', 'New York', 'New York', '10001');
|
|
255
|
+
checkoutPage.fillValidCreditCard();
|
|
256
|
+
checkoutPage.checkout();
|
|
257
|
+
|
|
258
|
+
// verify that the checkout was successful
|
|
259
|
+
I.see('Your order has been placed successfully!');
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
As you see the code of a test was reduced. And we can write the similar tests on the same manner.
|
|
264
|
+
|
|
265
|
+
By applying more and more cases you can test a website to all behaviors.
|
|
266
|
+
|
|
267
|
+
## Summary
|
|
268
|
+
|
|
269
|
+
This was a deep dive! If you think on just starting test automation, CodeceptJS is the best choice for you as it uses native language to pass commands to browser.
|
|
270
|
+
|
|
271
|
+
If you already skilled in JavaScript, with CodeceptJS you can focus on business level of your test, instead of writing code for browser. This way you can keep your tests stable and maintainable.
|
|
@@ -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
|
|
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.4.0
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"testcafe": "^2.1.0",
|
|
132
132
|
"ts-morph": "^3.1.3",
|
|
133
133
|
"ts-node": "^10.9.1",
|
|
134
|
-
"tsd-jsdoc": "
|
|
134
|
+
"tsd-jsdoc": "^2.5.0",
|
|
135
135
|
"typedoc": "^0.23.10",
|
|
136
136
|
"typedoc-plugin-markdown": "^3.13.4",
|
|
137
137
|
"typescript": "^4.8.4",
|
package/typings/index.d.ts
CHANGED
|
@@ -18,18 +18,28 @@ declare namespace CodeceptJS {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
type RetryConfig = {
|
|
21
|
-
|
|
21
|
+
/** Filter tests by string or regexp pattern */
|
|
22
|
+
grep: string | RegExp;
|
|
23
|
+
/** Number of times to repeat scenarios of a Feature */
|
|
22
24
|
Feature: number;
|
|
25
|
+
/** Number of times to repeat scenarios */
|
|
23
26
|
Scenario: number;
|
|
27
|
+
/** Number of times to repeat Before hook */
|
|
24
28
|
Before: number;
|
|
29
|
+
/** Number of times to repeat After hook */
|
|
25
30
|
After: number;
|
|
31
|
+
/** Number of times to repeat BeforeSuite hook */
|
|
26
32
|
BeforeSuite: number;
|
|
33
|
+
/** Number of times to repeat AfterSuite hook */
|
|
27
34
|
AfterSuite: number;
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
type TimeoutConfig = {
|
|
31
|
-
|
|
38
|
+
/** Filter tests by string or regexp pattern */
|
|
39
|
+
grep: string | RegExp;
|
|
40
|
+
/** Set timeout for a scenarios of a Feature */
|
|
32
41
|
Feature: number;
|
|
42
|
+
/** Set timeout for scenarios */
|
|
33
43
|
Scenario: number;
|
|
34
44
|
};
|
|
35
45
|
|