codeceptjs 4.0.0-rc.2 → 4.0.0-rc.20

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 (294) hide show
  1. package/README.md +39 -27
  2. package/bin/codecept.js +15 -2
  3. package/bin/codeceptq.js +49 -0
  4. package/bin/mcp-server.js +1187 -0
  5. package/docs/advanced.md +201 -0
  6. package/docs/agents.md +159 -0
  7. package/docs/ai.md +537 -0
  8. package/docs/aitrace.md +266 -0
  9. package/docs/api.md +332 -0
  10. package/docs/assertions.md +415 -0
  11. package/docs/auth.md +318 -0
  12. package/docs/basics.md +424 -0
  13. package/docs/bdd.md +539 -0
  14. package/docs/best.md +240 -0
  15. package/docs/bootstrap.md +132 -0
  16. package/docs/commands.md +352 -0
  17. package/docs/community-helpers.md +63 -0
  18. package/docs/configuration.md +230 -0
  19. package/docs/continuous-integration.md +497 -0
  20. package/docs/custom-helpers.md +297 -0
  21. package/docs/data.md +448 -0
  22. package/docs/debugging.md +332 -0
  23. package/docs/detox.md +235 -0
  24. package/docs/docker.md +136 -0
  25. package/docs/effects.md +179 -0
  26. package/docs/element-based-testing.md +295 -0
  27. package/docs/element-selection.md +125 -0
  28. package/docs/els.md +328 -0
  29. package/docs/examples.md +161 -0
  30. package/docs/heal.md +213 -0
  31. package/docs/helpers/ApiDataFactory.md +267 -0
  32. package/docs/helpers/Appium.md +1405 -0
  33. package/docs/helpers/Detox.md +665 -0
  34. package/docs/helpers/ExpectHelper.md +275 -0
  35. package/docs/helpers/FileSystem.md +152 -0
  36. package/docs/helpers/GraphQL.md +152 -0
  37. package/docs/helpers/GraphQLDataFactory.md +226 -0
  38. package/docs/helpers/JSONResponse.md +255 -0
  39. package/docs/helpers/Mochawesome.md +8 -0
  40. package/docs/helpers/MockRequest.md +377 -0
  41. package/docs/helpers/MockServer.md +212 -0
  42. package/docs/helpers/Playwright.md +2969 -0
  43. package/docs/helpers/Polly.md +44 -0
  44. package/docs/helpers/Protractor.md +1769 -0
  45. package/docs/helpers/Puppeteer-firefox.md +86 -0
  46. package/docs/helpers/Puppeteer.md +2690 -0
  47. package/docs/helpers/REST.md +289 -0
  48. package/docs/helpers/SoftExpectHelper.md +352 -0
  49. package/docs/helpers/WebDriver.md +2682 -0
  50. package/docs/hooks.md +339 -0
  51. package/docs/index.md +111 -0
  52. package/docs/installation.md +83 -0
  53. package/docs/internal-api.md +265 -0
  54. package/docs/internal-test-server.md +89 -0
  55. package/docs/locators.md +355 -0
  56. package/docs/mcp.md +485 -0
  57. package/docs/migration-4.md +556 -0
  58. package/docs/mobile.md +338 -0
  59. package/docs/pageobjects.md +399 -0
  60. package/docs/parallel.md +585 -0
  61. package/docs/playwright.md +714 -0
  62. package/docs/plugins.md +866 -0
  63. package/docs/puppeteer.md +314 -0
  64. package/docs/quickstart.md +120 -0
  65. package/docs/react.md +70 -0
  66. package/docs/reports.md +483 -0
  67. package/docs/retry.md +274 -0
  68. package/docs/secrets.md +150 -0
  69. package/docs/sessions.md +80 -0
  70. package/docs/shadow.md +68 -0
  71. package/docs/test-structure.md +275 -0
  72. package/docs/timeouts.md +183 -0
  73. package/docs/translation.md +247 -0
  74. package/docs/tutorial.md +271 -0
  75. package/docs/typescript.md +374 -0
  76. package/docs/web-element.md +251 -0
  77. package/docs/webdriver.md +708 -0
  78. package/docs/within.md +55 -0
  79. package/lib/ai.js +3 -2
  80. package/lib/aria.js +260 -0
  81. package/lib/assertions.js +18 -0
  82. package/lib/codecept.js +26 -23
  83. package/lib/command/check.js +2 -1
  84. package/lib/command/dryRun.js +24 -5
  85. package/lib/command/generate.js +2 -0
  86. package/lib/command/gherkin/snippets.js +5 -4
  87. package/lib/command/init.js +248 -269
  88. package/lib/command/list.js +150 -10
  89. package/lib/command/query.js +218 -0
  90. package/lib/command/run-multiple.js +2 -0
  91. package/lib/command/run-workers.js +2 -0
  92. package/lib/command/run.js +1 -1
  93. package/lib/command/workers/runTests.js +10 -10
  94. package/lib/config.js +77 -4
  95. package/lib/container.js +114 -17
  96. package/lib/effects.js +17 -0
  97. package/lib/element/WebElement.js +246 -2
  98. package/lib/els.js +12 -6
  99. package/lib/globals.js +32 -19
  100. package/lib/heal.js +4 -3
  101. package/lib/helper/ApiDataFactory.js +2 -1
  102. package/lib/helper/Appium.js +8 -8
  103. package/lib/helper/FileSystem.js +3 -2
  104. package/lib/helper/GraphQLDataFactory.js +2 -1
  105. package/lib/helper/Playwright.js +228 -162
  106. package/lib/helper/Puppeteer.js +208 -76
  107. package/lib/helper/WebDriver.js +173 -68
  108. package/lib/helper/errors/MultipleElementsFound.js +27 -110
  109. package/lib/helper/errors/NonFocusedType.js +8 -0
  110. package/lib/helper/extras/Download.js +45 -0
  111. package/lib/helper/extras/PlaywrightReactVueLocator.js +45 -36
  112. package/lib/helper/extras/elementSelection.js +58 -0
  113. package/lib/helper/extras/focusCheck.js +43 -0
  114. package/lib/helper/extras/richTextEditor.js +178 -0
  115. package/lib/helper/scripts/dropFile.js +11 -0
  116. package/lib/history.js +3 -2
  117. package/lib/html.js +103 -16
  118. package/lib/index.js +9 -1
  119. package/lib/listener/config.js +6 -4
  120. package/lib/listener/emptyRun.js +2 -1
  121. package/lib/listener/globalRetry.js +32 -6
  122. package/lib/listener/helpers.js +4 -1
  123. package/lib/listener/mocha.js +2 -1
  124. package/lib/listener/pageobjects.js +43 -0
  125. package/lib/listener/result.js +3 -2
  126. package/lib/locator.js +126 -3
  127. package/lib/mocha/cli.js +14 -2
  128. package/lib/mocha/factory.js +7 -2
  129. package/lib/mocha/inject.js +1 -1
  130. package/lib/mocha/scenarioConfig.js +2 -1
  131. package/lib/mocha/ui.js +5 -6
  132. package/lib/parser.js +2 -2
  133. package/lib/pause.js +38 -4
  134. package/lib/plugin/aiTrace.js +453 -0
  135. package/lib/plugin/analyze.js +1 -1
  136. package/lib/plugin/auth.js +3 -3
  137. package/lib/plugin/browser.js +77 -0
  138. package/lib/plugin/expose.js +159 -0
  139. package/lib/plugin/heal.js +44 -1
  140. package/lib/plugin/pageInfo.js +53 -49
  141. package/lib/plugin/pause.js +131 -0
  142. package/lib/plugin/pauseOnFail.js +10 -34
  143. package/lib/plugin/retryFailedStep.js +28 -19
  144. package/lib/plugin/screencast.js +287 -0
  145. package/lib/plugin/screenshot.js +563 -0
  146. package/lib/plugin/screenshotOnFail.js +8 -171
  147. package/lib/rerun.js +2 -1
  148. package/lib/result.js +2 -1
  149. package/lib/step/base.js +3 -2
  150. package/lib/step/config.js +15 -2
  151. package/lib/step/record.js +2 -2
  152. package/lib/store.js +72 -3
  153. package/lib/translation.js +2 -1
  154. package/lib/utils/mask_data.js +2 -1
  155. package/lib/utils/pluginParser.js +151 -0
  156. package/lib/utils/trace.js +297 -0
  157. package/lib/utils.js +77 -3
  158. package/lib/workers.js +52 -22
  159. package/package.json +19 -13
  160. package/typings/index.d.ts +19 -5
  161. package/docs/webapi/amOnPage.mustache +0 -11
  162. package/docs/webapi/appendField.mustache +0 -11
  163. package/docs/webapi/attachFile.mustache +0 -12
  164. package/docs/webapi/blur.mustache +0 -18
  165. package/docs/webapi/checkOption.mustache +0 -13
  166. package/docs/webapi/clearCookie.mustache +0 -9
  167. package/docs/webapi/clearField.mustache +0 -9
  168. package/docs/webapi/click.mustache +0 -29
  169. package/docs/webapi/clickLink.mustache +0 -8
  170. package/docs/webapi/closeCurrentTab.mustache +0 -7
  171. package/docs/webapi/closeOtherTabs.mustache +0 -8
  172. package/docs/webapi/dontSee.mustache +0 -11
  173. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  174. package/docs/webapi/dontSeeCookie.mustache +0 -8
  175. package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
  176. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  177. package/docs/webapi/dontSeeElement.mustache +0 -8
  178. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  179. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  180. package/docs/webapi/dontSeeInField.mustache +0 -11
  181. package/docs/webapi/dontSeeInSource.mustache +0 -8
  182. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  183. package/docs/webapi/dontSeeTraffic.mustache +0 -13
  184. package/docs/webapi/doubleClick.mustache +0 -13
  185. package/docs/webapi/downloadFile.mustache +0 -12
  186. package/docs/webapi/dragAndDrop.mustache +0 -9
  187. package/docs/webapi/dragSlider.mustache +0 -11
  188. package/docs/webapi/executeAsyncScript.mustache +0 -24
  189. package/docs/webapi/executeScript.mustache +0 -26
  190. package/docs/webapi/fillField.mustache +0 -16
  191. package/docs/webapi/flushNetworkTraffics.mustache +0 -5
  192. package/docs/webapi/focus.mustache +0 -13
  193. package/docs/webapi/forceClick.mustache +0 -28
  194. package/docs/webapi/forceRightClick.mustache +0 -18
  195. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  196. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  197. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  198. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  199. package/docs/webapi/grabCookie.mustache +0 -11
  200. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  201. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  202. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  203. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  204. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  205. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  206. package/docs/webapi/grabGeoLocation.mustache +0 -8
  207. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  208. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  209. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  210. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  211. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  212. package/docs/webapi/grabPopupText.mustache +0 -5
  213. package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
  214. package/docs/webapi/grabSource.mustache +0 -8
  215. package/docs/webapi/grabTextFrom.mustache +0 -10
  216. package/docs/webapi/grabTextFromAll.mustache +0 -9
  217. package/docs/webapi/grabTitle.mustache +0 -8
  218. package/docs/webapi/grabValueFrom.mustache +0 -9
  219. package/docs/webapi/grabValueFromAll.mustache +0 -8
  220. package/docs/webapi/grabWebElement.mustache +0 -9
  221. package/docs/webapi/grabWebElements.mustache +0 -9
  222. package/docs/webapi/moveCursorTo.mustache +0 -12
  223. package/docs/webapi/openNewTab.mustache +0 -7
  224. package/docs/webapi/pressKey.mustache +0 -12
  225. package/docs/webapi/pressKeyDown.mustache +0 -12
  226. package/docs/webapi/pressKeyUp.mustache +0 -12
  227. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  228. package/docs/webapi/refreshPage.mustache +0 -6
  229. package/docs/webapi/resizeWindow.mustache +0 -6
  230. package/docs/webapi/rightClick.mustache +0 -14
  231. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  232. package/docs/webapi/saveScreenshot.mustache +0 -12
  233. package/docs/webapi/say.mustache +0 -10
  234. package/docs/webapi/scrollIntoView.mustache +0 -11
  235. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  236. package/docs/webapi/scrollPageToTop.mustache +0 -6
  237. package/docs/webapi/scrollTo.mustache +0 -12
  238. package/docs/webapi/see.mustache +0 -11
  239. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  240. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  241. package/docs/webapi/seeCookie.mustache +0 -8
  242. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  243. package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
  244. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  245. package/docs/webapi/seeElement.mustache +0 -8
  246. package/docs/webapi/seeElementInDOM.mustache +0 -8
  247. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  248. package/docs/webapi/seeInField.mustache +0 -12
  249. package/docs/webapi/seeInPopup.mustache +0 -8
  250. package/docs/webapi/seeInSource.mustache +0 -7
  251. package/docs/webapi/seeInTitle.mustache +0 -8
  252. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  253. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  254. package/docs/webapi/seeTextEquals.mustache +0 -9
  255. package/docs/webapi/seeTitleEquals.mustache +0 -8
  256. package/docs/webapi/seeTraffic.mustache +0 -36
  257. package/docs/webapi/selectOption.mustache +0 -21
  258. package/docs/webapi/setCookie.mustache +0 -16
  259. package/docs/webapi/setGeoLocation.mustache +0 -12
  260. package/docs/webapi/startRecordingTraffic.mustache +0 -8
  261. package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
  262. package/docs/webapi/stopRecordingTraffic.mustache +0 -5
  263. package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
  264. package/docs/webapi/switchTo.mustache +0 -9
  265. package/docs/webapi/switchToNextTab.mustache +0 -10
  266. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  267. package/docs/webapi/type.mustache +0 -21
  268. package/docs/webapi/uncheckOption.mustache +0 -13
  269. package/docs/webapi/wait.mustache +0 -8
  270. package/docs/webapi/waitForClickable.mustache +0 -11
  271. package/docs/webapi/waitForCookie.mustache +0 -9
  272. package/docs/webapi/waitForDetached.mustache +0 -10
  273. package/docs/webapi/waitForDisabled.mustache +0 -6
  274. package/docs/webapi/waitForElement.mustache +0 -11
  275. package/docs/webapi/waitForEnabled.mustache +0 -6
  276. package/docs/webapi/waitForFunction.mustache +0 -17
  277. package/docs/webapi/waitForInvisible.mustache +0 -10
  278. package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
  279. package/docs/webapi/waitForText.mustache +0 -13
  280. package/docs/webapi/waitForValue.mustache +0 -10
  281. package/docs/webapi/waitForVisible.mustache +0 -10
  282. package/docs/webapi/waitInUrl.mustache +0 -9
  283. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  284. package/docs/webapi/waitToHide.mustache +0 -10
  285. package/docs/webapi/waitUrlEquals.mustache +0 -10
  286. package/lib/helper/AI.js +0 -214
  287. package/lib/listener/enhancedGlobalRetry.js +0 -110
  288. package/lib/plugin/enhancedRetryFailedStep.js +0 -99
  289. package/lib/plugin/htmlReporter.js +0 -3648
  290. package/lib/plugin/stepByStepReport.js +0 -427
  291. package/lib/plugin/subtitles.js +0 -89
  292. package/lib/retryCoordinator.js +0 -207
  293. package/typings/promiseBasedTypes.d.ts +0 -9469
  294. package/typings/types.d.ts +0 -11402
