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
@@ -0,0 +1,271 @@
1
+ ---
2
+ permalink: /tutorial
3
+ title: CodeceptJS Complete Tutorial
4
+ ---
5
+
6
+ # Tutorial: Writing Tests for Checkout Page
7
+
8
+ **[CodeceptJS](https://codecept.io) is a popular open-source testing framework** for JavaScript. It is designed to simplify writing and maintain end-to-end tests for web applications, using a readable and intuitive syntax. To run tests in browser it uses **[Playwright](https://playwright.dev)** by default but ca execute tests via WebDriver, Puppeteer or Appium.
9
+
10
+ ## Let's get CodeceptJS installed!
11
+
12
+ To install CodeceptJS, you will need to have Node.js and npm (the Node.js package manager) installed on your system. You can check if you already have these tools installed by running the following commands in a terminal:
13
+
14
+ ```bash
15
+ node --version
16
+ npm --version
17
+ ```
18
+
19
+ If either of these commands return an error, you will need to install Node.js and npm before you can install CodeceptJS. You can download and install the latest version of Node.js from the official website, which includes npm.
20
+
21
+ To install CodeceptJS create a new folder and run command form terminal:
22
+
23
+ ```
24
+ npx create-codeceptjs .
25
+ ```
26
+
27
+ If you run the npx create-codeceptjs . command, it will install CodeceptJS with Playwright in the current directory.
28
+
29
+ > The `npx` command is a tool that comes with npm (the Node.js package manager) and it allows you to run npm packages without having to install them globally on your system.
30
+
31
+ It may take some time as it downloads browsers: Chrome, Firefox and Safari and creates a demo project.
32
+
33
+ But we are here to write a checkout test, right?
34
+
35
+ Let's initialize a new project for that!
36
+
37
+ Run
38
+
39
+ ```
40
+ npx codeceptjs init
41
+ ```
42
+ Agree on defaults (press Enter for every question asked). When asked for base site URL, provide a URL of a ecommerce website you are testing. For instance, it could be: `https://myshop.com` if you test already published website or `http://localhost` if you run the website locally.
43
+
44
+ When asked for a test name and suite name write "Checkout". It will create the following dirctory structure:
45
+
46
+ ```
47
+ .
48
+ ├── codecept.conf.js
49
+ ├── package.json
50
+ └── Checkout_test.js
51
+ ```
52
+
53
+ The `codecept.conf.js` file in the root of the project directory contains the global configuration settings for CodeceptJS.
54
+
55
+ Now open a test:
56
+
57
+ ```js
58
+ Feature('Checkout');
59
+
60
+ Scenario('test something', ({ I }) => {
61
+ });
62
+ ```
63
+ Inside the Scenario block you write a test.
64
+
65
+ Add `I.amOnPage('/')` into it. It will open the browser on a URL you specified as a base.
66
+
67
+ ```js
68
+ Feature('Checkout');
69
+
70
+ Scenario('test something', ({ I }) => {
71
+ I.amOnPage('/')
72
+ });
73
+ ```
74
+ But you may want to ask...
75
+
76
+ ## What is I?
77
+
78
+ Glad you asked!
79
+
80
+ In CodeceptJS, the `I` object is used to represent the user performing actions in a test scenario. It provides a number of methods (also known as actions) that can be used to simulate user interactions with the application under test.
81
+
82
+ Some of the most popular actions of the I object are:
83
+
84
+ * `I.amOnPage(url)`: This action navigates the user to the specified URL.
85
+ * `I.click(locator)`: This action simulates a click on the element identified by the given locator.
86
+ * `I.fillField(field, value)`: This action fills the specified field with the given value.
87
+ * `I.see(text, context)`: This action checks that the given text is visible on the page (or in the specified context).
88
+ * `I.selectOption(select, option)`: This action selects the specified option from the given select dropdown.
89
+ * `I.waitForElement(locator, timeout)`: This action waits for the specified element to appear on the page, up to the given timeout.
90
+ * `I.waitForText(text, timeout, context)`: This action waits for the given text to appear on the page (or in the specified context), up to the given timeout.
91
+
92
+ We will need to use them to navigate into Checkout process. How do we navigate web? Sure by clicking on links!
93
+
94
+ Let's use `I.click()` for that.
95
+
96
+ But how we can access elements on a webpage?
97
+
98
+ CodeceptJS is smart enough to locate clickable elements by their visible text. For instance, if on your ecommerce website you have a product 'Coffee Cup' with that exact name you can use
99
+
100
+ ```js
101
+ I.click('Coffee Cup');
102
+ ```
103
+
104
+ But sometimes elements are not as easy to locate, so you can use CSS or XPath locators to locate them.
105
+
106
+ For instance, locating Coffee Cup via CSS can take into accont HTML structure of a page and element attributes. For instance, it can be like this:
107
+
108
+ ```js
109
+ I.click('div.products a.product-name[title="Coffee Cup"]');
110
+ ```
111
+
112
+ In this example, the `div.products` part of the selector specifies a div element with the `products` class, and the `a.product-name[title="Coffee Cup"]` part specifies an a element with `the product-name` class and the `title` attribute set to Coffee Cup.
113
+
114
+ You can read more about HTML and CSS locators, and basically that's all what you need to know to start writing a checkout test!
115
+
116
+ ## Get back to Checkout
117
+
118
+ Let's see how a regular checkout script may look in CodeceptJS:
119
+
120
+ ```js
121
+ Scenario('test the checkout form', async ({ I }) => {
122
+ // we select one product and switched to checkout project
123
+ I.amOnPage('/');
124
+ I.click('Coffee Cup');
125
+ I.click('Purchase');
126
+ I.click('Checkout');
127
+
128
+ // fill in the shipping address
129
+ I.fillField('First Name', 'John');
130
+ I.fillField('Last Name', 'Doe');
131
+ I.fillField('Address', '123 Main St.');
132
+ I.fillField('City', 'New York');
133
+ I.selectOption('State', 'New York');
134
+ I.fillField('Zip Code', '10001');
135
+
136
+ // select a payment method
137
+ I.click('#credit-card-option');
138
+ I.fillField('Card Number', '1234-5678-9012-3456');
139
+ I.fillField('Expiration Date', '12/22');
140
+ I.fillField('Security Code', '123');
141
+
142
+ // click the checkout button
143
+ I.click('Checkout');
144
+
145
+ // verify that the checkout was successful
146
+ I.see('Your order has been placed successfully!');
147
+ });
148
+ ```
149
+ Sure, in relaity your script might be more complicated. As you have noticed, we used CSS locator `'#credit-card-option'` to get select a payment option. However, the test is simple and you can follow user steps through it.
150
+
151
+ Please note, that you shouldn't use a real credit card number here. Good news, you don't need to. Payment providers like Strip provide dummy card numbers for testing purposes.
152
+
153
+ Run the test with next command:
154
+
155
+ ```
156
+ npx codeceptjs run --debug -p pause
157
+ ```
158
+
159
+ What are special options here?
160
+
161
+ * `--debug` flag is used to output additional information to the console, such as the details of each step in the test, the values of variables, and the results of test assertions. This can help you to identify and fix any issues in your tests.
162
+ * `-p pause` option is also used to keep the browser opened even if a test fails (default `on=fail`). It will help us to identify to which point test was executed and what can be improved.
163
+
164
+ Add more test steps if needed, update locators, and notify business owners that all that purchases are made by you so your collegues won't call you in the night asking when you want to get a coffee cup 😀 Also the good idea is to run tests on staging website, to not interfere with business process.
165
+
166
+ What a test is complete you can run it with:
167
+
168
+ ```
169
+ npx codeceptjs run
170
+ ```
171
+
172
+ If you are annoyed to see a browser window you can use `HEADLESS` environment variable:
173
+
174
+ ```
175
+ HEADLESS=true codeceptjs run
176
+ ```
177
+ for Windows users HEADLESS should be set in a different manner:
178
+
179
+ ```
180
+ set HEADLESS=true&& codeceptjs run
181
+ ```
182
+ The tests will pass but no browser is shown, so you can watch YouTube videos while it goes!
183
+
184
+ ## Refactoring
185
+
186
+ What if you need to check more purchases? Should you copy paste your code for that?
187
+
188
+ No! You can use Page Object pattern to put repeating interactions into the reusable functions.
189
+
190
+ You can create a page object via next command:
191
+
192
+ ```
193
+ npx codeceptjs gpo
194
+ ```
195
+
196
+ Sure, we will call it `Checkout`. It will be created in `./pages/Checkout.js` file. You should enable it in `codecept.conf.js` inside `include` section:
197
+
198
+ ```js
199
+ include: {
200
+ ...
201
+ checkoutPage: './pages/Checkout.js',
202
+ },
203
+
204
+ ```
205
+ Now open this file:
206
+
207
+ ```js
208
+ const { I } = inject();
209
+
210
+ export default {
211
+
212
+ // insert your locators and methods here
213
+ }
214
+ ```
215
+
216
+ Feels really empty. What should we do about it? Should we write more code? No, we already have it. Let's copy code blocks from a test we have it and place them under a corredponnding function names:
217
+
218
+ ```js
219
+ const { I } = inject();
220
+
221
+ export default {
222
+
223
+ fillShippingAddress(name, address, city, state, zip) {
224
+ I.fillField('Name', name);
225
+ I.fillField('Address', address);
226
+ I.fillField('City', city);
227
+ I.fillField('State', state);
228
+ I.fillField('Zip', zip);
229
+ },
230
+
231
+ fillValidCreditCard() {
232
+ I.click('#credit-card-option');
233
+ I.fillField('Card Number', '1234-5678-9012-3456');
234
+ I.fillField('Expiration Date', '12/22');
235
+ I.fillField('Security Code', '123');
236
+ },
237
+
238
+ checkout() {
239
+ I.click('Checkout');
240
+ },
241
+ }
242
+ ```
243
+
244
+ After that we can update our test to use the created page object. Note, that we import Checkout PageObject by its name `checkoutPage` we previously defined in a config.
245
+
246
+ ```js
247
+ Scenario('test the checkout form', async ({I, checkoutPage}) => {
248
+ I.amOnPage('/');
249
+ I.click('Coffee Cup');
250
+ I.click('Purchase');
251
+ I.click('Checkout');
252
+
253
+ // fill in the shipping address using the page object
254
+ checkoutPage.fillShippingAddress('John', 'Doe', '123 Main St.', 'New York', 'New York', '10001');
255
+ checkoutPage.fillValidCreditCard();
256
+ checkoutPage.checkout();
257
+
258
+ // verify that the checkout was successful
259
+ I.see('Your order has been placed successfully!');
260
+ });
261
+ ```
262
+
263
+ As you see the code of a test was reduced. And we can write the similar tests on the same manner.
264
+
265
+ By applying more and more cases you can test a website to all behaviors.
266
+
267
+ ## Summary
268
+
269
+ If you think on just starting test automation, CodeceptJS is the best choice for you as it uses native language to pass commands to browser.
270
+
271
+ If you already skilled in JavaScript, with CodeceptJS you can focus on business level of your test, instead of writing code for browser. This way you can keep your tests stable and maintainable.
@@ -0,0 +1,374 @@
1
+ ---
2
+ permalink: /typescript
3
+ title: TypeScript
4
+ ---
5
+
6
+ # TypeScript
7
+
8
+ CodeceptJS supports [type declaration](https://github.com/codeceptjs/CodeceptJS/tree/master/typings) for [TypeScript](https://www.typescriptlang.org/). It means that you can write your tests in TS. Also, all of your custom steps can be written in TS
9
+
10
+ # Why TypeScript?
11
+
12
+ With the TypeScript writing CodeceptJS tests becomes much easier. If you configure TS properly in your project as well as your IDE, you will get the following features:
13
+ - [Autocomplete (with IntelliSense)](https://code.visualstudio.com/docs/editor/intellisense) - a tool that streamlines your work by suggesting when you typing what function or property which exists in a class, what arguments can be passed to that method, what it returns, etc.
14
+ Example:
15
+
16
+ ![Auto Complete](/img/Auto_comlete.gif)
17
+
18
+ - To show additional information for a step in a test. Example:
19
+
20
+ ![Quick Info](/img/Quick_info.gif)
21
+
22
+ - Checks types - thanks to TypeScript support in CodeceptJS now allow to tests your tests. TypeScript can prevent some errors:
23
+ - invalid type of variables passed to function;
24
+ - calls no-exist method from PageObject or `I` object;
25
+ - incorrectly used CodeceptJS features;
26
+
27
+
28
+ ## Getting Started <Badge text="Since 3.3.5" type="warning"/>
29
+
30
+ CodeceptJS can initialize tests as a TypeScript project.
31
+ When starting a new project with a standard installation via
32
+
33
+ ```
34
+ npx codeceptjs init
35
+ ```
36
+ Then select TypeScript as the first question:
37
+
38
+ ```
39
+ ? Do you plan to write tests in TypeScript? Yes
40
+ ```
41
+
42
+ Then a config file and new tests will be created in TypeScript format.
43
+
44
+ If a config file is set in TypeScript format (`codecept.conf.ts`) package `ts-node` will be used to run tests.
45
+
46
+ ## TypeScript Tests in ESM (CodeceptJS 4.x) <Badge text="Since 4.0.0" type="tip"/>
47
+
48
+ CodeceptJS 4.x uses ES Modules (ESM) which requires a different approach for TypeScript test files. While TypeScript **config files** (`codecept.conf.ts`) are automatically transpiled, TypeScript **test files** need a loader.
49
+
50
+ ### Using tsx (Recommended)
51
+
52
+ [tsx](https://tsx.is) is a modern, fast TypeScript loader built on esbuild. It's the recommended way to run TypeScript tests in CodeceptJS 4.x.
53
+
54
+ **Installation:**
55
+ ```bash
56
+ npm install --save-dev tsx
57
+ ```
58
+
59
+ **Configuration:**
60
+ ```typescript
61
+ // codecept.conf.ts
62
+ export const config = {
63
+ tests: './**/*_test.ts',
64
+ require: ['tsx/cjs'], // ← Enable TypeScript loader for test files
65
+ helpers: {
66
+ Playwright: {
67
+ url: 'http://localhost',
68
+ browser: 'chromium'
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ That's it! Now you can write tests in TypeScript with full language support:
75
+
76
+ ```typescript
77
+ // login_test.ts
78
+ Feature('Login')
79
+
80
+ Scenario('successful login', ({ I }) => {
81
+ I.amOnPage('/login')
82
+ I.fillField('email', 'user@example.com')
83
+ I.fillField('password', 'password123')
84
+ I.click('Login')
85
+ I.see('Welcome')
86
+ })
87
+ ```
88
+
89
+ **Why tsx?**
90
+ - ⚡ **Fast:** Built on esbuild, much faster than ts-node
91
+ - 🎯 **Zero config:** Works without tsconfig.json
92
+ - 🚀 **Works with Mocha:** Uses CommonJS hooks that Mocha understands
93
+ - ✅ **Complete:** Handles all TypeScript features (enums, decorators, etc.)
94
+
95
+ ### Using ts-node/esm (Not Recommended)
96
+
97
+ > ⚠️ **Note:** `ts-node/esm` has significant limitations with module resolution and doesn't work well with modern ESM TypeScript projects. **We strongly recommend using `tsx` instead.** The information below is provided for reference only.
98
+
99
+ `ts-node/esm` has several issues:
100
+ - Doesn't support `"type": "module"` in package.json
101
+ - Doesn't resolve extensionless imports or `.js` imports to `.ts` files
102
+ - Requires explicit `.ts` extensions in imports, which isn't standard TypeScript practice
103
+ - Less reliable than `tsx` for ESM scenarios
104
+
105
+ **If you still want to use ts-node/esm:**
106
+
107
+ ```bash
108
+ npm install --save-dev ts-node
109
+ ```
110
+
111
+ ```typescript
112
+ // codecept.conf.ts
113
+ export const config = {
114
+ tests: './**/*_test.ts',
115
+ require: ['ts-node/esm'],
116
+ helpers: { /* ... */ }
117
+ }
118
+ ```
119
+
120
+ ```json
121
+ // tsconfig.json
122
+ {
123
+ "compilerOptions": {
124
+ "module": "ESNext",
125
+ "target": "ES2022",
126
+ "moduleResolution": "node",
127
+ "esModuleInterop": true
128
+ },
129
+ "ts-node": {
130
+ "esm": true
131
+ }
132
+ }
133
+ ```
134
+
135
+ **Critical Limitations:**
136
+ - ❌ Cannot use `"type": "module"` in package.json
137
+ - ❌ Import statements must match the actual file (no automatic resolution)
138
+ - ❌ Module resolution doesn't work like standard TypeScript/Node.js ESM
139
+
140
+ **Recommendation:** Use `tsx/cjs` instead for a better experience.
141
+
142
+ ### Full TypeScript Features in Tests
143
+
144
+ With tsx or ts-node/esm, you can use complete TypeScript syntax including imports, enums, interfaces, and types:
145
+
146
+ ```typescript
147
+ // types.ts
148
+ export enum Environment {
149
+ TEST = 'test',
150
+ STAGING = 'staging',
151
+ PRODUCTION = 'production'
152
+ }
153
+
154
+ export interface User {
155
+ email: string
156
+ password: string
157
+ }
158
+
159
+ // login_test.ts
160
+ import { Environment, User } from './types'
161
+
162
+ const testUser: User = {
163
+ email: 'test@example.com',
164
+ password: 'password123'
165
+ }
166
+
167
+ Feature('Login')
168
+
169
+ Scenario(`Login on ${Environment.TEST}`, ({ I }) => {
170
+ I.amOnPage('/login')
171
+ I.fillField('email', testUser.email)
172
+ I.fillField('password', testUser.password)
173
+ I.click('Login')
174
+ I.see('Welcome')
175
+ })
176
+ ```
177
+
178
+ ### Troubleshooting TypeScript Tests
179
+
180
+ **Error: "Cannot find module" or "Unexpected token"**
181
+
182
+ This means the TypeScript loader isn't configured. Make sure:
183
+ 1. You have `tsx` or `ts-node` installed: `npm install --save-dev tsx`
184
+ 2. Your config includes the loader in `require` array: `require: ['tsx/cjs']`
185
+ 3. The loader is specified before test files are loaded
186
+
187
+ **Error: Module not found when importing from `.ts` files**
188
+
189
+ When using `ts-node/esm` with ESM, you need to use `.js` extensions in imports:
190
+
191
+ ```typescript
192
+ // This will cause an error in ESM mode:
193
+ import loginPage from "./pages/Login"
194
+
195
+ // Use .js extension instead:
196
+ import loginPage from "./pages/Login.js"
197
+ ```
198
+
199
+ TypeScript will resolve the `.js` import to your `.ts` file during compilation. This is the standard behavior for ESM + TypeScript.
200
+
201
+ Alternatively, use `tsx/cjs` which doesn't require explicit extensions.
202
+
203
+ **TypeScript config files vs test files**
204
+
205
+ Note the difference:
206
+ - **Config files** (`codecept.conf.ts`, helpers): Automatically transpiled by CodeceptJS
207
+ - **Test files** (`*_test.ts`): Need a loader specified in `config.require`
208
+
209
+ ### Migration from CodeceptJS 3.x
210
+
211
+ If you're upgrading from CodeceptJS 3.x (CommonJS) to 4.x (ESM):
212
+
213
+ **Old setup (3.x):**
214
+ ```javascript
215
+ // codecept.conf.js
216
+ module.exports = {
217
+ tests: './*_test.ts',
218
+ require: ['ts-node/register'], // CommonJS loader
219
+ helpers: {}
220
+ }
221
+ ```
222
+
223
+ **New setup (4.x):**
224
+ ```typescript
225
+ // codecept.conf.ts
226
+ export const config = {
227
+ tests: './*_test.ts',
228
+ require: ['tsx/cjs'], // TypeScript loader
229
+ helpers: {}
230
+ }
231
+ ```
232
+
233
+ **Migration steps:**
234
+ 1. Install tsx: `npm install --save-dev tsx`
235
+ 2. Update package.json: `"type": "module"`
236
+ 3. Rename config to `codecept.conf.ts` and use `export const config = {}`
237
+ 4. Change `require: ['ts-node/register']` to `require: ['tsx/cjs']`
238
+ 5. Run tests: `npx codeceptjs run`
239
+
240
+ ## Promise-Based Typings
241
+
242
+ By default, CodeceptJS tests are written in synchronous mode. This is a regular CodeceptJS test:
243
+
244
+ ```js
245
+ I.amOnPage('/')
246
+ I.click('Login')
247
+ I.see('Hello!')
248
+ ```
249
+
250
+ Even thought we don't see any `await`, those commands are executed synchronously, one by one.
251
+ All methods of `I` object actually return promise and TypeScript linter requires to use `await` operator for those promises.
252
+ To trick TypeScript and allow writing tests in CodeceptJS manner we create typings where `void` is returned instead of promises. This way linter won't complain on async code without await, as no promise is returned.
253
+
254
+ Our philosophy here is: use `await` only when it is actually needed, don't add visual mess to your code prefixing each line with `await`. However, you might want to get a better control of your tests and follow TypeScript conventions.
255
+ This is why you might want to **enable promise-based typings**.
256
+
257
+ A previous test should be rewritten with `await`s:
258
+
259
+ ```js
260
+ await I.amOnPage('/')
261
+ await I.click('Login')
262
+ await I.see('Hello!')
263
+ ```
264
+
265
+ Using `await` explicitly provides a beter control of execution flow. Some CodeceptJS users report that they increased stability of tests by adopting `await` for all CodeceptJS commands in their codebase.
266
+
267
+ If you select to use promise-based typings, type definitions will be generated so all actions to return a promise.
268
+ Otherwise they will still return promises but it won't be relfected in type definitions.
269
+
270
+ To introduce promise-based typings into a current project edit `codecept.conf.ts`:
271
+
272
+ ```ts
273
+ fullPromiseBased: true;
274
+ ```
275
+
276
+ and rebuild type definitions with
277
+
278
+ ```
279
+ npx codeceptjs def
280
+ ```
281
+
282
+ ## Types for custom helper or page object
283
+
284
+ If you want to get types for your [custom helper](https://codecept.io/helpers/#configuration), you can add their automatically with CodeceptJS command `npx codeceptjs def`.
285
+
286
+ For example, if you add the new step `printMessage` for your custom helper like this:
287
+ ```js
288
+ // customHelper.ts
289
+ export class CustomHelper extends Helper {
290
+ printMessage(msg: string) {
291
+ console.log(msg)
292
+ }
293
+ }
294
+
295
+ ```
296
+
297
+ Then you need to add this helper to your `codecept.conf.js` like in this [docs](https://codecept.io/helpers/#configuration).
298
+ And then run the command `npx codeceptjs def`.
299
+
300
+ As result our `steps.d.ts` file will be updated like this:
301
+ ```ts
302
+ /// <reference types='codeceptjs' />
303
+ type CustomHelper = import('./CustomHelper');
304
+
305
+ declare namespace CodeceptJS {
306
+ interface SupportObject { I: I }
307
+ interface Methods extends Puppeteer, CustomHelper {}
308
+ interface I extends WithTranslation<Methods> {}
309
+ namespace Translation {
310
+ interface Actions {}
311
+ }
312
+ }
313
+ ```
314
+
315
+ And now you can use autocomplete on your test.
316
+
317
+ Generation types for PageObject looks like for a custom helper, but `steps.d.ts` will look like:
318
+ ```ts
319
+ /// <reference types='codeceptjs' />
320
+ type loginPage = typeof import('./loginPage');
321
+ type homePage = typeof import('./homePage');
322
+ type CustomHelper = import('./CustomHelper');
323
+
324
+ declare namespace CodeceptJS {
325
+ interface SupportObject { I: I, loginPage: loginPage, homePage: homePage }
326
+ interface Methods extends Puppeteer, CustomHelper {}
327
+ interface I extends WithTranslation<Methods> {}
328
+ namespace Translation {
329
+ interface Actions {}
330
+ }
331
+ }
332
+ ```
333
+
334
+ ## Types for custom strict locators
335
+
336
+ You can define [custom strict locators](https://codecept.io/locators/#custom-strict-locators) that can be used in all methods taking a locator (parameter type `LocatorOrString`).
337
+
338
+ Example: A custom strict locator with a `data` property, which can be used like this:
339
+
340
+ ```ts
341
+ I.click({ data: 'user-login' });
342
+ ```
343
+
344
+ In order to use the custom locator in TypeScript code, its type shape needs to be registered in the interface `CustomLocators` in your `steps.d.ts` file:
345
+
346
+ ```ts
347
+ /// <reference types='codeceptjs' />
348
+ ...
349
+
350
+ declare namespace CodeceptJS {
351
+ ...
352
+
353
+ interface CustomLocators {
354
+ data: { data: string };
355
+ }
356
+ }
357
+ ```
358
+
359
+ The property keys used in the `CustomLocators` interface do not matter (only the *types* of the interface properties are used). For simplicity it is recommended to use the name that is also used in your custom locator itself.
360
+
361
+ You can also define more complicated custom locators with multiple (also optional) properties:
362
+
363
+ ```ts
364
+ /// <reference types='codeceptjs' />
365
+ ...
366
+
367
+ declare namespace CodeceptJS {
368
+ ...
369
+
370
+ interface CustomLocators {
371
+ data: { data: string, value?: number, flag?: boolean };
372
+ }
373
+ }
374
+ ```