codeceptjs 3.2.1 → 3.3.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/docs/advanced.md +3 -3
- package/docs/api.md +227 -188
- package/docs/basics.md +26 -1
- package/docs/bdd.md +2 -2
- package/docs/build/ApiDataFactory.js +13 -6
- package/docs/build/Appium.js +98 -36
- package/docs/build/FileSystem.js +11 -1
- package/docs/build/GraphQL.js +11 -0
- package/docs/build/JSONResponse.js +297 -0
- package/docs/build/Nightmare.js +48 -48
- package/docs/build/Playwright.js +282 -151
- package/docs/build/Puppeteer.js +76 -67
- package/docs/build/REST.js +36 -0
- package/docs/build/TestCafe.js +44 -44
- package/docs/build/WebDriver.js +70 -70
- package/docs/changelog.md +17 -0
- package/docs/configuration.md +8 -8
- package/docs/custom-helpers.md +1 -1
- package/docs/data.md +9 -9
- package/docs/helpers/ApiDataFactory.md +7 -0
- package/docs/helpers/Appium.md +240 -198
- package/docs/helpers/FileSystem.md +11 -1
- package/docs/helpers/JSONResponse.md +230 -0
- package/docs/helpers/Playwright.md +283 -216
- package/docs/helpers/Puppeteer.md +9 -1
- package/docs/helpers/REST.md +30 -9
- package/docs/installation.md +3 -1
- package/docs/internal-api.md +265 -0
- package/docs/mobile.md +11 -11
- package/docs/nightmare.md +3 -3
- package/docs/pageobjects.md +2 -0
- package/docs/playwright.md +73 -18
- package/docs/plugins.md +138 -38
- package/docs/puppeteer.md +28 -12
- package/docs/quickstart.md +2 -3
- package/docs/reports.md +44 -3
- package/docs/testcafe.md +1 -1
- package/docs/translation.md +2 -2
- package/docs/videos.md +2 -2
- package/docs/visual.md +2 -2
- package/docs/vue.md +1 -1
- package/docs/webdriver.md +92 -4
- package/lib/actor.js +2 -2
- package/lib/cli.js +25 -20
- package/lib/command/init.js +5 -15
- package/lib/command/workers/runTests.js +25 -7
- package/lib/config.js +17 -13
- package/lib/helper/ApiDataFactory.js +13 -6
- package/lib/helper/Appium.js +65 -3
- package/lib/helper/FileSystem.js +11 -1
- package/lib/helper/GraphQL.js +11 -0
- package/lib/helper/JSONResponse.js +297 -0
- package/lib/helper/Playwright.js +220 -89
- package/lib/helper/Puppeteer.js +12 -3
- package/lib/helper/REST.js +36 -0
- package/lib/helper/WebDriver.js +1 -1
- package/lib/helper/extras/Console.js +8 -0
- package/lib/helper/extras/PlaywrightRestartOpts.js +35 -0
- package/lib/interfaces/bdd.js +3 -1
- package/lib/listener/timeout.js +4 -3
- package/lib/plugin/allure.js +12 -0
- package/lib/plugin/autoLogin.js +1 -1
- package/lib/plugin/eachElement.js +127 -0
- package/lib/plugin/stepTimeout.js +5 -4
- package/lib/plugin/tryTo.js +6 -0
- package/lib/recorder.js +2 -1
- package/lib/step.js +57 -2
- package/lib/utils.js +20 -0
- package/package.json +24 -22
- package/translations/pt-BR.js +8 -0
- package/typings/index.d.ts +4 -0
- package/typings/types.d.ts +345 -110
|
@@ -15,7 +15,15 @@ Uses [Google Chrome's Puppeteer][1] library to run tests inside headless Chrome.
|
|
|
15
15
|
Browser control is executed via DevTools Protocol (instead of Selenium).
|
|
16
16
|
This helper works with a browser out of the box with no additional tools required to install.
|
|
17
17
|
|
|
18
|
-
Requires `puppeteer` package to be installed.
|
|
18
|
+
Requires `puppeteer` or `puppeteer-core` package to be installed.
|
|
19
|
+
|
|
20
|
+
npm i puppeteer --save
|
|
21
|
+
|
|
22
|
+
or
|
|
23
|
+
|
|
24
|
+
npm i puppeteer-core --save
|
|
25
|
+
|
|
26
|
+
Using `puppeteer-core` package, will prevent the download of browser binaries and allow connecting to an existing browser installation or for connecting to a remote one.
|
|
19
27
|
|
|
20
28
|
> Experimental Firefox support [can be activated][2].
|
|
21
29
|
|
package/docs/helpers/REST.md
CHANGED
|
@@ -71,6 +71,27 @@ Generates url based on format sent (takes endpoint + url if latter lacks 'http')
|
|
|
71
71
|
|
|
72
72
|
- `url` **any**
|
|
73
73
|
|
|
74
|
+
### amBearerAuthenticated
|
|
75
|
+
|
|
76
|
+
Adds a header for Bearer authentication
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
// we use secret function to hide token from logs
|
|
80
|
+
I.amBearerAuthenticated(secret('heregoestoken'))
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Parameters
|
|
84
|
+
|
|
85
|
+
- `accessToken` **[string][3]** Bearer access token
|
|
86
|
+
|
|
87
|
+
### haveRequestHeaders
|
|
88
|
+
|
|
89
|
+
Sets request headers for all requests of this test
|
|
90
|
+
|
|
91
|
+
#### Parameters
|
|
92
|
+
|
|
93
|
+
- `headers` **[object][4]** headers list
|
|
94
|
+
|
|
74
95
|
### sendDeleteRequest
|
|
75
96
|
|
|
76
97
|
Sends DELETE request to API.
|
|
@@ -82,7 +103,7 @@ I.sendDeleteRequest('/api/users/1');
|
|
|
82
103
|
#### Parameters
|
|
83
104
|
|
|
84
105
|
- `url` **any**
|
|
85
|
-
- `headers` **[object][
|
|
106
|
+
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
|
|
86
107
|
|
|
87
108
|
Returns **[Promise][2]<any>** response
|
|
88
109
|
|
|
@@ -97,7 +118,7 @@ I.sendGetRequest('/api/users.json');
|
|
|
97
118
|
#### Parameters
|
|
98
119
|
|
|
99
120
|
- `url` **any**
|
|
100
|
-
- `headers` **[object][
|
|
121
|
+
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
|
|
101
122
|
|
|
102
123
|
Returns **[Promise][2]<any>** response
|
|
103
124
|
|
|
@@ -114,9 +135,9 @@ I.sendPatchRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
114
135
|
|
|
115
136
|
#### Parameters
|
|
116
137
|
|
|
117
|
-
- `url` **[string][
|
|
138
|
+
- `url` **[string][3]**
|
|
118
139
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
119
|
-
- `headers` **[object][
|
|
140
|
+
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
|
|
120
141
|
|
|
121
142
|
Returns **[Promise][2]<any>** response
|
|
122
143
|
|
|
@@ -135,7 +156,7 @@ I.sendPostRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
135
156
|
|
|
136
157
|
- `url` **any**
|
|
137
158
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
138
|
-
- `headers` **[object][
|
|
159
|
+
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
|
|
139
160
|
|
|
140
161
|
Returns **[Promise][2]<any>** response
|
|
141
162
|
|
|
@@ -152,9 +173,9 @@ I.sendPutRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
152
173
|
|
|
153
174
|
#### Parameters
|
|
154
175
|
|
|
155
|
-
- `url` **[string][
|
|
176
|
+
- `url` **[string][3]**
|
|
156
177
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
157
|
-
- `headers` **[object][
|
|
178
|
+
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
|
|
158
179
|
|
|
159
180
|
Returns **[Promise][2]<any>** response
|
|
160
181
|
|
|
@@ -174,8 +195,8 @@ I.setRequestTimeout(10000); // In milliseconds
|
|
|
174
195
|
|
|
175
196
|
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
176
197
|
|
|
177
|
-
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/
|
|
198
|
+
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
|
178
199
|
|
|
179
|
-
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/
|
|
200
|
+
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
|
180
201
|
|
|
181
202
|
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
package/docs/installation.md
CHANGED
|
@@ -33,6 +33,8 @@ Install CodeceptJS + webdriverio into `e2e-tests` directory:
|
|
|
33
33
|
npx create-codeceptjs e2e-tests --webdriverio
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
If you plan to use CodeceptJS for **API testing** only proceed to standard installation
|
|
37
|
+
|
|
36
38
|
## Standard Installation
|
|
37
39
|
|
|
38
40
|
Open a directory where you want to install CodeceptJS tests.
|
|
@@ -57,7 +59,7 @@ For WebDriver installation Selenium Server is required 👇
|
|
|
57
59
|
|
|
58
60
|
## WebDriver
|
|
59
61
|
|
|
60
|
-
WebDriver based helpers like WebDriver, Protractor, Selenium WebDriver will require [Selenium Server](
|
|
62
|
+
WebDriver based helpers like WebDriver, Protractor, Selenium WebDriver will require [Selenium Server](https://codecept.io/helpers/WebDriver/#selenium-installation) installed. They will also require ChromeDriver or GeckoDriver to run corresponding browsers.
|
|
61
63
|
|
|
62
64
|
We recommend to install them manually or use NPM packages:
|
|
63
65
|
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /internal-api
|
|
3
|
+
title: Internal API
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Concepts
|
|
7
|
+
|
|
8
|
+
In this guide we will overview the internal API of CodeceptJS.
|
|
9
|
+
This knowledge is required for customization, writing plugins, etc.
|
|
10
|
+
|
|
11
|
+
CodeceptJS provides an API which can be loaded via `require('codeceptjs')` when CodeceptJS is installed locally. Otherwise, you can load codeceptjs API via global `codeceptjs` object:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// via module
|
|
15
|
+
const { recorder, event, output } = require('codeceptjs');
|
|
16
|
+
// or using global object
|
|
17
|
+
const { recorder, event, output } = codeceptjs;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
These internal objects are available:
|
|
21
|
+
|
|
22
|
+
* [`codecept`](https://github.com/Codeception/CodeceptJS/blob/master/lib/codecept.js): test runner class
|
|
23
|
+
* [`config`](https://github.com/Codeception/CodeceptJS/blob/master/lib/config.js): current codecept config
|
|
24
|
+
* [`event`](https://github.com/Codeception/CodeceptJS/blob/master/lib/event.js): event listener
|
|
25
|
+
* [`recorder`](https://github.com/Codeception/CodeceptJS/blob/master/lib/recorder.js): global promise chain
|
|
26
|
+
* [`output`](https://github.com/Codeception/CodeceptJS/blob/master/lib/output.js): internal printer
|
|
27
|
+
* [`container`](https://github.com/Codeception/CodeceptJS/blob/master/lib/container.js): dependency injection container for tests, includes current helpers and support objects
|
|
28
|
+
* [`helper`](https://github.com/Codeception/CodeceptJS/blob/master/lib/helper.js): basic helper class
|
|
29
|
+
* [`actor`](https://github.com/Codeception/CodeceptJS/blob/master/lib/actor.js): basic actor (I) class
|
|
30
|
+
|
|
31
|
+
[API reference](https://github.com/Codeception/CodeceptJS/tree/master/docs/api) is available on GitHub.
|
|
32
|
+
Also please check the source code of corresponding modules.
|
|
33
|
+
|
|
34
|
+
### Container
|
|
35
|
+
|
|
36
|
+
CodeceptJS has a dependency injection container with helpers and support objects.
|
|
37
|
+
They can be retrieved from the container:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const { container } = require('codeceptjs');
|
|
41
|
+
|
|
42
|
+
// get object with all helpers
|
|
43
|
+
const helpers = container.helpers();
|
|
44
|
+
|
|
45
|
+
// get helper by name
|
|
46
|
+
const { WebDriver } = container.helpers();
|
|
47
|
+
|
|
48
|
+
// get support objects
|
|
49
|
+
const supportObjects = container.support();
|
|
50
|
+
|
|
51
|
+
// get support object by name
|
|
52
|
+
const { UserPage } = container.support();
|
|
53
|
+
|
|
54
|
+
// get all registered plugins
|
|
55
|
+
const plugins = container.plugins();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
New objects can also be added to container in runtime:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
const { container } = require('codeceptjs');
|
|
62
|
+
|
|
63
|
+
container.append({
|
|
64
|
+
helpers: { // add helper
|
|
65
|
+
MyHelper: new MyHelper({ config1: 'val1' });
|
|
66
|
+
},
|
|
67
|
+
support: { // add page object
|
|
68
|
+
UserPage: require('./pages/user');
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
> Use this trick to define custom objects inside `boostrap` script
|
|
74
|
+
|
|
75
|
+
The container also contains the current Mocha instance:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const mocha = container.mocha();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Event Listeners
|
|
82
|
+
|
|
83
|
+
CodeceptJS provides a module with an [event dispatcher and set of predefined events](https://github.com/Codeception/CodeceptJS/blob/master/lib/event.js).
|
|
84
|
+
|
|
85
|
+
It can be required from codeceptjs package if it is installed locally.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
const { event } = require('codeceptjs');
|
|
89
|
+
|
|
90
|
+
module.exports = function() {
|
|
91
|
+
|
|
92
|
+
event.dispatcher.on(event.test.before, function (test) {
|
|
93
|
+
|
|
94
|
+
console.log('--- I am before test --');
|
|
95
|
+
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Available events:
|
|
101
|
+
|
|
102
|
+
* `event.test.before(test)` - *async* when `Before` hooks from helpers and from test is executed
|
|
103
|
+
* `event.test.after(test)` - *async* after each test
|
|
104
|
+
* `event.test.started(test)` - *sync* at the very beginning of a test.
|
|
105
|
+
* `event.test.passed(test)` - *sync* when test passed
|
|
106
|
+
* `event.test.failed(test, error)` - *sync* when test failed
|
|
107
|
+
* `event.test.finished(test)` - *sync* when test finished
|
|
108
|
+
* `event.suite.before(suite)` - *async* before a suite
|
|
109
|
+
* `event.suite.after(suite)` - *async* after a suite
|
|
110
|
+
* `event.step.before(step)` - *async* when the step is scheduled for execution
|
|
111
|
+
* `event.step.after(step)`- *async* after a step
|
|
112
|
+
* `event.step.started(step)` - *sync* when step starts.
|
|
113
|
+
* `event.step.passed(step)` - *sync* when step passed.
|
|
114
|
+
* `event.step.failed(step, err)` - *sync* when step failed.
|
|
115
|
+
* `event.step.finished(step)` - *sync* when step finishes.
|
|
116
|
+
* `event.step.comment(step)` - *sync* fired for comments like `I.say`.
|
|
117
|
+
* `event.all.before` - before running tests
|
|
118
|
+
* `event.all.after` - after running tests
|
|
119
|
+
* `event.all.result` - when results are printed
|
|
120
|
+
* `event.workers.before` - before spawning workers in parallel run
|
|
121
|
+
* `event.workers.after` - after workers finished in parallel run
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
> *sync* - means that event is fired in the moment of the action happening.
|
|
125
|
+
*async* - means that event is fired when an action is scheduled. Use `recorder` to schedule your actions.
|
|
126
|
+
|
|
127
|
+
For further reference look for [currently available listeners](https://github.com/Codeception/CodeceptJS/tree/master/lib/listener) using the event system.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### Recorder
|
|
131
|
+
|
|
132
|
+
To inject asynchronous functions in a test or before/after a test you can subscribe to corresponding event and register a function inside a recorder object. [Recorder](https://github.com/Codeception/CodeceptJS/blob/master/lib/recorder.js) represents a global promises chain.
|
|
133
|
+
|
|
134
|
+
Provide a function in the first parameter, a function must be async or must return a promise:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
const { event, recorder } = require('codeceptjs');
|
|
138
|
+
|
|
139
|
+
module.exports = function() {
|
|
140
|
+
|
|
141
|
+
event.dispatcher.on(event.test.before, function (test) {
|
|
142
|
+
|
|
143
|
+
const request = require('request');
|
|
144
|
+
|
|
145
|
+
recorder.add('create fixture data via API', function() {
|
|
146
|
+
return new Promise((doneFn, errFn) => {
|
|
147
|
+
request({
|
|
148
|
+
baseUrl: 'http://api.site.com/',
|
|
149
|
+
method: 'POST',
|
|
150
|
+
url: '/users',
|
|
151
|
+
json: { name: 'john', email: 'john@john.com' }
|
|
152
|
+
}), (err, httpResponse, body) => {
|
|
153
|
+
if (err) return errFn(err);
|
|
154
|
+
doneFn();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Config
|
|
163
|
+
|
|
164
|
+
CodeceptJS config can be accessed from `require('codeceptjs').config.get()`:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
const { config } = require('codeceptjs');
|
|
168
|
+
|
|
169
|
+
// config object has access to all values of the current config file
|
|
170
|
+
|
|
171
|
+
if (config.get().myKey == 'value') {
|
|
172
|
+
// run something
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
### Output
|
|
178
|
+
|
|
179
|
+
Output module provides four verbosity levels. Depending on the mode you can have different information printed using corresponding functions.
|
|
180
|
+
|
|
181
|
+
* `default`: prints basic information using `output.print`
|
|
182
|
+
* `steps`: toggled by `--steps` option, prints step execution
|
|
183
|
+
* `debug`: toggled by `--debug` option, prints steps, and debug information with `output.debug`
|
|
184
|
+
* `verbose`: toggled by `--verbose` prints debug information and internal logs with `output.log`
|
|
185
|
+
|
|
186
|
+
It is recommended to avoid `console.log` and use output.* methods for printing.
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
const output = require('codeceptjs').output;
|
|
190
|
+
|
|
191
|
+
output.print('This is basic information');
|
|
192
|
+
output.debug('This is debug information');
|
|
193
|
+
output.log('This is verbose logging information');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### Test Object
|
|
197
|
+
|
|
198
|
+
The test events are providing a test object with following properties:
|
|
199
|
+
|
|
200
|
+
* `title` title of the test
|
|
201
|
+
* `body` test function as a string
|
|
202
|
+
* `opts` additional test options like retries, and others
|
|
203
|
+
* `pending` true if test is scheduled for execution and false if a test has finished
|
|
204
|
+
* `tags` array of tags for this test
|
|
205
|
+
* `artifacts` list of files attached to this test. Screenshots, videos and other files can be saved here and shared accross different reporters
|
|
206
|
+
* `file` path to a file with a test
|
|
207
|
+
* `steps` array of executed steps (available only in `test.passed`, `test.failed`, `test.finished` event)
|
|
208
|
+
* `skipInfo` additional test options when test skipped
|
|
209
|
+
* * `message` string with reason for skip
|
|
210
|
+
* * `description` string with test body
|
|
211
|
+
and others
|
|
212
|
+
|
|
213
|
+
#### Step Object
|
|
214
|
+
|
|
215
|
+
Step events provide step objects with following fields:
|
|
216
|
+
|
|
217
|
+
* `name` name of a step, like 'see', 'click', and others
|
|
218
|
+
* `actor` current actor, in most cases it is `I`
|
|
219
|
+
* `helper` current helper instance used to execute this step
|
|
220
|
+
* `helperMethod` corresponding helper method, in most cases is the same as `name`
|
|
221
|
+
* `status` status of a step (passed or failed)
|
|
222
|
+
* `prefix` if a step is executed inside `within` block contain within text, like: 'Within .js-signup-form'.
|
|
223
|
+
* `args` passed arguments
|
|
224
|
+
|
|
225
|
+
Whenever you execute tests with `--verbose` option you will see registered events and promises executed by a recorder.
|
|
226
|
+
|
|
227
|
+
## Custom Runner
|
|
228
|
+
|
|
229
|
+
You can run CodeceptJS tests from your script.
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
const { codecept: Codecept } = require('codeceptjs');
|
|
233
|
+
|
|
234
|
+
// define main config
|
|
235
|
+
const config = {
|
|
236
|
+
helpers: {
|
|
237
|
+
WebDriver: {
|
|
238
|
+
browser: 'chrome',
|
|
239
|
+
url: 'http://localhost'
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const opts = { steps: true };
|
|
245
|
+
|
|
246
|
+
// run CodeceptJS inside async function
|
|
247
|
+
(async () => {
|
|
248
|
+
const codecept = new Codecept(config, options);
|
|
249
|
+
codecept.init(__dirname);
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
await codecept.bootstrap();
|
|
253
|
+
codecept.loadTests('**_test.js');
|
|
254
|
+
// run tests
|
|
255
|
+
await codecept.run(test);
|
|
256
|
+
} catch (err) {
|
|
257
|
+
printError(err);
|
|
258
|
+
process.exitCode = 1;
|
|
259
|
+
} finally {
|
|
260
|
+
await codecept.teardown();
|
|
261
|
+
}
|
|
262
|
+
})();
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
> Also, you can run tests inside workers in a custom scripts. Please refer to the [parallel execution](/parallel) guide for more details.
|
package/docs/mobile.md
CHANGED
|
@@ -6,7 +6,7 @@ title: Mobile Testing with Appium
|
|
|
6
6
|
# Mobile Testing with Appium
|
|
7
7
|
|
|
8
8
|
CodeceptJS allows to test mobile and hybrid apps in a similar manner web applications are tested.
|
|
9
|
-
Such tests are executed using [Appium](
|
|
9
|
+
Such tests are executed using [Appium](https://appium.io) on emulated or physical devices. Also, Appium allows to test web application on mobile devices.
|
|
10
10
|
|
|
11
11
|
What makes CodeceptJS better for mobile testing?
|
|
12
12
|
Take a look. Here is the sample test for a native mobile application written in CodeceptJS:
|
|
@@ -14,10 +14,10 @@ Take a look. Here is the sample test for a native mobile application written in
|
|
|
14
14
|
```js
|
|
15
15
|
I.seeAppIsInstalled("io.super.app");
|
|
16
16
|
I.click('~startUserRegistrationCD');
|
|
17
|
-
I.fillField('~email of the customer', 'Nothing special')
|
|
18
|
-
I.see('davert@codecept.io', '~email of the customer')
|
|
19
|
-
I.clearField('~email of the customer')
|
|
20
|
-
I.dontSee('Nothing special', '~email of the customer')
|
|
17
|
+
I.fillField('~email of the customer', 'Nothing special');
|
|
18
|
+
I.see('davert@codecept.io', '~email of the customer');
|
|
19
|
+
I.clearField('~email of the customer');
|
|
20
|
+
I.dontSee('Nothing special', '~email of the customer');
|
|
21
21
|
I.seeElement({
|
|
22
22
|
android: 'android.widget.Button',
|
|
23
23
|
ios: '//UIAApplication[1]/UIAWindow[1]/UIAButton[1]'
|
|
@@ -29,15 +29,15 @@ Doesn't it sound cool?
|
|
|
29
29
|
|
|
30
30
|
## Setting Up
|
|
31
31
|
|
|
32
|
-
Ensure that you have [CodeceptJS installed](
|
|
33
|
-
You will also need to install [Appium](
|
|
32
|
+
Ensure that you have [CodeceptJS installed](https://codecept.io/installation/).
|
|
33
|
+
You will also need to install [Appium](https://appium.io/).
|
|
34
34
|
We suggest to use [appium-doctor](https://www.npmjs.com/package/appium-doctor) to check if your system is ready for mobile testing.
|
|
35
35
|
|
|
36
36
|
```sh
|
|
37
37
|
npm i -g appium-doctor
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
If everything is OK, continue with installing Appium. If not, consider using cloud based alternatives like [SauceLabs](https://saucelabs.com) or [BrowserStack](
|
|
40
|
+
If everything is OK, continue with installing Appium. If not, consider using cloud based alternatives like [SauceLabs](https://saucelabs.com) or [BrowserStack](https://browserstack.com). Cloud services provide hosted appium with real and emulated mobile devices.
|
|
41
41
|
|
|
42
42
|
To install Appium use npm:
|
|
43
43
|
|
|
@@ -71,7 +71,7 @@ Initialize CodeceptJS with `init` command:
|
|
|
71
71
|
npx codeceptjs init
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Select [Appium helper](
|
|
74
|
+
Select [Appium helper](https://codecept.io/helpers/Appium/) when asked.
|
|
75
75
|
|
|
76
76
|
```sh
|
|
77
77
|
? What helpers do you want to use?
|
|
@@ -166,7 +166,7 @@ There are mobile-only methods like:
|
|
|
166
166
|
* `hideDeviceKeyboard`,
|
|
167
167
|
* `seeAppIsInstalled`, `installApp`, `removeApp`, `seeAppIsNotInstalled` - Android only
|
|
168
168
|
|
|
169
|
-
and [others](
|
|
169
|
+
and [others](https://codecept.io/helpers/Appium/).
|
|
170
170
|
|
|
171
171
|
## Locating Elements
|
|
172
172
|
|
|
@@ -211,7 +211,7 @@ I.tap('Click me!');
|
|
|
211
211
|
I.click('Click me!');
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
-
Native iOS/Android locators can be used with `android=` and `ios=` prefixes. [Learn more](
|
|
214
|
+
Native iOS/Android locators can be used with `android=` and `ios=` prefixes. [Learn more](https://webdriver.io/guide/usage/selectors.html#Mobile-Selectors).
|
|
215
215
|
|
|
216
216
|
But how to get all those locators? We recommend to use [Appium Inspector](https://github.com/appium/appium-desktop).
|
|
217
217
|
|
package/docs/nightmare.md
CHANGED
|
@@ -11,7 +11,7 @@ This hardens setting it up testing environment for CI server and slows down test
|
|
|
11
11
|
|
|
12
12
|
Is there a sane alternative to Selenium?
|
|
13
13
|
|
|
14
|
-
Yes, how about [NightmareJS](
|
|
14
|
+
Yes, how about [NightmareJS](https://www.nightmarejs.org)?
|
|
15
15
|
|
|
16
16
|
It is modern Electron based testing framework which allows to execute tests in headless mode as well as in window mode for debug purposes.
|
|
17
17
|
This makes Nightmare very useful, much more handy than PhantomJS. Nightmare is in active development and has nice API for writing acceptance tests.
|
|
@@ -105,7 +105,7 @@ codeceptjs init
|
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
You will be asked for a Helper to use, you should select Nightmare and provide url of a website you are testing.
|
|
108
|
-
Setup process is explained on [QuickStart page](
|
|
108
|
+
Setup process is explained on [QuickStart page](https://codecept.io/quickstart/).
|
|
109
109
|
|
|
110
110
|
(If you already have CodeceptJS project, just install nightmare globally or locally and enable it in config)
|
|
111
111
|
|
|
@@ -171,7 +171,7 @@ Nightmare helper is missing you can easily create `ExtendedNightmare` helper by
|
|
|
171
171
|
codeceptjs gh
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
Learn more about [Helpers](
|
|
174
|
+
Learn more about [Helpers](https://codecept.io/helpers/).
|
|
175
175
|
|
|
176
176
|
Nightmare instance can be accessed by custom helper:
|
|
177
177
|
|
package/docs/pageobjects.md
CHANGED
|
@@ -191,6 +191,8 @@ module.exports = new AttachFile();
|
|
|
191
191
|
module.exports.AttachFile = AttachFile;
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
+
> ⚠ While building complex page objects it is important to keep all `async` functions to be called with `await`. While CodeceptJS allows to run commands synchronously if async function has `I.grab*` or any custom function that returns a promise it must be called with `await`. If you see `UnhandledPromiseRejectionWarning` it might be caused by async page object function that was called without `await`.
|
|
195
|
+
|
|
194
196
|
## Page Fragments
|
|
195
197
|
|
|
196
198
|
Similarly, CodeceptJS allows you to generate **PageFragments** and any other abstractions
|
package/docs/playwright.md
CHANGED
|
@@ -31,7 +31,7 @@ To start you need CodeceptJS with Playwright packages installed
|
|
|
31
31
|
npm install codeceptjs playwright --save
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Or see [alternative installation options](
|
|
34
|
+
Or see [alternative installation options](https://codecept.io/installation/)
|
|
35
35
|
|
|
36
36
|
> If you already have CodeceptJS project, just install `playwright` package and enable a helper it in config.
|
|
37
37
|
|
|
@@ -84,7 +84,7 @@ When to consider navigation succeeded, defaults to `load`. Given an array of eve
|
|
|
84
84
|
When a test runs faster than application it is recommended to increase `waitForAction` config value.
|
|
85
85
|
It will wait for a small amount of time (100ms) by default after each user action is taken.
|
|
86
86
|
|
|
87
|
-
> ▶ More options are listed in [helper reference](
|
|
87
|
+
> ▶ More options are listed in [helper reference](https://codecept.io/helpers/Playwright/).
|
|
88
88
|
|
|
89
89
|
## Writing Tests
|
|
90
90
|
|
|
@@ -109,7 +109,7 @@ Tests consist with a scenario of user's action taken on a page. The most widely
|
|
|
109
109
|
* `see`, `dontSee` - to check for a text on a page
|
|
110
110
|
* `seeElement`, `dontSeeElement` - to check for elements on a page
|
|
111
111
|
|
|
112
|
-
> ℹ All actions are listed in [Playwright helper reference](
|
|
112
|
+
> ℹ All actions are listed in [Playwright helper reference](https://codecept.io/helpers/Playwright/).*
|
|
113
113
|
|
|
114
114
|
All actions which interact with elements can use **[CSS or XPath locators](https://codecept.io/locators/#css-and-xpath)**. Actions like `click` or `fillField` can locate elements by their name or value on a page:
|
|
115
115
|
|
|
@@ -175,8 +175,10 @@ If you need to get element's value inside a test you can use `grab*` methods. Th
|
|
|
175
175
|
```js
|
|
176
176
|
const assert = require('assert');
|
|
177
177
|
Scenario('get value of current tasks', async ({ I }) => {
|
|
178
|
-
I.
|
|
179
|
-
I.
|
|
178
|
+
I.fillField('.todo', 'my first item');
|
|
179
|
+
I.pressKey('Enter')
|
|
180
|
+
I.fillField('.todo', 'my second item');
|
|
181
|
+
I.pressKey('Enter')
|
|
180
182
|
let numTodos = await I.grabTextFrom('.todo-count strong');
|
|
181
183
|
assert.equal(2, numTodos);
|
|
182
184
|
});
|
|
@@ -188,17 +190,35 @@ In case some actions should be taken inside one element (a container or modal wi
|
|
|
188
190
|
Please take a note that you can't use within inside another within in Playwright helper:
|
|
189
191
|
|
|
190
192
|
```js
|
|
191
|
-
within('.todoapp', () => {
|
|
192
|
-
I.
|
|
193
|
+
await within('.todoapp', () => {
|
|
194
|
+
I.fillField('.todo', 'my new item');
|
|
195
|
+
I.pressKey('Enter')
|
|
193
196
|
I.see('1 item left', '.todo-count');
|
|
194
197
|
I.click('.todo-list input.toggle');
|
|
195
198
|
});
|
|
196
199
|
I.see('0 items left', '.todo-count');
|
|
197
200
|
```
|
|
198
201
|
|
|
199
|
-
|
|
202
|
+
### Each Element <Badge text="Since 3.3" type="warning"/>
|
|
200
203
|
|
|
201
|
-
CodeceptJS
|
|
204
|
+
Usually, CodeceptJS performs an action on the first matched element.
|
|
205
|
+
In case you want to do an action on each element found, use the special function `eachElement` which comes from [eachElement](https://codecept.io/plugins/#eachelement) plugin.
|
|
206
|
+
|
|
207
|
+
`eachElement` function matches all elements by locator and performs a callback on each of those element. A callback function receives [ElementHandle instance](https://playwright.dev/docs/api/class-elementhandle) from Playwright API. `eachElement` may perform arbitrary actions on a page, so the first argument should by a description of the actions performed. This description will be used for logging purposes.
|
|
208
|
+
|
|
209
|
+
Usage example
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
await eachElement(
|
|
213
|
+
'tick all checkboxes',
|
|
214
|
+
'input.custom-checkbox',
|
|
215
|
+
async (el, index) => {
|
|
216
|
+
await el.check();
|
|
217
|
+
});
|
|
218
|
+
);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> ℹ Learn more about [eachElement plugin](/plugins/#eachelement)
|
|
202
222
|
|
|
203
223
|
## Multi Session Testing
|
|
204
224
|
|
|
@@ -307,19 +327,40 @@ Scenario('website looks nice on iPhone', () => {
|
|
|
307
327
|
});
|
|
308
328
|
```
|
|
309
329
|
|
|
310
|
-
##
|
|
330
|
+
## API Requests
|
|
311
331
|
|
|
312
|
-
|
|
332
|
+
CodeceptJS has [REST](/helpers/REST) and [GraphQL]((/helpers/GraphQL)) helpers to perform requests to external APIs. This may be helpful to implement [data management](https://codecept.io/data/) strategy.
|
|
313
333
|
|
|
314
|
-
Playwright
|
|
334
|
+
However, Playwright since 1.18 has its own [API for making request](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get). It uses cookies from browser session to authenticate requests. So you can use it via [`makeApiRequest`](/helpers/Playwright#makeApiRequest) method:
|
|
315
335
|
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
- uses: microsoft/playwright-github-action@v1
|
|
319
|
-
- name: run CodeceptJS tests
|
|
320
|
-
run: npx codeceptjs run
|
|
336
|
+
```js
|
|
337
|
+
I.makeApiRequest('GET', '/users')
|
|
321
338
|
```
|
|
322
339
|
|
|
340
|
+
It is also possible to test JSON responses by adding [`JSONResponse`](/helpers/JSONResponse) and connecting it to Playwright:
|
|
341
|
+
|
|
342
|
+
```js
|
|
343
|
+
// inside codecept.conf.js
|
|
344
|
+
{
|
|
345
|
+
helpers: {
|
|
346
|
+
Playwright: {
|
|
347
|
+
// current config
|
|
348
|
+
},
|
|
349
|
+
JSONResponse: {
|
|
350
|
+
requestHelper: 'Playwright',
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
This helper provides you methods for [API testing](/api). For instance, you can check for status code, data inclusion and structure:
|
|
356
|
+
|
|
357
|
+
```js
|
|
358
|
+
I.makeApiRequest('GET', '/users/1');
|
|
359
|
+
I.seeResponseCodeIs(200);
|
|
360
|
+
I.seeResponseContainsKeys(['user']);
|
|
361
|
+
```
|
|
362
|
+
This way you can do full fledged API testing via Playwright.
|
|
363
|
+
|
|
323
364
|
## Accessing Playwright API
|
|
324
365
|
|
|
325
366
|
To get [Playwright API](https://playwright.dev/docs/api/class-playwright) inside a test use `I.usePlaywrightTo` method with a callback.
|
|
@@ -350,7 +391,6 @@ I.usePlaywrightTo('emulate offline mode', async (Playwright) => {
|
|
|
350
391
|
// call a method of helper, await is required here
|
|
351
392
|
await Playwright.click('Reload');
|
|
352
393
|
});
|
|
353
|
-
|
|
354
394
|
```
|
|
355
395
|
|
|
356
396
|
## Mocking Network Requests <Badge text="Since 3.1" type="warning"/>
|
|
@@ -496,6 +536,7 @@ Open `index.html` in your browser to view the full interactive coverage report.
|
|
|
496
536
|

|
|
497
537
|
|
|
498
538
|

|
|
539
|
+
|
|
499
540
|
## Extending Helper
|
|
500
541
|
|
|
501
542
|
To create custom `I.*` commands using Playwright API you need to create a custom helper.
|
|
@@ -538,3 +579,17 @@ async setPermissions() {
|
|
|
538
579
|
> [▶ Learn more about BrowserContext](https://github.com/microsoft/playwright/blob/master/docs/src/api/class-browsercontext.md)
|
|
539
580
|
|
|
540
581
|
> [▶ Learn more about Helpers](https://codecept.io/helpers/)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
## Configuring CI
|
|
585
|
+
|
|
586
|
+
### GitHub Actions
|
|
587
|
+
|
|
588
|
+
Playwright can be added to GitHub Actions using [official action](https://github.com/microsoft/playwright-github-action). Use it before starting CodeceptJS tests to install all dependencies. It is important to run tests in headless mode ([otherwise you will need to enable xvfb to emulate desktop](https://github.com/microsoft/playwright-github-action#run-in-headful-mode)).
|
|
589
|
+
|
|
590
|
+
```yml
|
|
591
|
+
# from workflows/tests.yml
|
|
592
|
+
- uses: microsoft/playwright-github-action@v1
|
|
593
|
+
- name: run CodeceptJS tests
|
|
594
|
+
run: npx codeceptjs run
|
|
595
|
+
```
|