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.
Files changed (173) hide show
  1. package/CHANGELOG.md +125 -37
  2. package/README.md +15 -22
  3. package/bin/codecept.js +4 -1
  4. package/docs/acceptance.md +44 -1
  5. package/docs/advanced.md +1 -1
  6. package/docs/angular.md +6 -9
  7. package/docs/basics.md +388 -75
  8. package/docs/bdd.md +4 -3
  9. package/docs/best.md +1 -1
  10. package/docs/books.md +31 -0
  11. package/docs/build/Appium.js +215 -176
  12. package/docs/build/Nightmare.js +618 -489
  13. package/docs/build/Polly.js +189 -0
  14. package/docs/build/Protractor.js +747 -608
  15. package/docs/build/Puppeteer.js +914 -633
  16. package/docs/build/REST.js +1 -1
  17. package/docs/build/TestCafe.js +1835 -0
  18. package/docs/build/WebDriver.js +861 -805
  19. package/docs/build/WebDriverIO.js +616 -617
  20. package/docs/changelog.md +410 -316
  21. package/docs/commands.md +6 -6
  22. package/docs/community-helpers.md +2 -0
  23. package/docs/detox.md +235 -0
  24. package/docs/examples.md +23 -0
  25. package/docs/helpers/ApiDataFactory.md +11 -10
  26. package/docs/helpers/Appium.md +130 -61
  27. package/docs/helpers/Detox.md +579 -0
  28. package/docs/helpers/FileSystem.md +2 -1
  29. package/docs/helpers/Mochawesome.md +1 -0
  30. package/docs/helpers/Nightmare.md +348 -128
  31. package/docs/helpers/Polly.md +85 -0
  32. package/docs/helpers/Protractor.md +451 -184
  33. package/docs/helpers/Puppeteer-firefox.md +55 -0
  34. package/docs/helpers/Puppeteer.md +619 -183
  35. package/docs/helpers/REST.md +17 -16
  36. package/docs/helpers/SeleniumWebdriver.md +9 -8
  37. package/docs/helpers/TestCafe.md +1168 -0
  38. package/docs/helpers/WebDriver.md +600 -291
  39. package/docs/helpers/WebDriverIO.md +393 -278
  40. package/docs/helpers.md +37 -18
  41. package/docs/locators.md +2 -0
  42. package/docs/mobile-react-native-locators.md +64 -0
  43. package/docs/mobile.md +5 -0
  44. package/docs/plugins.md +54 -13
  45. package/docs/puppeteer.md +74 -26
  46. package/docs/quickstart.md +47 -12
  47. package/docs/react.md +67 -0
  48. package/docs/reports.md +1 -1
  49. package/docs/{webapi/_keys.mustache → shared/keys.mustache} +0 -0
  50. package/docs/shared/react.mustache +1 -0
  51. package/docs/testcafe.md +157 -0
  52. package/docs/videos.md +19 -0
  53. package/docs/webapi/amOnPage.mustache +1 -1
  54. package/docs/webapi/appendField.mustache +2 -2
  55. package/docs/webapi/attachFile.mustache +2 -2
  56. package/docs/webapi/checkOption.mustache +2 -2
  57. package/docs/webapi/clearCookie.mustache +1 -1
  58. package/docs/webapi/clearField.mustache +1 -1
  59. package/docs/webapi/click.mustache +2 -2
  60. package/docs/webapi/clickLink.mustache +3 -3
  61. package/docs/webapi/dontSee.mustache +6 -3
  62. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +7 -1
  63. package/docs/webapi/dontSeeCookie.mustache +5 -1
  64. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +6 -1
  65. package/docs/webapi/dontSeeElement.mustache +5 -1
  66. package/docs/webapi/dontSeeElementInDOM.mustache +5 -1
  67. package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
  68. package/docs/webapi/dontSeeInField.mustache +7 -2
  69. package/docs/webapi/dontSeeInSource.mustache +5 -1
  70. package/docs/webapi/dontSeeInTitle.mustache +5 -1
  71. package/docs/webapi/doubleClick.mustache +2 -2
  72. package/docs/webapi/downloadFile.mustache +2 -2
  73. package/docs/webapi/dragAndDrop.mustache +2 -2
  74. package/docs/webapi/dragSlider.mustache +2 -2
  75. package/docs/webapi/executeAsyncScript.mustache +1 -1
  76. package/docs/webapi/executeScript.mustache +1 -1
  77. package/docs/webapi/fillField.mustache +2 -2
  78. package/docs/webapi/grabAttributeFrom.mustache +3 -2
  79. package/docs/webapi/grabBrowserLogs.mustache +3 -1
  80. package/docs/webapi/grabCookie.mustache +2 -1
  81. package/docs/webapi/grabCssPropertyFrom.mustache +3 -2
  82. package/docs/webapi/grabCurrentUrl.mustache +3 -1
  83. package/docs/webapi/grabDataFromPerformanceTiming.mustache +19 -0
  84. package/docs/webapi/grabHTMLFrom.mustache +2 -1
  85. package/docs/webapi/grabNumberOfOpenTabs.mustache +4 -2
  86. package/docs/webapi/grabNumberOfVisibleElements.mustache +3 -2
  87. package/docs/webapi/grabPageScrollPosition.mustache +3 -1
  88. package/docs/webapi/grabSource.mustache +3 -1
  89. package/docs/webapi/grabTextFrom.mustache +2 -1
  90. package/docs/webapi/grabTitle.mustache +3 -1
  91. package/docs/webapi/grabValueFrom.mustache +2 -1
  92. package/docs/webapi/moveCursorTo.mustache +3 -3
  93. package/docs/webapi/pressKey.mustache +1 -1
  94. package/docs/webapi/resizeWindow.mustache +2 -2
  95. package/docs/webapi/rightClick.mustache +2 -2
  96. package/docs/webapi/saveScreenshot.mustache +3 -3
  97. package/docs/webapi/say.mustache +2 -2
  98. package/docs/webapi/scrollPageToBottom.mustache +1 -1
  99. package/docs/webapi/scrollPageToTop.mustache +1 -1
  100. package/docs/webapi/scrollTo.mustache +3 -3
  101. package/docs/webapi/see.mustache +2 -2
  102. package/docs/webapi/seeAttributesOnElements.mustache +3 -3
  103. package/docs/webapi/seeCheckboxIsChecked.mustache +2 -1
  104. package/docs/webapi/seeCookie.mustache +1 -1
  105. package/docs/webapi/seeCssPropertiesOnElements.mustache +2 -2
  106. package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
  107. package/docs/webapi/seeElement.mustache +1 -1
  108. package/docs/webapi/seeElementInDOM.mustache +1 -1
  109. package/docs/webapi/seeInCurrentUrl.mustache +1 -1
  110. package/docs/webapi/seeInField.mustache +2 -2
  111. package/docs/webapi/seeInSource.mustache +1 -1
  112. package/docs/webapi/seeInTitle.mustache +5 -1
  113. package/docs/webapi/seeNumberOfElements.mustache +10 -0
  114. package/docs/webapi/seeNumberOfVisibleElements.mustache +2 -2
  115. package/docs/webapi/selectOption.mustache +2 -2
  116. package/docs/webapi/setCookie.mustache +1 -1
  117. package/docs/webapi/switchTo.mustache +6 -1
  118. package/docs/webapi/uncheckOption.mustache +2 -2
  119. package/docs/webapi/wait.mustache +1 -2
  120. package/docs/webapi/waitForDetached.mustache +3 -3
  121. package/docs/webapi/waitForElement.mustache +2 -2
  122. package/docs/webapi/waitForEnabled.mustache +1 -1
  123. package/docs/webapi/waitForFunction.mustache +3 -3
  124. package/docs/webapi/waitForInvisible.mustache +3 -3
  125. package/docs/webapi/waitForText.mustache +3 -3
  126. package/docs/webapi/waitForValue.mustache +3 -3
  127. package/docs/webapi/waitForVisible.mustache +3 -3
  128. package/docs/webapi/waitInUrl.mustache +2 -2
  129. package/docs/webapi/waitNumberOfVisibleElements.mustache +3 -3
  130. package/docs/webapi/waitToHide.mustache +3 -3
  131. package/docs/webapi/waitUntil.mustache +3 -3
  132. package/docs/webapi/waitUrlEquals.mustache +2 -2
  133. package/docs/webdriver.md +453 -0
  134. package/lib/codecept.js +11 -9
  135. package/lib/command/definitions.js +183 -30
  136. package/lib/command/gherkin/snippets.js +29 -9
  137. package/lib/command/init.js +31 -9
  138. package/lib/command/run-multiple.js +46 -59
  139. package/lib/command/utils.js +1 -1
  140. package/lib/container.js +30 -4
  141. package/lib/data/dataScenarioConfig.js +18 -0
  142. package/lib/helper/Appium.js +24 -24
  143. package/lib/helper/Nightmare.js +81 -84
  144. package/lib/helper/Polly.js +189 -0
  145. package/lib/helper/Protractor.js +96 -86
  146. package/lib/helper/Puppeteer.js +238 -113
  147. package/lib/helper/REST.js +1 -1
  148. package/lib/helper/TestCafe.js +1257 -0
  149. package/lib/helper/WebDriver.js +217 -277
  150. package/lib/helper/WebDriverIO.js +75 -75
  151. package/lib/helper/clientscripts/nightmare.js +8 -0
  152. package/lib/helper/extras/React.js +55 -0
  153. package/lib/helper/testcafe/testControllerHolder.js +42 -0
  154. package/lib/helper/testcafe/testcafe-utils.js +63 -0
  155. package/lib/history.js +39 -0
  156. package/lib/hooks.js +25 -1
  157. package/lib/interfaces/gherkin.js +17 -1
  158. package/lib/interfaces/scenarioConfig.js +2 -2
  159. package/lib/listener/config.js +3 -3
  160. package/lib/locator.js +6 -0
  161. package/lib/pause.js +22 -1
  162. package/lib/plugin/allure.js +63 -0
  163. package/lib/plugin/autoLogin.js +65 -16
  164. package/lib/plugin/puppeteerCoverage.js +6 -1
  165. package/lib/plugin/stepByStepReport.js +4 -3
  166. package/lib/scenario.js +23 -17
  167. package/lib/step.js +5 -2
  168. package/lib/ui.js +1 -1
  169. package/lib/utils.js +70 -20
  170. package/package.json +20 -19
  171. package/translations/de-DE.js +69 -0
  172. package/translations/index.js +1 -0
  173. 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