package/docs/best.md ADDED
@@ -0,0 +1,240 @@
1
+ ---
2
+ permalink: /best
3
+ title: Best Practices
4
+ ---
5
+
6
+ # Best Practices
7
+
8
+ ## Focus on Readability
9
+
10
+ In CodeceptJS we encourage users to follow semantic elements on page while writing tests.
11
+ Instead of CSS/XPath locators try to stick to visible keywords on page.
12
+
13
+ Take a look into the next example:
14
+
15
+ ```js
16
+ // it's fine but...
17
+ I.click({css: 'nav.user .user-login'});
18
+ // can be better
19
+ I.click('Login', 'nav.user');
20
+ ```
21
+
22
+ If we replace raw CSS selector with a button title we can improve readability of such test.
23
+ Even if the text on the button changes, it's much easier to update it.
24
+
25
+ > If your code goes beyond using `I` object or page objects, you are probably doing something wrong.
26
+
27
+ When it's hard to match text to element we recommend using [locator builder](/locators#locator-builder). It allows to build complex locators via fluent API.
28
+ So if you want to click an element which is not a button or a link and use its text you can use `locate()` to build a readable locator:
29
+
30
+ ```js
31
+ // clicks element <span class="button">Click me</span>
32
+ I.click(locate('.button').withText('Click me'));
33
+ ```
34
+
35
+ ## Short Cuts
36
+
37
+ To write simpler and effective tests we encourage to use short cuts.
38
+ Make test be focused on one feature and try to simplify everything that is not related directly to test.
39
+
40
+ * If data is required for a test, try to create that data via API. See how to do it in [Data Management](/data) chapter.
41
+ * If user login is required, use [autoLogin plugin](/plugins#autoLogin) instead of putting login steps inside a test.
42
+ * Break a long test into few. Long test can be fragile and complicated to follow and update.
43
+ * Use [custom steps and page objects](/pageobjects) to hide steps which are not relevant to current test.
44
+
45
+ Make test as simple as:
46
+
47
+ ```js
48
+ Scenario('editing a metric', async ({ I, loginAs, metricPage }) => {
49
+ // login via autoLogin
50
+ loginAs('admin');
51
+ // create data with ApiDataFactory
52
+ const metric = await I.have('metric', { type: 'memory', duration: 'day' })
53
+ // use page object to open a page
54
+ metricPage.open(metric.id);
55
+ I.click('Edit');
56
+ I.see('Editing Metric');
57
+ // using a custom step
58
+ I.selectFromDropdown('duration', 'week');
59
+ I.click('Save');
60
+ I.see('Duration: Week', '.summary');
61
+ });
62
+ ```
63
+ ## Locators
64
+
65
+ * If you don't use multi-lingual website or you don't update texts often it is OK to click on links by their texts or match fields by their placeholders.
66
+ * If you don't want to rely on guessing locators, specify them manually with `{ css: 'button' }` or `{ xpath: '//button' }`. We call them strict locators. Those locators will be faster but less readable.
67
+ * Even better if you have a convention on active elements with special attributes like `data-test` or `data-qa`. Use `customLocator` plugin to easily add them to tests.
68
+ * Keep tests readable which will make them maintainable.
69
+
70
+ ## Page Objects
71
+
72
+ 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.
73
+
74
+ Here is a recommended strategy what to store where:
75
+
76
+ * Move site-wide actions into an **Actor** file (`custom_steps.js` file). Such actions like `login`, using site-wide common controls, like drop-downs, rich text editors, calendars.
77
+ * Move page-based actions and selectors into **Page Object**. All activities made on that page can go into methods of page object. If you test Single Page Application a PageObject should represent a screen of your application.
78
+ * When site-wide widgets are used, interactions with them should be placed in **Page Fragments**. This should be applied to global navigation, modals, widgets.
79
+ * A custom action that requires some low-level driver access, should be placed into a **Helper**. For instance, database connections, complex mouse actions, email testing, filesystem, services access.
80
+
81
+ > [Learn more](/pageobjects) about different refactoring options
82
+
83
+ However, it's recommended to not overengineer and keep tests simple. If a test code doesn't require reusage at this point it should not be transformed to use page objects.
84
+
85
+
86
+ * use page objects to store common actions
87
+ * don't make page objects for every page! Only for pages shared across different tests and suites.
88
+ * use classes for page objects, this allows inheritace. Export instance of that classes.
89
+ * if a page object is focused around a form with multiple fields in it, use a flexible set of arguments in it:
90
+
91
+ ```js
92
+ class CheckoutForm {
93
+
94
+ fillBillingInformation(data = {}) {
95
+ // take data in a flexible format
96
+ // iterate over fields to fill them all
97
+ for (let key of Object.keys(data)) {
98
+ I.fillField(key, data[key]); // like this one
99
+ }
100
+ }
101
+
102
+ }
103
+ export default new CheckoutForm();
104
+ export { CheckoutForm }; // for inheritance
105
+ ```
106
+
107
+ * for components that are repeated accross a website (widgets) but don't belong to any page, use component objects. They are the same as page objects but focused only aroung one element:
108
+
109
+ ```js
110
+ class DropDownComponent {
111
+
112
+ selectFirstItem(locator) {
113
+ I.click(locator);
114
+ I.click('#dropdown-items li');
115
+ }
116
+
117
+ selectItemByName(locator, name) {
118
+ I.click(locator);
119
+ I.click(locate('li').withText(name), '#dropdown-items');
120
+ }
121
+ }
122
+ ```
123
+ * another good example is datepicker component:
124
+ ```js
125
+ const { I } = inject();
126
+
127
+ /**
128
+ * Calendar works
129
+ */
130
+ class DatePicker {
131
+
132
+ selectToday(locator) {
133
+ I.click(locator);
134
+ I.click('.currentDate', '.date-picker');
135
+ }
136
+
137
+ selectInNextMonth(locator, date = '15') {
138
+ I.click(locator);
139
+ I.click('show next month', '.date-picker')
140
+ I.click(date, '.date-picker')
141
+ }
142
+
143
+ }
144
+
145
+
146
+ export default new DatePicker();
147
+ export { DatePicker }; // for inheritance
148
+ ```
149
+
150
+ ## Configuration
151
+
152
+ * create multiple config files for different setups/enrionments:
153
+ * `codecept.conf.js` - default one
154
+ * `codecept.ci.conf.js` - for CI
155
+ * `codecept.windows.conf.js` - for Windows, etc
156
+ * use `.env` files and dotenv package to load sensitive data
157
+
158
+ ```js
159
+ import 'dotenv/config'
160
+ ```
161
+
162
+ * move similar parts in those configs by moving them to modules and putting them to `config` dir
163
+ * when you need to load lots of page objects/components, you can get components/pageobjects file declaring them:
164
+
165
+ ```js
166
+ // inside config/components.js
167
+ export default {
168
+ DatePicker: "./components/datePicker",
169
+ Dropdown: "./components/dropdown",
170
+ }
171
+ ```
172
+
173
+ include them like this:
174
+
175
+ ```js
176
+ import pages from './config/pages.js'
177
+ import components from './config/components.js'
178
+
179
+ include: {
180
+ I: './steps_file',
181
+ ...pages, // import POs and DOs for module
182
+ ...components, // import all components
183
+ },
184
+ ```
185
+
186
+ * move long helpers configuration into `config/plugins.js` and export them
187
+ * move long configuration into `config/plugins.js` and export them
188
+ * inside config files import the exact helpers or plugins needed for this setup & environment
189
+ * to pass in data from config to a test use a container:
190
+
191
+ ```js
192
+ // inside codecept conf file
193
+ bootstrap: () => {
194
+ codeceptjs.container.append({
195
+ testUser: {
196
+ email: 'test@test.com',
197
+ password: '123456'
198
+ }
199
+ });
200
+ }
201
+ // now `testUser` can be injected into a test
202
+ ```
203
+ * (alternatively) if you have more test data to pass into tests, create a separate file for them and import them similarly to page object:
204
+
205
+ ```js
206
+ include: {
207
+ // ...
208
+ testData: './config/testData'
209
+
210
+ }
211
+ ```
212
+ * .env / different configs / different test data allows you to get configs for multiple environments
213
+
214
+ ## Data Access Objects
215
+
216
+ * Concept is similar to page objects but Data access objects can act like factories or data providers for tests
217
+ * Data Objects require REST or GraphQL helpers to be enabled for data interaction
218
+ * When you need to customize access to API and go beyond what ApiDataFactory provides, implement DAO:
219
+
220
+ ```js
221
+ import { faker } from '@faker-js/faker';
222
+ import { output } from 'codeceptjs';
223
+ const { I } = inject();
224
+
225
+ class InterfaceData {
226
+
227
+ async getLanguages() {
228
+ const { data } = await I.sendGetRequest('/api/languages');
229
+ const { records } = data;
230
+ output.debug(`Languages ${records.map(r => r.language)}`);
231
+ return records;
232
+ }
233
+
234
+ async getUsername() {
235
+ return faker.user.name();
236
+ }
237
+ }
238
+
239
+ export default new InterfaceData;
240
+ ```
@@ -0,0 +1,132 @@
1
+ ---
2
+ permalink: /bootstrap
3
+ title: Bootstrap
4
+ ---
5
+
6
+ # Bootstrap
7
+
8
+ In case you need to execute arbitrary code before or after the tests,
9
+ you can use the `bootstrap` and `teardown` config. Use it to start and stop a webserver, Selenium, etc.
10
+
11
+ When using the [parallel execution](/parallel) mode, there are two additional hooks available; `bootstrapAll` and `teardownAll`. See [bootstrapAll & teardownAll](#bootstrapall-teardownall) for more information.
12
+
13
+
14
+ ### Example: Bootstrap & Teardown
15
+
16
+ If you are using JavaScript-style config `codecept.conf.js`, bootstrap and teardown functions can be placed inside of it:
17
+
18
+ ```js
19
+ import server from './app_server.js';
20
+
21
+ export default {
22
+ tests: "./*_test.js",
23
+ helpers: {},
24
+
25
+ // adding bootstrap/teardown
26
+ async bootstrap() {
27
+ await server.launch();
28
+ },
29
+ async teardown() {
30
+ await server.stop();
31
+ }
32
+ // ...
33
+ // other config options
34
+ }
35
+
36
+ ```
37
+
38
+ ## BootstrapAll & TeardownAll
39
+
40
+ There are two additional hooks for [parallel execution](/parallel) in `run-multiple` or `run-workers` commands.
41
+
42
+ These hooks are only called in the parent process. Before child processes start (`bootstrapAll`) and after all of runs have finished (`teardownAll`). Each worker process will call `bootstrap` & `teardown` in their own process.
43
+
44
+ For example, when you run tests in 2 workers using the following command:
45
+
46
+ ```
47
+ npx codeceptjs run-workers 2
48
+ ```
49
+
50
+ First, `bootstrapAll` is called. Then two `bootstrap` runs in each of workers. Then tests in worker #1 ends and `teardown` is called. Same for worker #2. Finally, `teardownAll` runs in the main process.
51
+
52
+ > The same behavior is set for `run-multiple` command
53
+
54
+ The `bootstrapAll` and `teardownAll` hooks are preferred to use for setting up common logic of tested project: to start the application server or database or to start webdriver's grid.
55
+
56
+ The `bootstrap` and `teardown` hooks are used for setting up each testing browser: to create unique [cloud testing server](/helpers/WebDriver#cloud-providers) connection or to create specific browser-related test data in database (like users with names with browsername in it).
57
+
58
+ ### Example: BootstrapAll & TeardownAll Inside Config
59
+
60
+ Using JavaScript-style config `codecept.conf.js`, bootstrapAll and teardownAll functions can be placed inside of it:
61
+
62
+
63
+ ```js
64
+ import fs from 'fs';
65
+ const tempFolder = process.cwd() + '/tmpFolder';
66
+
67
+ export default {
68
+ tests: "./*_test.js",
69
+ helpers: {},
70
+
71
+ // adding bootstrapAll/teardownAll
72
+ async bootstrapAll() {
73
+ fs.mkdirSync(tempFolder);
74
+ },
75
+
76
+ async bootstrap() {
77
+ console.log('Do some pretty suite setup stuff');
78
+ },
79
+
80
+ async teardown() {
81
+ console.log('Cool, one of the workers have finished');
82
+ },
83
+
84
+ async teardownAll() {
85
+ console.log('All workers have finished running tests so we should clean up the temp folder');
86
+ fs.rmdirSync(tempFolder);
87
+ },
88
+
89
+ // ...
90
+ // other config options
91
+ }
92
+ ```
93
+
94
+ ## Combining Bootstrap & BootstrapAll
95
+
96
+ It is quite common that you expect that bootstrapAll and bootstrap will do the same thing. If an application server is already started in `bootstrapAll` we should not run it again inside `bootstrap` for each worker. To avoid code duplication we can run bootstrap script only when we are not inside a worker. CodeceptJS provides `store.workerMode` to detect if code is running in a worker process:
97
+
98
+ ```js
99
+ // inside codecept.conf.js
100
+
101
+ import store from 'codeceptjs/lib/store.js';
102
+
103
+ async function startServer() {
104
+ // implement starting server logic here
105
+ }
106
+ async function stopServer() {
107
+ // and stop server too
108
+ }
109
+
110
+
111
+ export default {
112
+ // codeceptjs config goes here
113
+
114
+ async bootstrapAll() {
115
+ await startServer();
116
+ },
117
+ async bootstrap() {
118
+ // start a server only if we are not in worker
119
+ if (!store.workerMode) return startServer();
120
+ }
121
+
122
+ async teardown() {
123
+ // stop a server only if we are not in worker
124
+ if (!store.workerMode) return stopServer();
125
+ }
126
+
127
+ async teardownAll() {
128
+ await stopServer();
129
+ },
130
+ }
131
+
132
+ ```