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/basics.md CHANGED
@@ -30,20 +30,23 @@ Here is the diagram of CodeceptJS architecture
30
30
  All helpers share the same API so it's easy to migrate tests from one backend to other.
31
31
  However, because of difference in backends and their limitations, they are not guaranteed to be compatible with each other. For instance, you can't set request headers in WebDriver or Protractor, but you can do so in Puppteer or Nightmare.
32
32
 
33
- Please note, you can't run tests by different helpers at once. You can't use some APIs from WebDriver and some from Nightmare. You should **pick one helper, as it defines how tests are executed.** If requirements change it's easy to migrate to another, but don't use few helpers at once. It's just not possible.
33
+ **Pick one helper, as it defines how tests are executed.** If requirements change it's easy to migrate to another, but don't use few helpers of same kind at once.
34
34
 
35
- A helper should be enabled in main config. Configuration (like base url) should be provided as well:
35
+ ---
36
36
 
37
- ```json
38
- "helpers": {
39
- "WebDriver": {
40
- "url": "http://localhost",
41
- "browser": "chrome"
42
- }
43
- }
44
- ```
37
+ Refer to following guides to more information on:
38
+
39
+ * [▶ WebDriver](https://codecept.io/webdriver)
40
+ * [▶ Protractor](https://codecept.io/angular)
41
+ * [▶ Puppeteer](https://codecept.io/puppeteer)
42
+ * [▶ Nightmare](https://codecept.io/nightmare)
43
+ * TestCafe
44
+
45
+ > ℹ Depending on a helper selected a list of available actions may change.
46
+
47
+ To list all available commands for current configuration run `codeceptjs list`
48
+ or enable [auto-completion by generating TypeScript definitions](#intellisense).
45
49
 
46
- In this config config all methods of `I` will be taken from `WebDriver` helper.
47
50
 
48
51
  ## Writing Tests
49
52
 
@@ -56,11 +59,221 @@ I.see('Please Login', 'h1');
56
59
  // ...
57
60
  ```
58
61
 
59
- To list all available commands for current configuration run `codeceptjs list`
60
- or enable [auto-completion by generating TypeScript definitions](#intellisense).
62
+ ### Opening a Page
63
+
64
+ A test should usually start with navigating browser to the website.
65
+
66
+ Start a test by opening a page. Use `I.amOnPage()` command for this:
67
+
68
+ ```js
69
+ // When "http://site.com" is url in config
70
+ I.amOnPage('/'); // -> opens http://site.com/
71
+ I.amOnPage('/about'); // -> opens http://site.com/about
72
+ I.amOnPage('https://google.com'); // -> https://google.com
73
+ ```
74
+
75
+ When URL doesn't start with a protocol (http:// or https://) it is considered to be a relative URL and appended to URL which was initially set in the config.
76
+
77
+ > It is recommended to use relative URLs and keep base URL in config file, so you could easily switch between development, staging, and production environments.
78
+
79
+
80
+ ### Locating Element
81
+
82
+ Element can be found by CSS or XPath locators.
83
+
84
+ ```js
85
+ I.seeElement('.user'); // element with CSS class user
86
+ I.seeElement('//button[contains(., "press me")]'); // button
87
+ ```
88
+
89
+ By default CodeceptJS tries to guess the locator type.
90
+ In order to specify exact locator type you can pass an object called **strict locator**.
91
+
92
+ ```js
93
+ I.seeElement({css: 'div.user'});
94
+ I.seeElement({xpath: '//div[@class=user]'});
95
+ ```
96
+
97
+ Strict locators allow to specify additional locator types:
98
+
99
+ ```js
100
+ // locate form element by name
101
+ I.seeElement({name: 'password'});
102
+ // locate element by id
103
+ I.seeElement({id: 'users'});
104
+ // locate element by React component and props
105
+ I.seeElement({react: 'user-profile', props: {name: 'davert'}});
106
+ ```
107
+
108
+ In [mobile testing](http://codecept.io/mobile/#locating-elements) you can use `~` to specify accessibility id to locate an element. In web application you can locate element by their `aria-label` value.
109
+
110
+ ```js
111
+ // locate element by [aria-label] attribute in web
112
+ // or by accessibility id in mobile
113
+ I.seeElement('~username');
114
+ ```
115
+
116
+ > [▶ Learn more about using locators in CodeceptJS](https://codecept.io/locators).
117
+
118
+ ### Clicking
119
+
120
+ CodeceptJS provides a flexible syntax to specify an element to click.
121
+
122
+ By default CodeceptJS tries to find button or link with exact text on it
123
+
124
+ ```js
125
+ // search for link or button
126
+ I.click('Login');
127
+ ```
128
+
129
+ If none found, CodeceptJS tries to find link or button containing that text. In case an image is clickable its `alt` attribute will be checked for text inclusion. Form buttons will also be searched by name.
130
+
131
+ To narrow down the results you can specify a context in second parameter.
132
+
133
+ ```js
134
+ I.click('Login', '.nav'); // search only in .nav
135
+ I.click('Login', {css: 'footer'}); // search only in footer
136
+ ```
137
+
138
+ > To skip guessing locator type pass in a strict locator. A locator starting with '#' or '.' is considered to be CSS. Locator starting with '//' or './/' is considered to be XPath.
139
+
140
+ You are not limited to buttons and links. Any element can be found by passing in valid CSS or XPath:
141
+
142
+ ```js
143
+ // click element by CSS
144
+ I.click('#signup');
145
+ // click element located by special test-id attribute
146
+ I.click('//dev[@test-id="myid"]');
147
+ ```
148
+
149
+ ### Filling Fields
150
+
151
+ Clicking the links is not what takes the most time during testing a web site. If your site consists only of links you can skip test automation. The most routine waste of time goes into the testing of forms. CodeceptJS provides several ways of doing that.
152
+
153
+ Let's submit this sample form for a test:
154
+
155
+ ```html
156
+ <form method="post" action="/update" id="update_form">
157
+ <label for="user_name">Name</label>
158
+ <input type="text" name="user[name]" id="user_name" />
159
+ <label for="user_email">Email</label>
160
+ <input type="text" name="user[email]" id="user_email" />
161
+ <label for="user_gender">Gender</label>
162
+ <select id="user_gender" name="user[gender]">
163
+ <option value="m">Male</option>
164
+ <option value="f">Female</option>
165
+ </select>
166
+ <input type="submit" name="submitButton" value="Update" />
167
+ </form>
168
+ ```
169
+
170
+ We need to fill in all those fields and click "Update" button. CodeceptJS matches form elements by their label, name, or by CSS or XPath locators.
171
+
172
+ ```js
173
+ // we are using label to match user_name field
174
+ I.fillField('Name', 'Miles');
175
+ // we can use input name
176
+ I.fillField('user[email]','miles@davis.com');
177
+ // select element by label, choose option by text
178
+ I.selectOption('Gender','Male');
179
+ // click 'Update' button, found by text
180
+ I.click('Update');
181
+ ```
182
+
183
+ Alternative scenario:
184
+
185
+ ```js
186
+ // we are using CSS
187
+ I.fillField('#user_name', 'Miles');
188
+ I.fillField('#user_email','miles@davis.com');
189
+ // select element by label, option by value
190
+ I.selectOption('#user_gender','m');
191
+ // click 'Update' button, found by name
192
+ I.click('submitButton', '#update_form');
193
+ ```
194
+
195
+ To fill in sensitive data use `secret` function:
196
+
197
+ ```js
198
+ I.fillField('password', secret('123456'));
199
+ ```
200
+
201
+ ### Assertions
202
+
203
+ In order to verify the expected behavior of a web application, a content should be checked.
204
+ CodeceptJS provides built-in assertions for that. They start with `see` (or `dontSee`) prefix.
205
+
206
+ The most general and common assertion is `see`, which checks visilibility of a text on a page:
207
+
208
+ ```js
209
+ // Just a visible text on a page
210
+ I.see('Hello');
211
+ // text inside .msg element
212
+ I.see('Hello', '.msg');
213
+ // opposite
214
+ I.dontSee('Bye');
215
+ ```
216
+
217
+ You should provide a text as first argument and optionally a locator to search for a text in a context.
218
+
219
+ You can check that specific element exists (or not) on a page, as it was described in [Locating Element](#locating-element) section.
220
+
221
+ ```js
222
+ I.seeElement('.notice');
223
+ I.dontSeeElement('.error');
224
+ ```
225
+
226
+ Additional assertions:
227
+
228
+ ```js
229
+ I.seeInCurrentUrl('/user/miles');
230
+ I.seeInField('user[name]', 'Miles');
231
+ I.seeInTitle('My Website');
232
+ ```
233
+
234
+ To see all possible assertions see the helper's reference.
235
+
236
+ ### Grabbing
237
+
238
+ Sometimes you need to retrieve a data from a page to use it in next steps of a scenario.
239
+ Imagine, application generates a password and you want to ensure that user can login using this password.
240
+
241
+ ```js
242
+ Scenario('login with generated password', async (I) => {
243
+ I.fillField('email', 'miles@davis.com');
244
+ I.click('Generate Password');
245
+ const password = await I.grabTextFrom('#password');
246
+ I.click('Login');
247
+ I.fillField('email', 'miles@davis.com');
248
+ I.fillField('password', password);
249
+ I.click('Log in!');
250
+ I.see('Hello, Miles');
251
+ });
252
+ ```
253
+
254
+ `grabTextFrom` action is used here to retrieve text from an element. All actions starting with `grab` prefix are expected to return data. In order to synchronize this step with a scenario you should pause test execution with `await` keyword of ES6. To make it work your test should be written inside a async function (notice `async` in its definition).
255
+
256
+ ```js
257
+ Scenario('use page title', async (I) => {
258
+ // ...
259
+ const password = await I.grabTextFrom('#password');
260
+ I.fillField('password', password);
261
+ });
262
+ ```
263
+
264
+ ### Waiting
61
265
 
62
- > For most helpers basic actions like `amOnPage`, `fillField`, `click` are the same.
63
- Proceed to [Acceptance Testing Chapter](https://codecept.io/acceptance/) to learn how to use them.
266
+ In modern web applications rendering is happen on client side.
267
+ Sometimes that may cause delays. A test may fail while trying to click an element which has not appeared on a page yet.
268
+ To handle this cases `wait*` methods introduced.
269
+
270
+ ```js
271
+ I.waitForElement('#agree_button', 30); // secs
272
+ // clicks a button only when it is visible
273
+ I.click('#agree_button');
274
+ ```
275
+
276
+ > ℹ See [helpers reference](https://codecept.io/reference) for a complete list of all available commands for a helper you use.
64
277
 
65
278
  ## How It Works
66
279
 
@@ -197,6 +410,76 @@ This can be configured in [screenshotOnFail Plugin](https://codecept.io/plugins/
197
410
  To see how the test was executed, use [stepByStepReport Plugin](https://codecept.io/plugins/#stepbystepreport). It saves a screenshot of each passed step and shows them in a nice slideshow.
198
411
 
199
412
 
413
+ ## Retries
414
+
415
+ ### Retry Step
416
+
417
+ If you have a step which often fails you can retry execution for this single step.
418
+ Use `retry()` function before an action to ask CodeceptJS to retry this step on failure:
419
+
420
+ ```js
421
+ I.retry().see('Welcome');
422
+ ```
423
+
424
+ If you'd like to retry step more than once pass the amount as parameter:
425
+
426
+ ```js
427
+ I.retry(3).see('Welcome');
428
+ ```
429
+
430
+ Additional options can be provided to retry so you can set the additional options (defined in [promise-retry](https://www.npmjs.com/package/promise-retry) library).
431
+
432
+
433
+ ```js
434
+ // retry action 3 times waiting for 0.1 second before next try
435
+ I.retry({ retries: 3, minTimeout: 100 }).see('Hello');
436
+
437
+ // retry action 3 times waiting no more than 3 seconds for last retry
438
+ I.retry({ retries: 3, maxTimeout: 3000 }).see('Hello');
439
+
440
+ // retry 2 times if error with message 'Node not visible' happens
441
+ I.retry({
442
+ retries: 2,
443
+ when: err => err.message === 'Node not visible'
444
+ }).seeElement('#user');
445
+ ```
446
+
447
+ Pass a function to `when` option to retry only when error matches the expected one.
448
+
449
+ ### Auto Retry
450
+
451
+ You can auto-retry a failed step by enabling [retryFailedStep Plugin](https://codecept.io/plugins/#retryfailedstep).
452
+
453
+ ### Retry Scenario
454
+
455
+ When you need to rerun scenarios few times just add `retries` option added to `Scenario` declaration.
456
+
457
+ CodeceptJS implements retries the same way [Mocha do](https://mochajs.org#retry-tests);
458
+ You can set number of a retries for a feature:
459
+
460
+ ```js
461
+ Scenario('Really complex', (I) => {
462
+ // test goes here
463
+ }).retry(2);
464
+
465
+ // alternative
466
+ Scenario('Really complex', { retries: 2 }, (I) => {});
467
+ ```
468
+
469
+ This scenario will be restarted two times on a failure.
470
+
471
+ ### Retry Feature
472
+
473
+ To set this option for all scenarios in a file, add retry to a feature:
474
+
475
+ ```js
476
+ Feature('Complex JS Stuff').retry(3);
477
+ ```
478
+
479
+ Every Scenario inside this feature will be rerun 3 times.
480
+ You can make an exception for a specific scenario by passing `retries` option to a Scenario.
481
+
482
+
200
483
  ## Before
201
484
 
202
485
  Common preparation steps like opening a web page, logging in a user, can be placed in `Before` or `Background` hook:
@@ -258,7 +541,23 @@ within('.js-signup-form', () => {
258
541
  I.see('There were problems creating your account.');
259
542
  ```
260
543
 
261
- `within` can also work with [iframes](/acceptance/#iframes)
544
+ `within` can also work with IFrames. Special `frame` locator is required to locate the iframe and get into its context.
545
+
546
+ See example:
547
+
548
+ ```js
549
+ within({frame: "#editor"}, () => {
550
+ I.see('Page');
551
+ });
552
+ ```
553
+
554
+ Nested IFrames can be set by passing array *(WebDriver, Nightmare & Puppeteer only)*:
555
+
556
+ ```js
557
+ within({frame: [".content", "#editor"]}, () => {
558
+ I.see('Page');
559
+ });
560
+ ```
262
561
 
263
562
  When running steps inside a within block will be shown with a shift:
264
563
 
@@ -293,91 +592,105 @@ I.say('This is blue', 'blue'); //blue is used
293
592
  I.say('This is by default'); //cyan is used
294
593
  ```
295
594
 
296
- ## IntelliSense
595
+ ## Multiple Sessions
297
596
 
298
- If you are using Visual Studio Code or other IDE that supports TypeScript Definitions,
299
- you can generate step definitions with
597
+ CodeceptJS allows to run several browser sessions inside a test. This can be useful for testing communication between users inside a system, for instance in chats. To open another browser use `session()` function as shown in example:
300
598
 
301
- ```sh
302
- codeceptjs def
599
+ ```js
600
+ Scenario('test app', (I) => {
601
+ I.amOnPage('/chat');
602
+ I.fillField('name', 'davert');
603
+ I.click('Sign In');
604
+ I.see('Hello, davert');
605
+ session('john', () => {
606
+ // another session started
607
+ I.amOnPage('/chat');
608
+ I.fillField('name', 'john');
609
+ I.click('Sign In');
610
+ I.see('Hello, john');
611
+ });
612
+ // switching back to default session
613
+ I.fillField('message', 'Hi, john');
614
+ // there is a message from current user
615
+ I.see('me: Hi, john', '.messages');
616
+ session('john', () => {
617
+ // let's check if john received it
618
+ I.see('davert: Hi, john', '.messages');
619
+ });
620
+ });
303
621
  ```
304
622
 
305
- Now you should include `/// <reference path="./steps.d.ts" />` into your test files to get
306
- method autocompletion while writing tests.
307
-
308
- ## Skipping
309
-
310
- Like in Mocha you can use `x` and `only` to skip tests or making a single test to run.
311
-
312
- * `xScenario` - skips current test
313
- * `Scenario.only` - executes only the current test
314
-
623
+ `session` function expects a first parameter to be a name of a session. You can switch back to session by using the same name.
315
624
 
316
- ## Retries
317
-
318
- ### Retry Step
319
-
320
- If you have a step which often fails you can retry execution for this single step.
321
- Use `retry()` function before an action to ask CodeceptJS to retry this step on failure:
625
+ You can override config for session by passing second parameter:
322
626
 
323
627
  ```js
324
- I.retry().see('Welcome');
628
+ session('john', { browser: 'firefox' } , () => {
629
+ // run this steps in firefox
630
+ I.amOnPage('/');
631
+ });
325
632
  ```
326
633
 
327
- If you'd like to retry step more than once pass the amount as parameter:
634
+ or just start session without switching to it. Call `session` passing only its name:
328
635
 
329
636
  ```js
330
- I.retry(3).see('Welcome');
331
- ```
637
+ Scenario('test', (I) => {
638
+ // opens 3 additional browsers
639
+ session('john');
640
+ session('mary');
641
+ session('jane');
332
642
 
333
- Additional options can be provided to retry so you can set the additional options (defined in [promise-retry](https://www.npmjs.com/package/promise-retry) library).
643
+ I.amOnPage('/');
334
644
 
645
+ // switch to session by its name
646
+ session('mary', () => {
647
+ I.amOnPage('/login');
648
+ });
649
+ }
650
+ ```
651
+ `session` can return value which can be used in scenario:
335
652
 
336
653
  ```js
337
- // retry action 3 times waiting for 0.1 second before next try
338
- I.retry({ retries: 3, minTimeout: 100 }).see('Hello');
339
-
340
- // retry action 3 times waiting no more than 3 seconds for last retry
341
- I.retry({ retries: 3, maxTimeout: 3000 }).see('Hello');
342
-
343
- // retry 2 times if error with message 'Node not visible' happens
344
- I.retry({
345
- retries: 2,
346
- when: err => err.message === 'Node not visible'
347
- }).seeElement('#user');
654
+ // inside async function
655
+ const val = await session('john', () => {
656
+ I.amOnPage('/info');
657
+ return I.grabTextFrom({ css: 'h1' });
658
+ });
659
+ I.fillField('Description', val);
348
660
  ```
349
661
 
350
- Pass a function to `when` option to retry only when error matches the expected one.
662
+ Function passed into session can use `I`, page objects, and any objects declared for the scenario.
663
+ This function can also be declared as async (but doesn't work as generator).
351
664
 
352
- ### Auto Retry
665
+ Also, you can use `within` inside a session but you can't call session from inside `within`.
353
666
 
354
- You can auto-retry a failed step by enabling [retryFailedStep Plugin](https://codecept.io/plugins/#retryfailedstep).
355
667
 
356
- ### Retry Scenario
668
+ ## IntelliSense
357
669
 
358
- When you need to rerun scenarios few times just add `retries` option added to `Scenario` declaration.
670
+ If you are using Visual Studio Code or other IDE that supports TypeScript Definitions,
671
+ you can generate step definitions with
359
672
 
360
- CodeceptJS implements retries the same way [Mocha do](https://mochajs.org#retry-tests);
361
- You can set number of a retries for a feature:
673
+ ```sh
674
+ codeceptjs def
675
+ ```
362
676
 
363
- ```js
364
- Scenario('Really complex', (I) => {
365
- // test goes here
366
- }).retry(2);
677
+ Now you should create `jsconfig.json` in your project root directory.
367
678
 
368
- // alternative
369
- Scenario('Really complex', { retries: 2 }, (I) => {});
679
+ ```jsconfig.json
680
+ {
681
+ "compilerOptions": {
682
+ "allowJs": true,
683
+ }
684
+ }
370
685
  ```
686
+ but in usually case, this file has already generated when you execute `codeceptjs init`.
371
687
 
372
- This scenario will be restarted two times on a failure.
373
-
374
- ### Retry Feature
688
+ Alternatively, you can include `/// <reference path="./steps.d.ts" />` into your test files
689
+ to get method autocompletion while writing tests.
375
690
 
376
- To set this option for all scenarios in a file, add retry to a feature:
691
+ ## Skipping
377
692
 
378
- ```js
379
- Feature('Complex JS Stuff').retry(3);
380
- ```
693
+ Like in Mocha you can use `x` and `only` to skip tests or making a single test to run.
381
694
 
382
- Every Scenario inside this feature will be rerun 3 times.
383
- You can make an exception for a specific scenario by passing `retries` option to a Scenario.
695
+ * `xScenario` - skips current test
696
+ * `Scenario.only` - executes only the current test
package/docs/bdd.md CHANGED
@@ -138,11 +138,12 @@ This scenarios are nice as live documentation but they do not test anything yet.
138
138
  Steps can be defined by executing `gherkin:snippets` command:
139
139
 
140
140
  ```bash
141
- codeceptjs gherkin:snippets
141
+ codeceptjs gherkin:snippets [--path=PATH] [--feature=PATH]
142
142
  ```
143
143
 
144
- This will produce code templates for all undefined steps in all feature files of this suite.
145
- It will also place stub definitions into `step_definitions/steps.js` file.
144
+ This will produce code templates for all undefined steps in the .feature files.
145
+ By default, it will scan all of the .feature files specified in the gherkin.features section of the config and produce code templates for all undefined steps. If the `--feature` option is specified, it will scan the specified .feature file(s).
146
+ The stub definitions by default will be placed into the first file specified in the gherkin.steps section of the config. However, you may also use `--path` to specify a specific file in which to place all undefined steps. This file must exist and be in the gherkin.steps array of the config.
146
147
  Our next step will be to define those steps and transforming feature-file into a valid test.
147
148
 
148
149
  ### Step Definitions
package/docs/best.md CHANGED
@@ -61,7 +61,7 @@ Scenario('editing a metric', async (I, loginAs, metricPage) => {
61
61
 
62
62
  ## Refactoring and PageObjects
63
63
 
64
- When a project is growing and more and more tests are required, it's time to think about reusing test code accoross the tests. Some common actions should be moved from tests to other files so to be accessible from different tests.
64
+ When a project is growing and more and more tests are required, it's time to think about reusing test code across the tests. Some common actions should be moved from tests to other files so to be accessible from different tests.
65
65
 
66
66
  Here is a recommended strategy what to store where:
67
67
 
package/docs/books.md ADDED
@@ -0,0 +1,31 @@
1
+ ---
2
+ id: books
3
+ title: Books & Posts
4
+ ---
5
+
6
+ > Add your own books or posts to our [Wiki Page](https://github.com/Codeception/CodeceptJS/wiki/Books-&-Posts)
7
+ ### [Practical End 2 End Testing with CodeceptJS](https://leanpub.com/codeceptjs/)
8
+
9
+ A book by **Paul Vincent Beigang**
10
+
11
+ [![](https://user-images.githubusercontent.com/220264/58870454-e2e8ce80-86c8-11e9-868e-7deefdde47ce.png)](https://leanpub.com/codeceptjs/)
12
+
13
+ #### Contents:
14
+
15
+ 1. Preparation for End 2 End Testing with CodeceptJS
16
+ 1. Setup CodeceptJS with WebdriverIO
17
+ 1. Create Your First CodeceptJS Test
18
+ 1. Run Your First CodeceptJS Test Locally
19
+ 1. Run Test on BrowserStack Against with the Safari Browser
20
+ 1. How to Debug & Fix a Failing E2E Test
21
+ 1. Run a CodeceptJS Test in GitLab´s Continuous Integration (CI) Environment
22
+ 1. Delicious Test Reports With Allure
23
+
24
+ ### Posts
25
+
26
+ A list of good educational posts about CodeceptJS
27
+
28
+ * [Effective End2End Tests with CodeceptJS](https://hackernoon.com/effective-end-2-end-testing-in-javascript-with-codeceptjs-37c8d7d6a928) by @davertmik
29
+ * [Running End to End tests as Google Cloud Functions](https://hackernoon.com/running-end-to-end-tests-as-google-cloud-functions-f5e34ffc3984)
30
+ * [End-To-End Testing With CodeceptJS](https://www.monterail.com/blog/end-to-end-testing-with-codeceptjs) by Piotr Michalski
31
+ * [Getting started with CodeceptJS and Selenium WebDriver](https://medium.com/@garrettvorce/getting-started-with-selenium-and-codeceptjs-c0698e8df677)