- ```json
28
- "helpers": {
29
- "WebDriver": { },
30
- "MyHelper": {
31
- "require": "./path/to/module.js"
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.json` config. It should look like this:
37
+ Generated Helper will be added to `codecept.conf.js` config. It should look like this:
38
38
 
39
39
  ```js
40
- 'use strict';
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
- 'use strict';
83
- let Helper = codecept_helper;
80
+ const Helper = codecept_helper;
84
81
 
85
82
  // use any assertion library you like
86
- let assert = require('assert');
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
- 'use strict';
122
- let Helper = codecept_helper;
141
+ const Helper = codecept_helper;
123
142
 
124
143
  // use any assertion library you like
125
- var chai = require('chai');
126
- var chaiAsPromised = require('chai-as-promised');
144
+ const chai = require('chai');
145
+ const chaiAsPromised = require('chai-as-promised');
127
146
  chai.use(chaiAsPromised);
128
- var expect = chai.expect;
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
- var history = element.all(by.repeater('result in memory'));
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
- admin: {
221
- login: (I) => {
222
- I.amOnPage('/login');
223
- I.fillField('email', 'admin@site.com');
224
- I.fillField('password', '123456');
225
- I.click('Login');
226
- }
227
- check: (I) => {
228
- I.amOnPage('/dashboard');
229
- I.see('Admin', '.navbar');
230
- },
231
- fetch: () => {}, // empty function
232
- restore: () => {}, // empty funciton
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 -g codeceptjs puppeteer
29
+ npm install codeceptjs puppeteer --save
31
30
  ```
