codeceptjs 3.5.12-beta.5 → 3.5.12-beta.6
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/lib/helper/Playwright.js +41 -22
- package/lib/helper/Puppeteer.js +23 -6
- package/lib/helper/WebDriver.js +23 -4
- package/lib/helper/errors/ElementAssertion.js +38 -0
- package/lib/locator.js +4 -13
- package/package.json +8 -10
- package/docs/advanced.md +0 -351
- package/docs/ai.md +0 -248
- package/docs/api.md +0 -323
- package/docs/basics.md +0 -979
- package/docs/bdd.md +0 -539
- package/docs/best.md +0 -237
- package/docs/books.md +0 -37
- package/docs/bootstrap.md +0 -135
- package/docs/build/ApiDataFactory.js +0 -410
- package/docs/build/Appium.js +0 -2027
- package/docs/build/Expect.js +0 -422
- package/docs/build/FileSystem.js +0 -228
- package/docs/build/GraphQL.js +0 -229
- package/docs/build/GraphQLDataFactory.js +0 -309
- package/docs/build/JSONResponse.js +0 -338
- package/docs/build/Mochawesome.js +0 -71
- package/docs/build/Nightmare.js +0 -2152
- package/docs/build/OpenAI.js +0 -126
- package/docs/build/Playwright.js +0 -5110
- package/docs/build/Protractor.js +0 -2706
- package/docs/build/Puppeteer.js +0 -3905
- package/docs/build/REST.js +0 -344
- package/docs/build/TestCafe.js +0 -2125
- package/docs/build/WebDriver.js +0 -4240
- package/docs/changelog.md +0 -2572
- package/docs/commands.md +0 -266
- package/docs/community-helpers.md +0 -58
- package/docs/configuration.md +0 -157
- package/docs/continuous-integration.md +0 -22
- package/docs/custom-helpers.md +0 -306
- package/docs/data.md +0 -379
- package/docs/detox.md +0 -235
- package/docs/docker.md +0 -136
- package/docs/email.md +0 -183
- package/docs/examples.md +0 -149
- package/docs/helpers/ApiDataFactory.md +0 -266
- package/docs/helpers/Appium.md +0 -1374
- package/docs/helpers/Detox.md +0 -586
- package/docs/helpers/Expect.md +0 -275
- package/docs/helpers/FileSystem.md +0 -152
- package/docs/helpers/GraphQL.md +0 -151
- package/docs/helpers/GraphQLDataFactory.md +0 -226
- package/docs/helpers/JSONResponse.md +0 -254
- package/docs/helpers/Mochawesome.md +0 -8
- package/docs/helpers/MockRequest.md +0 -377
- package/docs/helpers/Nightmare.md +0 -1305
- package/docs/helpers/OpenAI.md +0 -70
- package/docs/helpers/Playwright.md +0 -2759
- package/docs/helpers/Polly.md +0 -44
- package/docs/helpers/Protractor.md +0 -1769
- package/docs/helpers/Puppeteer-firefox.md +0 -86
- package/docs/helpers/Puppeteer.md +0 -2317
- package/docs/helpers/REST.md +0 -218
- package/docs/helpers/TestCafe.md +0 -1321
- package/docs/helpers/WebDriver.md +0 -2547
- package/docs/hooks.md +0 -340
- package/docs/index.md +0 -111
- package/docs/installation.md +0 -75
- package/docs/internal-api.md +0 -266
- package/docs/locators.md +0 -339
- package/docs/mobile-react-native-locators.md +0 -67
- package/docs/mobile.md +0 -338
- package/docs/pageobjects.md +0 -291
- package/docs/parallel.md +0 -400
- package/docs/playwright.md +0 -632
- package/docs/plugins.md +0 -1259
- package/docs/puppeteer.md +0 -316
- package/docs/quickstart.md +0 -162
- package/docs/react.md +0 -70
- package/docs/reports.md +0 -392
- package/docs/secrets.md +0 -36
- package/docs/shadow.md +0 -68
- package/docs/shared/keys.mustache +0 -31
- package/docs/shared/react.mustache +0 -1
- package/docs/testcafe.md +0 -174
- package/docs/translation.md +0 -247
- package/docs/tutorial.md +0 -271
- package/docs/typescript.md +0 -180
- package/docs/ui.md +0 -59
- package/docs/videos.md +0 -28
- package/docs/visual.md +0 -202
- package/docs/vue.md +0 -143
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -11
- package/docs/webapi/attachFile.mustache +0 -12
- package/docs/webapi/blur.mustache +0 -18
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -9
- package/docs/webapi/clearField.mustache +0 -9
- package/docs/webapi/click.mustache +0 -25
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -8
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -11
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -16
- package/docs/webapi/focus.mustache +0 -13
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/grabWebElement.mustache +0 -9
- package/docs/webapi/grabWebElements.mustache +0 -9
- package/docs/webapi/moveCursorTo.mustache +0 -12
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -8
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -12
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/selectOption.mustache +0 -21
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -21
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
- package/docs/webdriver.md +0 -701
- package/docs/wiki/Books-&-Posts.md +0 -27
- package/docs/wiki/Community-Helpers-&-Plugins.md +0 -53
- package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -61
- package/docs/wiki/Examples.md +0 -145
- package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
- package/docs/wiki/Home.md +0 -16
- package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +0 -83
- package/docs/wiki/Release-Process.md +0 -24
- package/docs/wiki/Roadmap.md +0 -23
- package/docs/wiki/Tests.md +0 -1393
- package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
- package/docs/wiki/Videos.md +0 -19
package/docs/internal-api.md
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
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
|
-
* `event.workers.result` - test results after workers finished in parallel run
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
> *sync* - means that event is fired in the moment of the action happening.
|
|
126
|
-
*async* - means that event is fired when an action is scheduled. Use `recorder` to schedule your actions.
|
|
127
|
-
|
|
128
|
-
For further reference look for [currently available listeners](https://github.com/Codeception/CodeceptJS/tree/master/lib/listener) using the event system.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### Recorder
|
|
132
|
-
|
|
133
|
-
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.
|
|
134
|
-
|
|
135
|
-
Provide a function in the first parameter, a function must be async or must return a promise:
|
|
136
|
-
|
|
137
|
-
```js
|
|
138
|
-
const { event, recorder } = require('codeceptjs');
|
|
139
|
-
|
|
140
|
-
module.exports = function() {
|
|
141
|
-
|
|
142
|
-
event.dispatcher.on(event.test.before, function (test) {
|
|
143
|
-
|
|
144
|
-
const request = require('request');
|
|
145
|
-
|
|
146
|
-
recorder.add('create fixture data via API', function() {
|
|
147
|
-
return new Promise((doneFn, errFn) => {
|
|
148
|
-
request({
|
|
149
|
-
baseUrl: 'http://api.site.com/',
|
|
150
|
-
method: 'POST',
|
|
151
|
-
url: '/users',
|
|
152
|
-
json: { name: 'john', email: 'john@john.com' }
|
|
153
|
-
}), (err, httpResponse, body) => {
|
|
154
|
-
if (err) return errFn(err);
|
|
155
|
-
doneFn();
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Config
|
|
164
|
-
|
|
165
|
-
CodeceptJS config can be accessed from `require('codeceptjs').config.get()`:
|
|
166
|
-
|
|
167
|
-
```js
|
|
168
|
-
const { config } = require('codeceptjs');
|
|
169
|
-
|
|
170
|
-
// config object has access to all values of the current config file
|
|
171
|
-
|
|
172
|
-
if (config.get().myKey == 'value') {
|
|
173
|
-
// run something
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
### Output
|
|
179
|
-
|
|
180
|
-
Output module provides four verbosity levels. Depending on the mode you can have different information printed using corresponding functions.
|
|
181
|
-
|
|
182
|
-
* `default`: prints basic information using `output.print`
|
|
183
|
-
* `steps`: toggled by `--steps` option, prints step execution
|
|
184
|
-
* `debug`: toggled by `--debug` option, prints steps, and debug information with `output.debug`
|
|
185
|
-
* `verbose`: toggled by `--verbose` prints debug information and internal logs with `output.log`
|
|
186
|
-
|
|
187
|
-
It is recommended to avoid `console.log` and use output.* methods for printing.
|
|
188
|
-
|
|
189
|
-
```js
|
|
190
|
-
const output = require('codeceptjs').output;
|
|
191
|
-
|
|
192
|
-
output.print('This is basic information');
|
|
193
|
-
output.debug('This is debug information');
|
|
194
|
-
output.log('This is verbose logging information');
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
#### Test Object
|
|
198
|
-
|
|
199
|
-
The test events are providing a test object with following properties:
|
|
200
|
-
|
|
201
|
-
* `title` title of the test
|
|
202
|
-
* `body` test function as a string
|
|
203
|
-
* `opts` additional test options like retries, and others
|
|
204
|
-
* `pending` true if test is scheduled for execution and false if a test has finished
|
|
205
|
-
* `tags` array of tags for this test
|
|
206
|
-
* `artifacts` list of files attached to this test. Screenshots, videos and other files can be saved here and shared accross different reporters
|
|
207
|
-
* `file` path to a file with a test
|
|
208
|
-
* `steps` array of executed steps (available only in `test.passed`, `test.failed`, `test.finished` event)
|
|
209
|
-
* `skipInfo` additional test options when test skipped
|
|
210
|
-
* * `message` string with reason for skip
|
|
211
|
-
* * `description` string with test body
|
|
212
|
-
and others
|
|
213
|
-
|
|
214
|
-
#### Step Object
|
|
215
|
-
|
|
216
|
-
Step events provide step objects with following fields:
|
|
217
|
-
|
|
218
|
-
* `name` name of a step, like 'see', 'click', and others
|
|
219
|
-
* `actor` current actor, in most cases it is `I`
|
|
220
|
-
* `helper` current helper instance used to execute this step
|
|
221
|
-
* `helperMethod` corresponding helper method, in most cases is the same as `name`
|
|
222
|
-
* `status` status of a step (passed or failed)
|
|
223
|
-
* `prefix` if a step is executed inside `within` block contain within text, like: 'Within .js-signup-form'.
|
|
224
|
-
* `args` passed arguments
|
|
225
|
-
|
|
226
|
-
Whenever you execute tests with `--verbose` option you will see registered events and promises executed by a recorder.
|
|
227
|
-
|
|
228
|
-
## Custom Runner
|
|
229
|
-
|
|
230
|
-
You can run CodeceptJS tests from your script.
|
|
231
|
-
|
|
232
|
-
```js
|
|
233
|
-
const { codecept: Codecept } = require('codeceptjs');
|
|
234
|
-
|
|
235
|
-
// define main config
|
|
236
|
-
const config = {
|
|
237
|
-
helpers: {
|
|
238
|
-
WebDriver: {
|
|
239
|
-
browser: 'chrome',
|
|
240
|
-
url: 'http://localhost'
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
const opts = { steps: true };
|
|
246
|
-
|
|
247
|
-
// run CodeceptJS inside async function
|
|
248
|
-
(async () => {
|
|
249
|
-
const codecept = new Codecept(config, options);
|
|
250
|
-
codecept.init(__dirname);
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
await codecept.bootstrap();
|
|
254
|
-
codecept.loadTests('**_test.js');
|
|
255
|
-
// run tests
|
|
256
|
-
await codecept.run(test);
|
|
257
|
-
} catch (err) {
|
|
258
|
-
printError(err);
|
|
259
|
-
process.exitCode = 1;
|
|
260
|
-
} finally {
|
|
261
|
-
await codecept.teardown();
|
|
262
|
-
}
|
|
263
|
-
})();
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
> Also, you can run tests inside workers in a custom scripts. Please refer to the [parallel execution](/parallel) guide for more details.
|
package/docs/locators.md
DELETED
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
permalink: /locators
|
|
3
|
-
title: Locators
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Locators
|
|
7
|
-
|
|
8
|
-
CodeceptJS provides flexible strategies for locating elements:
|
|
9
|
-
|
|
10
|
-
* [CSS and XPath locators](#css-and-xpath)
|
|
11
|
-
* [Semantic locators](#semantic-locators): by link text, by button text, by field names, etc.
|
|
12
|
-
* [Locator Builder](#locator-builder)
|
|
13
|
-
* [ID locators](#id-locators): by CSS id or by accessibility id
|
|
14
|
-
* [Custom Locator Strategies](#custom-locators): by data attributes or whatever you prefer.
|
|
15
|
-
* [Shadow DOM](/shadow): to access shadow dom elements
|
|
16
|
-
* [React](/react): to access React elements by component names and props
|
|
17
|
-
|
|
18
|
-
Most methods in CodeceptJS use locators which can be either a string or an object.
|
|
19
|
-
|
|
20
|
-
If the locator is an object, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, `react`, `class` or `shadow`) and the value being the locator itself. This is called a "strict" locator.
|
|
21
|
-
|
|
22
|
-
Examples:
|
|
23
|
-
|
|
24
|
-
* {id: 'foo'} matches `<div id="foo">`
|
|
25
|
-
* {name: 'foo'} matches `<div name="foo">`
|
|
26
|
-
* {css: 'input[type=input][value=foo]'} matches `<input type="input" value="foo">`
|
|
27
|
-
* {xpath: "//input[@type='submit'][contains(@value, 'foo')]"} matches `<input type="submit" value="foobar">`
|
|
28
|
-
* {class: 'foo'} matches `<div class="foo">`
|
|
29
|
-
|
|
30
|
-
Writing good locators can be tricky.
|
|
31
|
-
The Mozilla team has written an excellent guide titled [Writing reliable locators for Selenium and WebDriver tests](https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/).
|
|
32
|
-
|
|
33
|
-
If you prefer, you may also pass a string for the locator. This is called a "fuzzy" locator.
|
|
34
|
-
In this case, CodeceptJS uses a variety of heuristics (depending on the exact method called) to determine what element you're referring to. If you are locating a clickable element or an input element, CodeceptJS will use [semantic locators](#semantic-locators).
|
|
35
|
-
|
|
36
|
-
For example, here's the heuristic used for the `fillField` method:
|
|
37
|
-
|
|
38
|
-
1. Does the locator look like an ID selector (e.g. "#foo")? If so, try to find an input element matching that ID.
|
|
39
|
-
2. If nothing found, check if locator looks like a CSS selector. If so, run it.
|
|
40
|
-
3. If nothing found, check if locator looks like an XPath expression. If so, run it.
|
|
41
|
-
4. If nothing found, check if there is an input element with a corresponding name.
|
|
42
|
-
5. If nothing found, check if there is a label with specified text for input element.
|
|
43
|
-
6. If nothing found, throw an `ElementNotFound` exception.
|
|
44
|
-
|
|
45
|
-
> ⚠ Be warned that fuzzy locators can be significantly slower than strict locators. If speed is a concern, it's recommended you stick with explicitly specifying the locator type via object syntax.
|
|
46
|
-
|
|
47
|
-
It is recommended to avoid using implicit CSS locators in methods like `fillField` or `click`, where semantic locators are allowed.
|
|
48
|
-
Use locator type to speed up search by various locator strategies.
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
// will search for "input[type=password]" text before trying to search by CSS
|
|
52
|
-
I.fillField('input[type=password]', '123456');
|
|
53
|
-
// replace with strict locator
|
|
54
|
-
I.fillField({ css: 'input[type=password]' }, '123456');
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## CSS and XPath
|
|
58
|
-
|
|
59
|
-
Both CSS and XPath is supported. Usually CodeceptJS can guess locator's type:
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
// select by CSS
|
|
63
|
-
I.seeElement('.user .profile');
|
|
64
|
-
I.seeElement('#user-name');
|
|
65
|
-
|
|
66
|
-
// select by XPath
|
|
67
|
-
I.seeElement('//table/tr/td[position()=3]');
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
To specify exact locator type use **strict locators**:
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
// it's not clear that 'button' is actual CSS locator
|
|
74
|
-
I.seeElement({ css: 'button' });
|
|
75
|
-
|
|
76
|
-
// it's not clear that 'descendant::table/tr' is actual XPath locator
|
|
77
|
-
I.seeElement({ xpath: 'descendant::table/tr' });
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
> ℹ Use [Locator Advicer](https://davertmik.github.io/locator/) to check quality of your locators.
|
|
81
|
-
|
|
82
|
-
## Semantic Locators
|
|
83
|
-
|
|
84
|
-
CodeceptJS can guess an element's locator from context.
|
|
85
|
-
For example, when clicking CodeceptJS will try to find a link or button by their text
|
|
86
|
-
When typing into a field this field can be located by its name, placeholder.
|
|
87
|
-
|
|
88
|
-
```js
|
|
89
|
-
I.click('Sign In');
|
|
90
|
-
I.fillField('Username', 'davert');
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Various strategies are used to locate semantic elements. However, they may run slower than specifying locator by XPath or CSS.
|
|
94
|
-
|
|
95
|
-
## Locator Builder
|
|
96
|
-
|
|
97
|
-
CodeceptJS provides a fluent builder to compose custom locators in JavaScript. Use `locate` function to start.
|
|
98
|
-
|
|
99
|
-
To locate `a` element inside `label` with text: 'Hello' use:
|
|
100
|
-
|
|
101
|
-
```js
|
|
102
|
-
locate('a')
|
|
103
|
-
.withAttr({ href: '#' })
|
|
104
|
-
.inside(locate('label').withText('Hello'));
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
which will produce following XPath:
|
|
108
|
-
|
|
109
|
-
```
|
|
110
|
-
.//a[@href = '#'][ancestor::label[contains(., 'Hello')]]
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Locator builder accepts both XPath and CSS as parameters but converts them to XPath as more feature-rich format.
|
|
114
|
-
Sometimes provided locators can get very long so it's recommended to simplify the output by providing a brief description for generated XPath:
|
|
115
|
-
|
|
116
|
-
```js
|
|
117
|
-
locate('//table')
|
|
118
|
-
.find('a')
|
|
119
|
-
.withText('Edit')
|
|
120
|
-
.as('edit button')
|
|
121
|
-
// will be printed as 'edit button'
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
`locate` has following methods:
|
|
125
|
-
|
|
126
|
-
#### find
|
|
127
|
-
|
|
128
|
-
Finds an element inside a located.
|
|
129
|
-
|
|
130
|
-
```js
|
|
131
|
-
// find td inside a table
|
|
132
|
-
locate('table').find('td');
|
|
133
|
-
```
|
|
134
|
-
Switches current element to found one.
|
|
135
|
-
Can accept another `locate` call or strict locator.
|
|
136
|
-
|
|
137
|
-
#### withAttr
|
|
138
|
-
|
|
139
|
-
Find an element with provided attributes
|
|
140
|
-
|
|
141
|
-
```js
|
|
142
|
-
// find input with placeholder 'Type in name'
|
|
143
|
-
locate('input').withAttr({ placeholder: 'Type in name' });
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
#### withChild
|
|
147
|
-
|
|
148
|
-
Finds an element which contains a child element provided:
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
// finds form with <select> inside it
|
|
152
|
-
locate('form').withChild('select');
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
#### withDescendant
|
|
156
|
-
|
|
157
|
-
Finds an element which contains a descendant element provided:
|
|
158
|
-
|
|
159
|
-
```js
|
|
160
|
-
// finds form with <select> which is the descendant it
|
|
161
|
-
locate('form').withDescendant('select');
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
#### withText
|
|
165
|
-
|
|
166
|
-
Find an element containing a text
|
|
167
|
-
|
|
168
|
-
```js
|
|
169
|
-
locate('span').withText('Warning');
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
#### withTextEquals
|
|
173
|
-
|
|
174
|
-
Find an element with exact text
|
|
175
|
-
|
|
176
|
-
```js
|
|
177
|
-
locate('button').withTextEquals('Add');
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### first
|
|
181
|
-
|
|
182
|
-
Get first element:
|
|
183
|
-
|
|
184
|
-
```js
|
|
185
|
-
locate('#table td').first();
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
#### last
|
|
189
|
-
|
|
190
|
-
Get last element:
|
|
191
|
-
|
|
192
|
-
```js
|
|
193
|
-
locate('#table td').last();
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
#### at
|
|
197
|
-
|
|
198
|
-
Get element at position:
|
|
199
|
-
|
|
200
|
-
```js
|
|
201
|
-
// first element
|
|
202
|
-
locate('#table td').at(1);
|
|
203
|
-
// second element
|
|
204
|
-
locate('#table td').at(2);
|
|
205
|
-
// second element from end
|
|
206
|
-
locate('#table td').at(-2);
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
#### inside
|
|
210
|
-
|
|
211
|
-
Finds an element which contains an provided ancestor:
|
|
212
|
-
|
|
213
|
-
```js
|
|
214
|
-
// finds `select` element inside #user_profile
|
|
215
|
-
locate('select').inside('form#user_profile');
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
#### before
|
|
219
|
-
|
|
220
|
-
Finds element located before the provided one
|
|
221
|
-
|
|
222
|
-
```js
|
|
223
|
-
// finds `button` before .btn-cancel
|
|
224
|
-
locate('button').before('.btn-cancel');
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
#### after
|
|
228
|
-
|
|
229
|
-
Finds element located after the provided one
|
|
230
|
-
|
|
231
|
-
```js
|
|
232
|
-
// finds `button` after .btn-cancel
|
|
233
|
-
locate('button').after('.btn-cancel');
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
## ID Locators
|
|
237
|
-
|
|
238
|
-
ID locators are best to select the exact semantic element in web and mobile testing:
|
|
239
|
-
|
|
240
|
-
* `#user` or `{ id: 'user' }` finds element with id="user"
|
|
241
|
-
* `~user` finds element with accessibility id "user" (in Mobile testing) or with `aria-label=user`.
|
|
242
|
-
|
|
243
|
-
## Custom Locators
|
|
244
|
-
|
|
245
|
-
CodeceptJS allows to create custom locator strategies and use them in tests. This way you can define your own handling of elements using specially prepared attributes of elements.
|
|
246
|
-
|
|
247
|
-
What if you use special test attributes for locators such as `data-qa`, `data-test`, `test-id`, etc.
|
|
248
|
-
We created [customLocator plugin](/plugins#customlocator) to declare rules for locating element.
|
|
249
|
-
|
|
250
|
-
Instead of writing a full CSS locator like `[data-qa-id=user_name]` simplify it to `$user_name`.
|
|
251
|
-
|
|
252
|
-
```js
|
|
253
|
-
// replace this:
|
|
254
|
-
I.click({ css: '[data-test-id=register_button]'});
|
|
255
|
-
// with this:
|
|
256
|
-
I.click('$register_button');
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
This plugin requires two options: locator prefix and actual attribute to match.
|
|
260
|
-
|
|
261
|
-
> ℹ See [customLocator Plugin](/plugins#customlocator) reference to learn how to set it up.
|
|
262
|
-
|
|
263
|
-
If you need more control over custom locators see how declare them manually without using a customLocator plugin.
|
|
264
|
-
|
|
265
|
-
#### Custom Strict Locators
|
|
266
|
-
|
|
267
|
-
If use locators of `data-element` attribute you can implement a strategy, which will allow you to use `{ data: 'my-element' }` as a valid locator.
|
|
268
|
-
|
|
269
|
-
Custom locators should be implemented in a plugin or a bootstrap script using internal CodeceptJS API:
|
|
270
|
-
|
|
271
|
-
```js
|
|
272
|
-
// inside a plugin or a bootstrap script:
|
|
273
|
-
codeceptjs.locator.addFilter((providedLocator, locatorObj) => {
|
|
274
|
-
// providedLocator - a locator in a format it was provided
|
|
275
|
-
// locatorObj - a standrard locator object.
|
|
276
|
-
if (providedLocator.data) {
|
|
277
|
-
locatorObj.type = 'css';
|
|
278
|
-
locatorObj.value = `[data-element=${providedLocator.data}]`
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
That's all. New locator type is ready to use:
|
|
284
|
-
|
|
285
|
-
```js
|
|
286
|
-
I.click({ data: 'user-login' });
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
#### Custom String Locators
|
|
290
|
-
|
|
291
|
-
What if we want to locators prefixed with `=` to match elements with exact text value.
|
|
292
|
-
We can do that too:
|
|
293
|
-
|
|
294
|
-
```js
|
|
295
|
-
// inside a plugin or a bootstrap script:
|
|
296
|
-
codeceptjs.locator.addFilter((providedLocator, locatorObj) => {
|
|
297
|
-
if (typeof providedLocator === 'string') {
|
|
298
|
-
// this is a string
|
|
299
|
-
if (providedLocator[0] === '=') {
|
|
300
|
-
locatorObj.value = `.//*[text()="${providedLocator.substring(1)}"]`;
|
|
301
|
-
locatorObj.type = 'xpath';
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
```
|
|
306
|
-
New locator strategy is ready to use:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
```js
|
|
310
|
-
I.click('=Login');
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
#### Custom Strategy Locators
|
|
314
|
-
|
|
315
|
-
CodeceptJS provides the option to specify custom locators that uses Custom Locator Strategies defined in the WebDriver configuration. It uses the WebDriverIO's [custom$](https://webdriver.io/docs/api/browser/custom$.html) locators internally to locate the elements on page.
|
|
316
|
-
To use the defined Custom Locator Strategy add your custom strategy to your configuration.
|
|
317
|
-
|
|
318
|
-
```js
|
|
319
|
-
// in codecept.conf.js
|
|
320
|
-
|
|
321
|
-
const myStrat = (selector) => {
|
|
322
|
-
return document.querySelectorAll(selector)
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// under WebDriver Helpers Configuration
|
|
326
|
-
WebDriver: {
|
|
327
|
-
...
|
|
328
|
-
customLocatorStrategies: {
|
|
329
|
-
custom: myStrat
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
```js
|
|
335
|
-
I.click({custom: 'my-shadow-element-unique-css'})
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
> For more details on locator object see [Locator](https://github.com/codeceptjs/CodeceptJS/blob/master/lib/locator.js) class implementation.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
## Automating React Native apps
|
|
2
|
-
|
|
3
|
-
### Problem
|
|
4
|
-
|
|
5
|
-
> ⚠️ **NOTE**: This problem is not actual starting from `react-native@0.65.x` [CHANGELOG](https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#android-specific-9), [#381fb3](https://github.com/facebook/react-native/commit/381fb395ad9d2d48717a5d082aaedbecdd804554)
|
|
6
|
-
|
|
7
|
-
Let's say we have a React Native app with component defined like this
|
|
8
|
-
```html
|
|
9
|
-
<Button testID='someButton'>My button</Button>
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
If you will try to execute a simple test like
|
|
13
|
-
```js
|
|
14
|
-
I.tap('~someButton')
|
|
15
|
-
```
|
|
16
|
-
it will work correctly on iOS (with XUITest driver), but on Android's UIAutomator2 it will give you an error
|
|
17
|
-
```
|
|
18
|
-
Touch actions like "tap" need at least some kind of position information like "element", "x" or "y" options, you've none given.
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
This happens because of the way React Native implements `testID` for Android, it puts provided value into the [View tag](https://developer.android.com/reference/android/view/View#tags),
|
|
22
|
-
as could be found in the [source code](https://github.com/facebook/react-native/blob/19a88d7f4addcd9f95fd4908d50db37b3604b5b1/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java#L114).
|
|
23
|
-
But UIAutomator doesn't have any means to work with view tags.
|
|
24
|
-
|
|
25
|
-
### Solutions
|
|
26
|
-
As many resources suggest (like [here](https://github.com/appium/appium/issues/6025#issuecomment-406141946) or [here](https://github.com/facebook/react-native/issues/7135)),
|
|
27
|
-
you could use `testID` for iOS and `accesibilityLabel` for Android, but `accessibilityLabel` is a user-facing text that's intended for ... accesibility,
|
|
28
|
-
not for UI tests, and you will need to switch it off for production builds.
|
|
29
|
-
|
|
30
|
-
Another way to solve this issue is to use Espresso driver for Android.
|
|
31
|
-
At first you need to enable Espresso driver for your Android configuration.
|
|
32
|
-
You could do it just by changing `automationName` in the `helpers` section of the config file:
|
|
33
|
-
```js
|
|
34
|
-
{
|
|
35
|
-
//...
|
|
36
|
-
helpers: {
|
|
37
|
-
Appium: {
|
|
38
|
-
app: '/path/to/apk.apk',
|
|
39
|
-
platform: 'Android',
|
|
40
|
-
desiredCapabilities: {
|
|
41
|
-
automationName: 'Espresso',
|
|
42
|
-
platformVersion: '9',
|
|
43
|
-
deviceName: 'Android Emulator'
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
//...
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
Then you could locate components using XPath expression:
|
|
51
|
-
```js
|
|
52
|
-
I.tap({android: '//*[@view-tag="someButton"]', ios: '~someButton'})
|
|
53
|
-
```
|
|
54
|
-
This way test would work for both platforms without any changes in code.
|
|
55
|
-
To simplify things further you could write a helper function:
|
|
56
|
-
```js
|
|
57
|
-
function tid(id) {
|
|
58
|
-
return {
|
|
59
|
-
android: `//*[@view-tag="${id}"]`,
|
|
60
|
-
ios: '~' + id
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
Now test will look more concise
|
|
65
|
-
```js
|
|
66
|
-
I.tap(tid('someButton'));
|
|
67
|
-
```
|