codeceptjs 2.1.3 → 2.2.1
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 +125 -37
- package/README.md +15 -22
- package/bin/codecept.js +4 -1
- package/docs/acceptance.md +44 -1
- package/docs/advanced.md +1 -1
- package/docs/angular.md +6 -9
- package/docs/basics.md +388 -75
- package/docs/bdd.md +4 -3
- package/docs/best.md +1 -1
- package/docs/books.md +31 -0
- package/docs/build/Appium.js +215 -176
- package/docs/build/Nightmare.js +618 -489
- package/docs/build/Polly.js +189 -0
- package/docs/build/Protractor.js +747 -608
- package/docs/build/Puppeteer.js +914 -633
- package/docs/build/REST.js +1 -1
- package/docs/build/TestCafe.js +1835 -0
- package/docs/build/WebDriver.js +861 -805
- package/docs/build/WebDriverIO.js +616 -617
- package/docs/changelog.md +410 -316
- package/docs/commands.md +6 -6
- package/docs/community-helpers.md +2 -0
- package/docs/detox.md +235 -0
- package/docs/examples.md +23 -0
- package/docs/helpers/ApiDataFactory.md +11 -10
- package/docs/helpers/Appium.md +130 -61
- package/docs/helpers/Detox.md +579 -0
- package/docs/helpers/FileSystem.md +2 -1
- package/docs/helpers/Mochawesome.md +1 -0
- package/docs/helpers/Nightmare.md +348 -128
- package/docs/helpers/Polly.md +85 -0
- package/docs/helpers/Protractor.md +451 -184
- package/docs/helpers/Puppeteer-firefox.md +55 -0
- package/docs/helpers/Puppeteer.md +619 -183
- package/docs/helpers/REST.md +17 -16
- package/docs/helpers/SeleniumWebdriver.md +9 -8
- package/docs/helpers/TestCafe.md +1168 -0
- package/docs/helpers/WebDriver.md +600 -291
- package/docs/helpers/WebDriverIO.md +393 -278
- package/docs/helpers.md +37 -18
- package/docs/locators.md +2 -0
- package/docs/mobile-react-native-locators.md +64 -0
- package/docs/mobile.md +5 -0
- package/docs/plugins.md +54 -13
- package/docs/puppeteer.md +74 -26
- package/docs/quickstart.md +47 -12
- package/docs/react.md +67 -0
- package/docs/reports.md +1 -1
- package/docs/{webapi/_keys.mustache → shared/keys.mustache} +0 -0
- package/docs/shared/react.mustache +1 -0
- package/docs/testcafe.md +157 -0
- package/docs/videos.md +19 -0
- package/docs/webapi/amOnPage.mustache +1 -1
- package/docs/webapi/appendField.mustache +2 -2
- package/docs/webapi/attachFile.mustache +2 -2
- package/docs/webapi/checkOption.mustache +2 -2
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/clearField.mustache +1 -1
- package/docs/webapi/click.mustache +2 -2
- package/docs/webapi/clickLink.mustache +3 -3
- package/docs/webapi/dontSee.mustache +6 -3
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +7 -1
- package/docs/webapi/dontSeeCookie.mustache +5 -1
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +6 -1
- package/docs/webapi/dontSeeElement.mustache +5 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +5 -1
- package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +7 -2
- package/docs/webapi/dontSeeInSource.mustache +5 -1
- package/docs/webapi/dontSeeInTitle.mustache +5 -1
- package/docs/webapi/doubleClick.mustache +2 -2
- package/docs/webapi/downloadFile.mustache +2 -2
- package/docs/webapi/dragAndDrop.mustache +2 -2
- package/docs/webapi/dragSlider.mustache +2 -2
- package/docs/webapi/executeAsyncScript.mustache +1 -1
- package/docs/webapi/executeScript.mustache +1 -1
- package/docs/webapi/fillField.mustache +2 -2
- package/docs/webapi/grabAttributeFrom.mustache +3 -2
- package/docs/webapi/grabBrowserLogs.mustache +3 -1
- package/docs/webapi/grabCookie.mustache +2 -1
- package/docs/webapi/grabCssPropertyFrom.mustache +3 -2
- package/docs/webapi/grabCurrentUrl.mustache +3 -1
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +19 -0
- package/docs/webapi/grabHTMLFrom.mustache +2 -1
- package/docs/webapi/grabNumberOfOpenTabs.mustache +4 -2
- package/docs/webapi/grabNumberOfVisibleElements.mustache +3 -2
- package/docs/webapi/grabPageScrollPosition.mustache +3 -1
- package/docs/webapi/grabSource.mustache +3 -1
- package/docs/webapi/grabTextFrom.mustache +2 -1
- package/docs/webapi/grabTitle.mustache +3 -1
- package/docs/webapi/grabValueFrom.mustache +2 -1
- package/docs/webapi/moveCursorTo.mustache +3 -3
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/resizeWindow.mustache +2 -2
- package/docs/webapi/rightClick.mustache +2 -2
- package/docs/webapi/saveScreenshot.mustache +3 -3
- package/docs/webapi/say.mustache +2 -2
- package/docs/webapi/scrollPageToBottom.mustache +1 -1
- package/docs/webapi/scrollPageToTop.mustache +1 -1
- package/docs/webapi/scrollTo.mustache +3 -3
- package/docs/webapi/see.mustache +2 -2
- package/docs/webapi/seeAttributesOnElements.mustache +3 -3
- package/docs/webapi/seeCheckboxIsChecked.mustache +2 -1
- package/docs/webapi/seeCookie.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +2 -2
- package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInCurrentUrl.mustache +1 -1
- package/docs/webapi/seeInField.mustache +2 -2
- package/docs/webapi/seeInSource.mustache +1 -1
- package/docs/webapi/seeInTitle.mustache +5 -1
- package/docs/webapi/seeNumberOfElements.mustache +10 -0
- package/docs/webapi/seeNumberOfVisibleElements.mustache +2 -2
- package/docs/webapi/selectOption.mustache +2 -2
- package/docs/webapi/setCookie.mustache +1 -1
- package/docs/webapi/switchTo.mustache +6 -1
- package/docs/webapi/uncheckOption.mustache +2 -2
- package/docs/webapi/wait.mustache +1 -2
- package/docs/webapi/waitForDetached.mustache +3 -3
- package/docs/webapi/waitForElement.mustache +2 -2
- package/docs/webapi/waitForEnabled.mustache +1 -1
- package/docs/webapi/waitForFunction.mustache +3 -3
- package/docs/webapi/waitForInvisible.mustache +3 -3
- package/docs/webapi/waitForText.mustache +3 -3
- package/docs/webapi/waitForValue.mustache +3 -3
- package/docs/webapi/waitForVisible.mustache +3 -3
- package/docs/webapi/waitInUrl.mustache +2 -2
- package/docs/webapi/waitNumberOfVisibleElements.mustache +3 -3
- package/docs/webapi/waitToHide.mustache +3 -3
- package/docs/webapi/waitUntil.mustache +3 -3
- package/docs/webapi/waitUrlEquals.mustache +2 -2
- package/docs/webdriver.md +453 -0
- package/lib/codecept.js +11 -9
- package/lib/command/definitions.js +183 -30
- package/lib/command/gherkin/snippets.js +29 -9
- package/lib/command/init.js +31 -9
- package/lib/command/run-multiple.js +46 -59
- package/lib/command/utils.js +1 -1
- package/lib/container.js +30 -4
- package/lib/data/dataScenarioConfig.js +18 -0
- package/lib/helper/Appium.js +24 -24
- package/lib/helper/Nightmare.js +81 -84
- package/lib/helper/Polly.js +189 -0
- package/lib/helper/Protractor.js +96 -86
- package/lib/helper/Puppeteer.js +238 -113
- package/lib/helper/REST.js +1 -1
- package/lib/helper/TestCafe.js +1257 -0
- package/lib/helper/WebDriver.js +217 -277
- package/lib/helper/WebDriverIO.js +75 -75
- package/lib/helper/clientscripts/nightmare.js +8 -0
- package/lib/helper/extras/React.js +55 -0
- package/lib/helper/testcafe/testControllerHolder.js +42 -0
- package/lib/helper/testcafe/testcafe-utils.js +63 -0
- package/lib/history.js +39 -0
- package/lib/hooks.js +25 -1
- package/lib/interfaces/gherkin.js +17 -1
- package/lib/interfaces/scenarioConfig.js +2 -2
- package/lib/listener/config.js +3 -3
- package/lib/locator.js +6 -0
- package/lib/pause.js +22 -1
- package/lib/plugin/allure.js +63 -0
- package/lib/plugin/autoLogin.js +65 -16
- package/lib/plugin/puppeteerCoverage.js +6 -1
- package/lib/plugin/stepByStepReport.js +4 -3
- package/lib/scenario.js +23 -17
- package/lib/step.js +5 -2
- package/lib/ui.js +1 -1
- package/lib/utils.js +70 -20
- package/package.json +20 -19
- package/translations/de-DE.js +69 -0
- package/translations/index.js +1 -0
- package/docs/video.md +0 -26
package/docs/helpers.md
CHANGED
|
@@ -24,22 +24,20 @@ codeceptjs gh
|
|
|
24
24
|
|
|
25
25
|
This command generates a basic helper and appends it to `helpers` section of config file:
|
|
26
26
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
```js
|
|
28
|
+
helpers: {
|
|
29
|
+
WebDriver: { },
|
|
30
|
+
MyHelper: {
|
|
31
|
+
require: './path/to/module'
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Helpers are ES6 classes inherited from [corresponding abstract class](https://github.com/Codeception/CodeceptJS/blob/master/lib/helper.js).
|
|
37
|
-
Generated Helper will be added to `codecept.
|
|
37
|
+
Generated Helper will be added to `codecept.conf.js` config. It should look like this:
|
|
38
38
|
|
|
39
39
|
```js
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let Helper = codecept_helper;
|
|
40
|
+
const Helper = codecept_helper;
|
|
43
41
|
|
|
44
42
|
class MyHelper extends Helper {
|
|
45
43
|
|
|
@@ -79,11 +77,10 @@ Method `seeAuthentication` will use `client` instance of WebDriver to get access
|
|
|
79
77
|
Standard NodeJS assertion library will be used (you can use any).
|
|
80
78
|
|
|
81
79
|
```js
|
|
82
|
-
|
|
83
|
-
let Helper = codecept_helper;
|
|
80
|
+
const Helper = codecept_helper;
|
|
84
81
|
|
|
85
82
|
// use any assertion library you like
|
|
86
|
-
|
|
83
|
+
const assert = require('assert');
|
|
87
84
|
|
|
88
85
|
class MyHelper extends Helper {
|
|
89
86
|
/**
|
|
@@ -111,6 +108,29 @@ class MyHelper extends Helper {
|
|
|
111
108
|
module.exports = MyHelper;
|
|
112
109
|
```
|
|
113
110
|
|
|
111
|
+
## Puppeteer Example
|
|
112
|
+
|
|
113
|
+
Puppteer has [nice and elegant API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md) which you can use inside helpers. Access `page` instance via `this.helpers.Puppeteer.page` from inside a helper.
|
|
114
|
+
|
|
115
|
+
Let's see how we can use [emulate](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageemulateoptions) function to emulate iPhone browser in a test.
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
const Helper = codecept_helper;
|
|
119
|
+
const puppeteer = require('puppeteer');
|
|
120
|
+
const iPhone = puppeteer.devices['iPhone 6'];
|
|
121
|
+
|
|
122
|
+
class MyHelper extends Helper {
|
|
123
|
+
|
|
124
|
+
async emulateIPhone() {
|
|
125
|
+
const { page } = this.helpers.Puppeteer;
|
|
126
|
+
await page.emulate(iPhone);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = MyHelper;
|
|
132
|
+
```
|
|
133
|
+
|
|
114
134
|
## Protractor Example
|
|
115
135
|
|
|
116
136
|
Protractor example demonstrates usage of global `element` and `by` objects.
|
|
@@ -118,14 +138,13 @@ However `browser` should be accessed from a helper instance via `this.helpers['P
|
|
|
118
138
|
We also use `chai-as-promised` library to have nice assertions with promises.
|
|
119
139
|
|
|
120
140
|
```js
|
|
121
|
-
|
|
122
|
-
let Helper = codecept_helper;
|
|
141
|
+
const Helper = codecept_helper;
|
|
123
142
|
|
|
124
143
|
// use any assertion library you like
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
const chai = require('chai');
|
|
145
|
+
const chaiAsPromised = require('chai-as-promised');
|
|
127
146
|
chai.use(chaiAsPromised);
|
|
128
|
-
|
|
147
|
+
const expect = chai.expect;
|
|
129
148
|
|
|
130
149
|
class MyHelper extends Helper {
|
|
131
150
|
/**
|
|
@@ -136,7 +155,7 @@ class MyHelper extends Helper {
|
|
|
136
155
|
this.helpers['Protractor'].browser.refresh();
|
|
137
156
|
|
|
138
157
|
// you can use `element` as well as in protractor
|
|
139
|
-
|
|
158
|
+
const history = element.all(by.repeater('result in memory'));
|
|
140
159
|
|
|
141
160
|
// use chai as promised for better assertions
|
|
142
161
|
// end your method with `return` to handle promises
|
package/docs/locators.md
CHANGED
|
@@ -64,6 +64,8 @@ I.seeElement({ css: 'button' });
|
|
|
64
64
|
I.seeElement({ xpath: 'descendant::table/tr' });
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
> ℹ Use [Locator Advicer](https://davertmik.github.io/locator/) to check quality of your locators.
|
|
68
|
+
|
|
67
69
|
## Semantic Locators
|
|
68
70
|
|
|
69
71
|
CodeceptJS can guess an element's locator from context.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
## Automating React Native apps
|
|
2
|
+
|
|
3
|
+
### Problem
|
|
4
|
+
Let's say we have a React Native app with component defined like this
|
|
5
|
+
```html
|
|
6
|
+
<Button testID='someButton'>My button</Button>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
If you will try to execute a simple test like
|
|
10
|
+
```js
|
|
11
|
+
I.tap('~someButton')
|
|
12
|
+
```
|
|
13
|
+
it will work correctly on iOS (with XUITest driver), but on Android's UIAutomator2 it will give you an error
|
|
14
|
+
```
|
|
15
|
+
Touch actions like "tap" need at least some kind of position information like "element", "x" or "y" options, you've none given.
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
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),
|
|
19
|
+
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).
|
|
20
|
+
But UIAutomator doesn't have any means to work with view tags.
|
|
21
|
+
|
|
22
|
+
### Solutions
|
|
23
|
+
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)),
|
|
24
|
+
you could use `testID` for iOS and `accesibilityLabel` for Android, but `accessibilityLabel` is a user-facing text that's intended for ... accesibility,
|
|
25
|
+
not for UI tests, and you will need to switch it off for production builds.
|
|
26
|
+
|
|
27
|
+
Another way to solve this issue is to use Espresso driver for Android.
|
|
28
|
+
At first you need to enable Espresso driver for your Android configuration.
|
|
29
|
+
You could do it just by changing `automationName` in the `helpers` section of the config file:
|
|
30
|
+
```js
|
|
31
|
+
{
|
|
32
|
+
//...
|
|
33
|
+
helpers: {
|
|
34
|
+
Appium: {
|
|
35
|
+
app: '/path/to/apk.apk',
|
|
36
|
+
platform: 'Android',
|
|
37
|
+
desiredCapabilities: {
|
|
38
|
+
automationName: 'Espresso',
|
|
39
|
+
platformVersion: '9',
|
|
40
|
+
deviceName: 'Android Emulator'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//...
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
Then you could locate components using XPath expression:
|
|
48
|
+
```js
|
|
49
|
+
I.tap({android: '//*[@view-tag="someButton"]', ios: '~someButton'})
|
|
50
|
+
```
|
|
51
|
+
This way test would work for both platforms without any changes in code.
|
|
52
|
+
To simplify things further you could write a helper function:
|
|
53
|
+
```js
|
|
54
|
+
function tid(id) {
|
|
55
|
+
return {
|
|
56
|
+
android: `//*[@view-tag="${id}"]`,
|
|
57
|
+
ios: '~' + id
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
Now test will look more concise
|
|
62
|
+
```js
|
|
63
|
+
I.tap(tid('someButton'));
|
|
64
|
+
```
|
package/docs/mobile.md
CHANGED
|
@@ -173,6 +173,8 @@ In both Android and iPhone elements are defined in XML format and can be searche
|
|
|
173
173
|
I.seeElement('//android.widget.ScrollView/android.widget.LinearLayout')'
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
+
> Despite showing XPath in this guide we **do not recommend using XPath for testing iOS native apps. XPath runs very slow on iOS. Consider using ID or Accessibility ID locators instead.
|
|
177
|
+
|
|
176
178
|
CSS locators are not supported in native mobile apps, you need to switch to web context to use them.
|
|
177
179
|
|
|
178
180
|
Elements can also be located by their accessability id, available both at Android and iOS.
|
|
@@ -181,6 +183,9 @@ Accessibility id is recommended to use for locating element, as it rarely change
|
|
|
181
183
|
* iOS uses [UIAccessibilityIdentification](https://developer.apple.com/documentation/uikit/uiaccessibilityidentification)
|
|
182
184
|
* Android `accessibility id` matches the content-description
|
|
183
185
|
* Web view uses `[aria-label]` attribute as accessibility id
|
|
186
|
+
* For [React Native for Android see our special guide](mobile-react-native-locators.md).
|
|
187
|
+
|
|
188
|
+
> If you test React Native application, consider using [Detox helper](/detox) for faster tests.
|
|
184
189
|
|
|
185
190
|
Add `~` prefix to search for element by its accessibility id:
|
|
186
191
|
|
package/docs/plugins.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
id: plugins
|
|
3
3
|
title: Plugins
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
6
7
|
|
|
7
8
|
## allure
|
|
@@ -54,6 +55,12 @@ const allure = codeceptjs.container.plugins('allure');
|
|
|
54
55
|
|
|
55
56
|
- `addAttachment(name, buffer, type)` - add an attachment to current test / suite
|
|
56
57
|
- `addLabel(name, value)` - adds a label to current test
|
|
58
|
+
- `severity(value)` - adds severity label
|
|
59
|
+
- `epic(value)` - adds epic label
|
|
60
|
+
- `feature(value)` - adds feature label
|
|
61
|
+
- `story(value)` - adds story label
|
|
62
|
+
- `issue(value)` - adds issue label
|
|
63
|
+
- `setDescription(description, type)` - sets a description
|
|
57
64
|
|
|
58
65
|
### Parameters
|
|
59
66
|
|
|
@@ -217,19 +224,21 @@ helpers: {
|
|
|
217
224
|
},
|
|
218
225
|
plugins: {
|
|
219
226
|
autoLogin: {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
I
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
I
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
users: {
|
|
228
|
+
admin: {
|
|
229
|
+
login: (I) => {
|
|
230
|
+
I.amOnPage('/login');
|
|
231
|
+
I.fillField('email', 'admin@site.com');
|
|
232
|
+
I.fillField('password', '123456');
|
|
233
|
+
I.click('Login');
|
|
234
|
+
},
|
|
235
|
+
check: (I) => {
|
|
236
|
+
I.amOnPage('/dashboard');
|
|
237
|
+
I.see('Admin', '.navbar');
|
|
238
|
+
},
|
|
239
|
+
fetch: () => {}, // empty function
|
|
240
|
+
restore: () => {}, // empty funciton
|
|
241
|
+
}
|
|
233
242
|
}
|
|
234
243
|
}
|
|
235
244
|
}
|
|
@@ -257,6 +266,38 @@ plugins: {
|
|
|
257
266
|
}
|
|
258
267
|
```
|
|
259
268
|
|
|
269
|
+
#### Tips: Using async function in the autoLogin
|
|
270
|
+
|
|
271
|
+
If you use async functions in the autoLogin plugin, login function should be used with `await` keyword.
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
autoLogin: {
|
|
275
|
+
enabled: true,
|
|
276
|
+
saveToFile: true,
|
|
277
|
+
inject: 'login',
|
|
278
|
+
users: {
|
|
279
|
+
admin: {
|
|
280
|
+
login: async (I) => { // If you use async function in the autoLogin plugin
|
|
281
|
+
const phrase = await I.grabTextFrom('#phrase')
|
|
282
|
+
I.fillField('username', 'admin'),
|
|
283
|
+
I.fillField('password', 'password')
|
|
284
|
+
I.fillField('phrase', phrase)
|
|
285
|
+
},
|
|
286
|
+
check: (I) => {
|
|
287
|
+
I.amOnPage('/');
|
|
288
|
+
I.see('Admin');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
Scenario('login', async (I, login) => {
|
|
297
|
+
await login('admin') // you should use `await`
|
|
298
|
+
})
|
|
299
|
+
```
|
|
300
|
+
|
|
260
301
|
### Parameters
|
|
261
302
|
|
|
262
303
|
- `config`
|
package/docs/puppeteer.md
CHANGED
|
@@ -3,8 +3,7 @@ id: puppeteer
|
|
|
3
3
|
title: Testing with Puppeteer
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Among all Selenium alternatives the most interesting emerging ones are tools developed around Google Chrome [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). And the most prominent one is [Puppeteer](https://github.com/GoogleChrome/puppeteer).
|
|
7
|
-
It operates over Google Chrome directly without requireing additional tools like ChromeDriver. So tests setup with Puppeteer can be started with npm install only. If you want get faster and simpler to setup tests, Puppeteer would be your choice.
|
|
6
|
+
Among all Selenium alternatives the most interesting emerging ones are tools developed around Google Chrome [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). And the most prominent one is [Puppeteer](https://github.com/GoogleChrome/puppeteer). It operates over Google Chrome directly without requiring additional tools like ChromeDriver. So tests setup with Puppeteer can be started with npm install only. If you want get faster and simpler to setup tests, Puppeteer would be your choice.
|
|
8
7
|
|
|
9
8
|
CodeceptJS uses Puppeteer to improve end to end testing experience. No need to learn the syntax of a new tool, all drivers in CodeceptJS share the same API.
|
|
10
9
|
|
|
@@ -27,47 +26,51 @@ It's readable and simple and works using Puppeteer API!
|
|
|
27
26
|
To start you need CodeceptJS with Puppeteer packages installed
|
|
28
27
|
|
|
29
28
|
```bash
|
|
30
|
-
npm install
|
|
29
|
+
npm install codeceptjs puppeteer --save
|
|
31
30
|
```
|
|
32
31
|
|
|
33
32
|
Or see [alternative installation options](http://codecept.io/installation/)
|
|
34
|
-
|
|
33
|
+
|
|
34
|
+
> If you already have CodeceptJS project, just install `puppeteer` package and enable a helper it in config.
|
|
35
35
|
|
|
36
36
|
And a basic project initialized
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
codeceptjs init
|
|
39
|
+
npx codeceptjs init
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
You will be asked for a Helper to use, you should select Puppeteer and provide url of a website you are testing.
|
|
43
43
|
|
|
44
|
+
> Puppeteer can also work with Firefox. [Learn how to set it up](https://codecept.io/helpers/Puppeteer-firefox)
|
|
45
|
+
|
|
44
46
|
## Configuring
|
|
45
47
|
|
|
46
|
-
Make sure `Puppeteer` helper is enabled in `codecept.
|
|
48
|
+
Make sure `Puppeteer` helper is enabled in `codecept.conf.js` config:
|
|
47
49
|
|
|
48
50
|
```js
|
|
49
51
|
{ // ..
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
helpers: {
|
|
53
|
+
Puppeteer: {
|
|
54
|
+
url: "http://localhost",
|
|
55
|
+
show: true
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
// ..
|
|
57
59
|
}
|
|
58
60
|
```
|
|
59
61
|
|
|
60
|
-
Turn
|
|
62
|
+
> Turn off the `show` option if you want to run test in headless mode.
|
|
61
63
|
|
|
62
64
|
Puppeteer uses different strategies to detect if a page is loaded. In configuration use `waitForNavigation` option for that:
|
|
63
65
|
|
|
64
66
|
By default it is set to `domcontentloaded` which waits for `DOMContentLoaded` event being fired. However, for Single Page Applications it's more useful to set this value to `networkidle0` which waits for all network connections to be finished.
|
|
65
67
|
|
|
66
68
|
```js
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
helpers: {
|
|
70
|
+
Puppeteer: {
|
|
71
|
+
url: "http://localhost",
|
|
72
|
+
show: true,
|
|
73
|
+
waitForNavigation: "networkidle0"
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
```
|
|
@@ -75,14 +78,14 @@ By default it is set to `domcontentloaded` which waits for `DOMContentLoaded` ev
|
|
|
75
78
|
When a test runs faster than application it is recommended to increase `waitForAction` config value.
|
|
76
79
|
It will wait for a small amount of time (100ms) by default after each user action is taken.
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
> ▶ More options are listed in [helper reference](http://codecept.io/helpers/Puppeteer/).
|
|
79
82
|
|
|
80
83
|
## Writing Tests
|
|
81
84
|
|
|
82
85
|
CodeceptJS test should be created with `gt` command:
|
|
83
86
|
|
|
84
87
|
```sh
|
|
85
|
-
codeceptjs gt
|
|
88
|
+
npx codeceptjs gt
|
|
86
89
|
```
|
|
87
90
|
|
|
88
91
|
As an example we will use `ToDoMvc` app for testing.
|
|
@@ -100,9 +103,9 @@ Tests consist with a scenario of user's action taken on a page. The most widely
|
|
|
100
103
|
* `see`, `dontSee` - to check for a text on a page
|
|
101
104
|
* `seeElement`, `dontSeeElement` - to check for elements on a page
|
|
102
105
|
|
|
103
|
-
|
|
106
|
+
> ℹ All actions are listed in [Puppeteer helper reference](http://codecept.io/helpers/Puppeteer/).*
|
|
104
107
|
|
|
105
|
-
All actions
|
|
108
|
+
All actions which interact with elements **support CSS and XPath locators**. Actions like `click` or `fillField` by locate elements by their name or value on a page:
|
|
106
109
|
|
|
107
110
|
```js
|
|
108
111
|
|
|
@@ -153,7 +156,7 @@ Scenario('get value of current tasks', async (I) => {
|
|
|
153
156
|
|
|
154
157
|
### Within
|
|
155
158
|
|
|
156
|
-
In case some actions should be taken inside one element (a container or modal window) you can use `within` block to narrow the scope.
|
|
159
|
+
In case some actions should be taken inside one element (a container or modal window or iframe) you can use `within` block to narrow the scope.
|
|
157
160
|
Please take a note that you can't use within inside another within in Puppeteer helper:
|
|
158
161
|
|
|
159
162
|
```js
|
|
@@ -165,15 +168,58 @@ within('.todoapp', () => {
|
|
|
165
168
|
I.see('0 items left', '.todo-count');
|
|
166
169
|
```
|
|
167
170
|
|
|
171
|
+
> [▶ Learn more about basic commands](https://codecept.io/basics#writing-tests)
|
|
172
|
+
|
|
168
173
|
CodeceptJS allows you to implement custom actions like `I.createTodo` or use **PageObjects**. Learn how to improve your tests in [PageObjects](http://codecept.io/pageobjects/) guide.
|
|
169
174
|
|
|
170
|
-
|
|
175
|
+
> [▶ Demo project is available on GitHub](https://github.com/DavertMik/codeceptjs-todomvc-puppeteer)
|
|
176
|
+
|
|
177
|
+
## Mocking Requests
|
|
178
|
+
|
|
179
|
+
Web application sends various requests to local services (Rest API, GraphQL) or to 3rd party services (CDNS, Google Analytics, etc).
|
|
180
|
+
When you run tests with Puppeteer you can control those requests by mocking them. For instance, you can speed up your tests by blocking trackers, Google Analytics, and other services you don't control.
|
|
181
|
+
|
|
182
|
+
Also you can replace real request with a one explicitly defined. This is useful when you want to isolate application testing from a backend. For instance, if you don't want to save data to database, and you know the request which performs save, you can mock the request, so application will treat this as valid response, but no data will be actually saved.
|
|
171
183
|
|
|
172
|
-
|
|
184
|
+
To mock requests enable additional helper [Polly](https://codecept.io/helpers/Polly) (which is based on Polly.js).
|
|
173
185
|
|
|
174
|
-
|
|
186
|
+
```js
|
|
187
|
+
helpers: {
|
|
188
|
+
Puppeteer: {
|
|
189
|
+
// regular Puppeteer config here
|
|
190
|
+
},
|
|
191
|
+
Polly: {}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
175
194
|
|
|
176
|
-
|
|
195
|
+
And install additional packages:
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
npm i @pollyjs/core @pollyjs/adapter-puppeteer --save-dev
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
After an installation function `mockRequest` will be added to `I` object. You can use it to explicitly define which requests to block and which response they should return instead:
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
// block all Google Analytics calls
|
|
205
|
+
I.mockRequest('/google-analytics/*path', 200);
|
|
206
|
+
// return an empty successful response
|
|
207
|
+
I.mockRequest('GET', '/api/users', 200);
|
|
208
|
+
// block post requests to /api/users and return predefined object
|
|
209
|
+
I.mockRequest('POST', '/api/users', { user: 'davert' });
|
|
210
|
+
// return error request with body
|
|
211
|
+
I.mockRequest('GET', '/api/users/1', 404, { error: 'User not found' });
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
> See [`mockRequest` API](https://codecept.io/helpers/Polly#mockrequest)
|
|
215
|
+
|
|
216
|
+
To see `mockRequest` method in intellisense auto completion don't forget to run `codeceptjs def` command:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
npx codeceptjs def
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Mocking rules will be kept while a test is running. To stop mocking use `I.stopMocking()` command
|
|
177
223
|
|
|
178
224
|
## Extending
|
|
179
225
|
|
|
@@ -182,7 +228,7 @@ Puppeteer has a very [rich and flexible API](https://github.com/GoogleChrome/pup
|
|
|
182
228
|
Start with creating an `MyPuppeteer` helper using `generate:helper` or `gh` command:
|
|
183
229
|
|
|
184
230
|
```sh
|
|
185
|
-
codeceptjs gh
|
|
231
|
+
npx codeceptjs gh
|
|
186
232
|
```
|
|
187
233
|
|
|
188
234
|
Then inside a Helper you can access `Puppeteer` helper of CodeceptJS.
|
|
@@ -197,5 +243,7 @@ async renderPageToPdf() {
|
|
|
197
243
|
}
|
|
198
244
|
```
|
|
199
245
|
|
|
200
|
-
The same way you can also access `browser` object to implement more actions or handle events.
|
|
246
|
+
The same way you can also access `browser` object to implement more actions or handle events.
|
|
247
|
+
|
|
248
|
+
> [▶ Learn more about Helpers](http://codecept.io/helpers/)
|
|
201
249
|
|
package/docs/quickstart.md
CHANGED
|
@@ -4,18 +4,42 @@ title: Quickstart
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
**NodeJS v 8.9** and higher required to start.
|
|
7
|
-
CodeceptJS is
|
|
7
|
+
CodeceptJS is an end 2 end testing framework which supports multiple browser drivers like WebDriver, Puppeteer, Protractor, TestCafe etc.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
* If you are familiar with Selenium, you can choose classical [**Selenium WebDriver** setup](#using-selenium-webdriver).
|
|
11
|
-
* Also, look at [complete installation reference](https://codecept.io/installation/).
|
|
9
|
+
> **⬇️ TLDR [Fastest and simplest setup with Puppeteer and CodeceptJS](#using-puppeteer) ⬇️**
|
|
12
10
|
|
|
11
|
+
How to choose the right driver for your web application?
|
|
12
|
+
Here is a brief comparison of all tools you can use with CodeceptJS.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
| Driver | Cross-Browser | Limitations | Headless | Selenuim | Speed |
|
|
16
|
+
|---|---|---|--|--|--|
|
|
17
|
+
| WebDriver | ✔️ | headers, downloads | ⁉ | ✔️ | normal |
|
|
18
|
+
| Puppeteer | chrome | cross-browser support | ✔️ | | fast |
|
|
19
|
+
| Protractor | ✔️ | headers, downloads | ⁉ | ✔️ | normal |
|
|
20
|
+
| TestCafe | ✔️ | multiple tabs | ✔️ | | fast |
|
|
21
|
+
| Nightmare | electron (chromium) | multiple tabs, cross-browser | ✔️ | | fast |
|
|
22
|
+
|
|
23
|
+
⁉ - headless mode requires additional tools and configuration.
|
|
24
|
+
|
|
25
|
+
#### How to choose browser driver
|
|
26
|
+
|
|
27
|
+
* **[Choose Puppeteer](#Using-Puppeteer)** for simplest setup, fast tests, full browser control. Limited to Chrome and Firefox only. Cloud browsers via browserless.io.
|
|
28
|
+
* **[Choose WebDriver](#Using-WebDriver)** or Protractor for classical Selenium. Rich ecosystem and cross browser support with cloud browsers via Sauce Labs, BrowserStack, TestingBot. **Selenium server requried** for local start.
|
|
29
|
+
* **[Choose TestCafe](#Using-TestCafe)** for cheap and fast cross-browser tests. Has stability and feature limitation comparing to WebDriver.
|
|
30
|
+
|
|
31
|
+
Each driver has its own pros and cons which can't be described in this paragraph. However, in CodeceptJS it is easy to switch between them. In most cases you just need to update a config to run tests differently.
|
|
13
32
|
|
|
14
33
|
## Using Puppeteer
|
|
15
34
|
|
|
16
35
|
|
|
17
36
|
<video onclick="this.paused ? this.play() : this.pause();" src="/img/codeceptjs-install.mp4" style="width: 100%" controls></video>
|
|
18
37
|
|
|
38
|
+
0) If you start an empty project, initialize npm first:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
npm init -y
|
|
42
|
+
```
|
|
19
43
|
|
|
20
44
|
1) Install CodeceptJS with Puppeteer
|
|
21
45
|
|
|
@@ -102,17 +126,24 @@ Puppeteer starts a browser without showing its window. To see the browser, edit
|
|
|
102
126
|
|
|
103
127
|
Rerun the test to see the browser.
|
|
104
128
|
|
|
105
|
-
> Next:
|
|
129
|
+
> [▶ Next: CodeceptJS Basics](https://codecept.io/basics/)
|
|
130
|
+
|
|
131
|
+
> [▶ Next: CodeceptJS with Puppeteer](https://codecept.io/puppeteer/)
|
|
106
132
|
|
|
107
|
-
> Next: [CodeceptJS Basics >>>](https://codecept.io/basics/)
|
|
108
133
|
|
|
109
|
-
> Next: [Demo Project](https://github.com/DavertMik/codeceptjs-todomvc-puppeteer)
|
|
110
134
|
|
|
111
135
|
|
|
112
136
|
---
|
|
113
137
|
|
|
114
138
|
## Using Selenium WebDriver
|
|
115
139
|
|
|
140
|
+
0) If you start an empty project, initialize npm first:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
npm init -y
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
|
|
116
147
|
1) Install CodeceptJS with webdriverio library
|
|
117
148
|
|
|
118
149
|
```
|
|
@@ -209,19 +240,23 @@ My First Test --
|
|
|
209
240
|
```
|
|
210
241
|
|
|
211
242
|
|
|
212
|
-
> Next:
|
|
243
|
+
> [▶ Next: CodeceptJS Basics](https://codecept.io/basics/)
|
|
213
244
|
|
|
214
|
-
> Next:
|
|
245
|
+
> [▶ Next: WebDriver Testing](https://codecept.io/webdriver/)
|
|
215
246
|
|
|
216
247
|
|
|
217
248
|
## Using Protractor
|
|
218
249
|
|
|
219
|
-
> [
|
|
250
|
+
> [▶ Follow corresponding guide](https://codecept.io/angular/)
|
|
220
251
|
|
|
221
252
|
## Using Appium
|
|
222
253
|
|
|
223
|
-
> [
|
|
254
|
+
> [▶ Follow corresponding guide](https://codecept.io/mobile/)
|
|
224
255
|
|
|
225
256
|
## Using NightmareJS
|
|
226
257
|
|
|
227
|
-
> [
|
|
258
|
+
> [▶ Follow corresponding guide](https://codecept.io/nightmare/)
|
|
259
|
+
|
|
260
|
+
## Using TestCafe
|
|
261
|
+
|
|
262
|
+
> [▶ Follow corresponding guide](https://codecept.io/testcafe/)
|
package/docs/react.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: react
|
|
3
|
+
title: Testing React Applications
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
React applications require some additional love for end to end testing.
|
|
7
|
+
At first, it is very hard to test an application which was never designed to be tested!
|
|
8
|
+
This happens to many React application. While building components developers often forget to keep the element's semantic.
|
|
9
|
+
|
|
10
|
+
Generated HTML code may often look like this:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
<div class="jss607 jss869 jss618 jss871 jss874 jss876" tabindex="0" role="tab" aria-selected="true" style="pointer-events: auto;">
|
|
14
|
+
<span class="jss877">
|
|
15
|
+
<span class="jss878">
|
|
16
|
+
<span class="jss879">Click Me!</span>
|
|
17
|
+
</span>
|
|
18
|
+
</span>
|
|
19
|
+
<span class="jss610"></span></div>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
It's quite common that clickable elements are not actual `a` or `button` elements. This way `I.click('Click Me!');` won't work, as well as `fillField('name', 'value)`. Finding a correct locator for such cases turns to be almost impossible.
|
|
23
|
+
|
|
24
|
+
In this case test engineers have two options:
|
|
25
|
+
|
|
26
|
+
1. Update JSX files to change output HTML and rebuild the application
|
|
27
|
+
1. Test the application how it is.
|
|
28
|
+
|
|
29
|
+
We recommend for long-running projects to go with the first option. The better you write your initial HTML the cleaner and less fragile will be your tests. Replace divs with correct HTML elements, add `data-` attributes, add labels, and names to input fields to make all CodeceptJS magic like clicking link by a text to work.
|
|
30
|
+
|
|
31
|
+
However, if you can't update the code you can go to the second option. In this case, you should bind your locators to visible text on page and available semantic attribues. For instance, instead of using generated locator as this one:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
//*[@id="document"]/div[2]/div/div[2]/div
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
use [Locator Builder](https://codecept.io/locators#locator-builder) to make clean semantic locator:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
locate('[role=tab]').withText('Click Me!');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This way you can build very flexible and stable locators even on application never designed for testing.
|
|
44
|
+
|
|
45
|
+
## Locators
|
|
46
|
+
|
|
47
|
+
For React apps a special `react` locator is available. It allows to select an element by its component name, props and state.
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
{ react: 'MyComponent' }
|
|
51
|
+
{ react: 'Button', props: { title: 'Click Me' }}
|
|
52
|
+
{ react: 'Button', state: { some: 'state' }}
|
|
53
|
+
{ react: 'Input', state: 'valid'}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
In WebDriver and Puppeteer you can use React locators in any method where locator is required:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
I.click({ react: 'Tab', props: { title: 'Click Me!' }});
|
|
60
|
+
I.seeElement({ react: 't', props: { title: 'Clicked' }});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To find React element names and props in a tree use [React DevTools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) extension.
|
|
64
|
+
|
|
65
|
+
> Turn off minifcation for application builds otherwise component names will be uglified as well
|
|
66
|
+
|
|
67
|
+
React locators work via [resq](https://github.com/baruchvlz/resq) library, which handles React 16 and above.
|
package/docs/reports.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This action supports [React locators](https://codecept.io/react#locators)
|