32
31
 
33
32
  Or see [alternative installation options](http://codecept.io/installation/)
34
- If you already have CodeceptJS project, just install `puppeteer` package and enable it in config.
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.json` config:
48
+ Make sure `Puppeteer` helper is enabled in `codecept.conf.js` config:
47
49
 
48
50
  ```js
49
51
  { // ..
50
- "helpers": {
51
- "Puppeteer": {
52
- "url": "http://localhost",
53
- "show": false
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 on the `show` option if you want to follow test progress in a window. This is very useful for debugging.
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
- "helpers": {
68
- "Puppeteer": {
69
- "url": "http://localhost",
70
- "waitForNavigation": "networkidle0"
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
- *More options are listed in [helper reference](http://codecept.io/helpers/Puppeteer/).*
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
- *All actions are listed in [helper reference](http://codecept.io/helpers/Puppeteer/).*
106
+ > ℹ All actions are listed in [Puppeteer helper reference](http://codecept.io/helpers/Puppeteer/).*
104
107
 
105
- All actions whicn interact with elements **support CSS and XPath locators**. Actions like `click` or `fillField` by locate elements by their name or value on a page:
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
- `within` can also work with [iframes](/acceptance/#iframes)
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
- When running steps inside a within block will be shown with a shift.
184
+ To mock requests enable additional helper [Polly](https://codecept.io/helpers/Polly) (which is based on Polly.js).
173
185
 
174
- ![within](https://codecept.io/img/within.png)
186
+ ```js
187
+ helpers: {
188
+ Puppeteer: {
189
+ // regular Puppeteer config here
190
+ },
191
+ Polly: {}
192
+ }
193
+ ```
175
194
 
176
- > [Demo project is available on GitHub](https://github.com/DavertMik/codeceptjs-todomvc-puppeteer)
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. [Learn more about Helpers](http://codecept.io/helpers/) in the corresponding guide.
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
 
@@ -4,18 +4,42 @@ title: Quickstart
4
4
  ---
5
5
 
6
6
  **NodeJS v 8.9** and higher required to start.
7
- CodeceptJS is multi-backend testing framework. It can execute tests using different libraries like webdriverio, Puppeteer, Protractor, etc.
7
+ CodeceptJS is an end 2 end testing framework which supports multiple browser drivers like WebDriver, Puppeteer, Protractor, TestCafe etc.
8
8
 
9
- * In this guide we will use [Google Chrome **Puppeteer**](https://github.com/GoogleChrome/puppeteer) as a driver for browsers. This allows us to start in a minutes with no extra tools installed.
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: [CodeceptJS with Puppeteer >>>](https://codecept.io/puppeteer/)
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: [CodeceptJS Basics >>>](https://codecept.io/basics/)
243
+ > [▶ Next: CodeceptJS Basics](https://codecept.io/basics/)
213
244
 
214
- > Next: [Acceptance Testing in CodeceptJS >>>](https://codecept.io/acceptance/)
245
+ > [▶ Next: WebDriver Testing](https://codecept.io/webdriver/)
215
246
 
216
247
 
217
248
  ## Using Protractor
218
249
 
219
- > [**Follow corresponding guide >>**](https://codecept.io/angular/)
250
+ > [Follow corresponding guide](https://codecept.io/angular/)
220
251
 
221
252
  ## Using Appium
222
253
 
223
- > [**Follow corresponding guide >>**](https://codecept.io/mobile/)
254
+ > [Follow corresponding guide](https://codecept.io/mobile/)
224
255
 
225
256
  ## Using NightmareJS
226
257
 
227
- > [**Follow corresponding guide >>**](https://codecept.io/nightmare/)
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
@@ -1,5 +1,5 @@
1
1
  ---
2
- id: reporters
2
+ id: reports
3
3
  title: Reporters
4
4
  ---
5
5
 
@@ -0,0 +1 @@
1
+ This action supports [React locators](https://codecept.io/react#locators)