codeceptjs 4.0.0-rc.22 → 4.0.0-rc.24

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 (82) hide show
  1. package/README.md +9 -10
  2. package/docs/ai.md +3 -51
  3. package/docs/architecture.md +16 -0
  4. package/docs/bootstrap.md +1 -1
  5. package/docs/continuous-integration.md +16 -44
  6. package/docs/custom-helpers.md +1 -1
  7. package/docs/detox.md +1 -1
  8. package/docs/docker.md +1 -30
  9. package/docs/examples.md +0 -1
  10. package/docs/helpers/Appium.md +16 -2
  11. package/docs/helpers/Playwright.md +161 -160
  12. package/docs/helpers/Puppeteer.md +143 -250
  13. package/docs/helpers/WebDriver.md +134 -177
  14. package/docs/hooks.md +11 -1
  15. package/docs/index.md +1 -1
  16. package/docs/installation.md +2 -19
  17. package/docs/locators.md +1 -1
  18. package/docs/migrate-from-cypress.md +98 -0
  19. package/docs/migrate-from-java.md +108 -0
  20. package/docs/migrate-from-protractor.md +101 -0
  21. package/docs/migrate-from-testcafe.md +99 -0
  22. package/docs/migration-4.md +195 -8
  23. package/docs/plugins/aiTrace.md +49 -0
  24. package/docs/plugins/analyze.md +66 -0
  25. package/docs/plugins/auth.md +241 -0
  26. package/docs/plugins/autoDelay.md +48 -0
  27. package/docs/plugins/browser.md +41 -0
  28. package/docs/plugins/coverage.md +39 -0
  29. package/docs/plugins/customLocator.md +119 -0
  30. package/docs/plugins/customReporter.md +16 -0
  31. package/docs/plugins/expose.md +75 -0
  32. package/docs/plugins/heal.md +44 -0
  33. package/docs/plugins/junitReporter.md +51 -0
  34. package/docs/plugins/pageInfo.md +34 -0
  35. package/docs/plugins/pause.md +43 -0
  36. package/docs/plugins/pauseOnFail.md +18 -0
  37. package/docs/plugins/retryFailedStep.md +75 -0
  38. package/docs/plugins/screencast.md +55 -0
  39. package/docs/plugins/screenshot.md +58 -0
  40. package/docs/plugins/screenshotOnFail.md +18 -0
  41. package/docs/plugins/stepTimeout.md +65 -0
  42. package/docs/plugins.md +40 -862
  43. package/docs/reports.md +18 -4
  44. package/docs/retry.md +48 -18
  45. package/docs/store.md +94 -0
  46. package/docs/timeouts.md +1 -1
  47. package/docs/tutorial.md +207 -155
  48. package/docs/webdriver.md +6 -73
  49. package/lib/actor.js +1 -36
  50. package/lib/command/run-multiple.js +1 -2
  51. package/lib/heal.js +2 -2
  52. package/lib/helper/Playwright.js +1 -15
  53. package/lib/helper/Puppeteer.js +0 -103
  54. package/lib/helper/WebDriver.js +1 -28
  55. package/lib/helper/extras/PlaywrightLocator.js +10 -0
  56. package/lib/locator.js +0 -13
  57. package/lib/plugin/aiTrace.js +4 -3
  58. package/lib/plugin/analyze.js +3 -4
  59. package/lib/plugin/junitReporter.js +1 -1
  60. package/lib/plugin/pauseOnFail.js +3 -1
  61. package/lib/plugin/retryFailedStep.js +11 -10
  62. package/lib/plugin/screencast.js +1 -1
  63. package/lib/plugin/screenshot.js +2 -7
  64. package/lib/plugin/screenshotOnFail.js +3 -1
  65. package/lib/plugin/stepTimeout.js +3 -2
  66. package/lib/recorder.js +1 -1
  67. package/lib/step/base.js +7 -7
  68. package/lib/step/comment.js +2 -2
  69. package/lib/step/helper.js +4 -4
  70. package/lib/step/meta.js +3 -3
  71. package/lib/step/record.js +3 -3
  72. package/lib/workers.js +0 -4
  73. package/package.json +3 -4
  74. package/docs/helpers/Mochawesome.md +0 -8
  75. package/docs/helpers/MockServer.md +0 -212
  76. package/docs/helpers/Polly.md +0 -44
  77. package/docs/helpers/Protractor.md +0 -1769
  78. package/docs/helpers/SoftExpectHelper.md +0 -352
  79. package/docs/react.md +0 -70
  80. package/lib/helper/Mochawesome.js +0 -96
  81. package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -61
  82. package/lib/helper/extras/React.js +0 -65
package/docs/tutorial.md CHANGED
@@ -3,45 +3,38 @@ permalink: /tutorial
3
3
  title: CodeceptJS Complete Tutorial
4
4
  ---
5
5
 
6
- # Tutorial: Writing Tests for Checkout Page
6
+ # Tutorial: Testing a Checkout Page
7
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.
8
+ **[CodeceptJS](https://codecept.io) is a popular open-source end-to-end testing framework** for JavaScript. It is designed to make web tests readable and easy to maintain by writing them as a linear scenario of user actions. By default it drives the browser with **[Playwright](https://playwright.dev)**, but the same tests can run via WebDriver, Puppeteer, or Appium without changes.
9
9
 
10
- ## Let's get CodeceptJS installed!
10
+ In this tutorial we write a real, runnable test for the **[Bootstrap checkout example](https://getbootstrap.com/docs/4.0/examples/checkout/)** — a public page with a billing and payment form. By the end you will have a clean test and a reusable page object.
11
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:
12
+ ## Install CodeceptJS
13
+
14
+ You need Node.js (and npm) installed. Check with:
13
15
 
14
16
  ```bash
15
17
  node --version
16
18
  npm --version
17
19
  ```
18
20
 
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:
21
+ Create a new folder, then install CodeceptJS together with Playwright:
22
22
 
23
+ ```bash
24
+ npm init -y
25
+ npm install codeceptjs playwright --save-dev
26
+ npx playwright install --with-deps
23
27
  ```
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
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.
29
+ `npx playwright install` downloads the Chromium, Firefox, and WebKit browsers; `--with-deps` also installs the system libraries they need.
30
30
 
31
- It may take some time as it downloads browsers: Chrome, Firefox and Safari and creates a demo project.
31
+ Now scaffold the project:
32
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
- ```
33
+ ```bash
40
34
  npx codeceptjs init
41
35
  ```
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
36
 
44
- When asked for a test name and suite name write "Checkout". It will create the following dirctory structure:
37
+ `init` runs a short wizard. Accept the defaults when asked for the **base URL** enter `https://getbootstrap.com`, and name the first test **Checkout**. This creates:
45
38
 
46
39
  ```
47
40
  .
@@ -50,9 +43,31 @@ When asked for a test name and suite name write "Checkout". It will create the f
50
43
  └── Checkout_test.js
51
44
  ```
52
45
 
53
- The `codecept.conf.js` file in the root of the project directory contains the global configuration settings for CodeceptJS.
46
+ `codecept.conf.js` holds the project configuration. Because CodeceptJS 4.x uses **ES modules**, the config and tests use `import`/`export` syntax — `init` sets `"type": "module"` in `package.json` for you.
54
47
 
55
- Now open a test:
48
+ Open `codecept.conf.js`. The two settings that matter here are the helper and the base URL:
49
+
50
+ ```js
51
+ import { setHeadlessWhen } from '@codeceptjs/configure'
52
+
53
+ // show the browser locally, run headless on CI
54
+ setHeadlessWhen(process.env.CI)
55
+
56
+ export const config = {
57
+ tests: './*_test.js',
58
+ output: './output',
59
+ helpers: {
60
+ Playwright: {
61
+ url: 'https://getbootstrap.com',
62
+ browser: 'chromium',
63
+ },
64
+ },
65
+ }
66
+ ```
67
+
68
+ ## Your First Test
69
+
70
+ Open `Checkout_test.js`:
56
71
 
57
72
  ```js
58
73
  Feature('Checkout');
@@ -60,212 +75,249 @@ Feature('Checkout');
60
75
  Scenario('test something', ({ I }) => {
61
76
  });
62
77
  ```
63
- Inside the Scenario block you write a test.
64
78
 
65
- Add `I.amOnPage('/')` into it. It will open the browser on a URL you specified as a base.
79
+ A test lives inside a `Scenario` block. Let's open the checkout page:
66
80
 
67
81
  ```js
68
82
  Feature('Checkout');
69
83
 
70
84
  Scenario('test something', ({ I }) => {
71
- I.amOnPage('/')
85
+ I.amOnPage('/docs/4.0/examples/checkout/');
72
86
  });
73
87
  ```
74
- But you may want to ask...
75
-
76
- ## What is I?
77
88
 
78
- Glad you asked!
89
+ `I.amOnPage()` navigates the browser. Because the path is relative, it is appended to the base URL from the config — keep the base URL in config so you can switch between staging and production without touching tests.
79
90
 
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.
91
+ But you may be wondering...
81
92
 
82
- Some of the most popular actions of the I object are:
93
+ ### What is `I`?
83
94
 
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.
95
+ In CodeceptJS the `I` object is the **actor** — it represents the user performing actions. It exposes methods (called *actions*) that simulate interactions with the app:
91
96
 
92
- We will need to use them to navigate into Checkout process. How do we navigate web? Sure by clicking on links!
97
+ - `I.amOnPage(url)` navigate to a URL
98
+ - `I.click(locator)` — click an element
99
+ - `I.fillField(field, value)` — type into an input
100
+ - `I.selectOption(select, option)` — choose an option in a dropdown
101
+ - `I.checkOption(locator)` — tick a checkbox or radio
102
+ - `I.see(text)` — assert that text is visible
103
+ - `I.seeInField(field, value)` — assert an input holds a value
93
104
 
94
- Let's use `I.click()` for that.
105
+ CodeceptJS **waits automatically** before clicking, filling, and most other actions, so you rarely need explicit waits. Steps also write themselves into a promise chain, so you usually **don't need `await`** for regular actions — only for `grab*` actions and page object methods that return data.
95
106
 
96
- But how we can access elements on a webpage?
107
+ ### Locating Elements
97
108
 
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
109
+ Most actions accept a locator. CodeceptJS supports several strategies prefer the readable ones:
99
110
 
100
111
  ```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.
112
+ // by visible text / label
113
+ I.click('Continue to checkout');
114
+ I.fillField('First name', 'John');
105
115
 
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:
116
+ // by ARIA role and accessible name (resilient to CSS changes)
117
+ I.click({ role: 'button', name: 'Continue to checkout' });
107
118
 
108
- ```js
109
- I.click('div.products a.product-name[title="Coffee Cup"]');
119
+ // by CSS or XPath, when nothing semantic is available
120
+ I.fillField('#email', 'john@example.com');
110
121
  ```
111
122
 
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.
123
+ > **Best practice:** prefer labels and ARIA locators (`{ role, name }`). They survive styling changes and document intent. Fall back to CSS/XPath only when needed.
113
124
 
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!
125
+ ## Writing the Checkout Test
115
126
 
116
- ## Get back to Checkout
117
-
118
- Let's see how a regular checkout script may look in CodeceptJS:
127
+ The Bootstrap checkout form has billing fields, country/state selects, and a payment section. CodeceptJS finds inputs by their visible `<label>`, so the test reads like the form:
119
128
 
120
129
  ```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');
130
+ Feature('Checkout');
141
131
 
142
- // click the checkout button
143
- I.click('Checkout');
132
+ Scenario('fill in the checkout form', ({ I }) => {
133
+ I.amOnPage('/docs/4.0/examples/checkout/');
134
+ I.see('Checkout form');
144
135
 
145
- // verify that the checkout was successful
146
- I.see('Your order has been placed successfully!');
136
+ // billing address fields located by their labels
137
+ I.fillField('First name', 'John');
138
+ I.fillField('Last name', 'Doe');
139
+ I.fillField('Username', 'johndoe');
140
+ I.fillField('#email', 'john@example.com'); // label has "(Optional)", use CSS
141
+ I.fillField('Address', '123 Main St.');
142
+ I.selectOption('Country', 'United States');
143
+ I.selectOption('State', 'California');
144
+ I.fillField('Zip', '10001');
145
+
146
+ // shipping / preferences
147
+ I.checkOption('Shipping address is the same as my billing address');
148
+ I.checkOption('Save this information for next time');
149
+
150
+ // payment — "Credit card" is selected by default
151
+ I.click('Credit card');
152
+ I.fillField('Name on card', 'John Doe');
153
+ I.fillField('Credit card number', secret('4111 1111 1111 1111'));
154
+
155
+ // verify the form holds what we entered
156
+ I.seeInField('First name', 'John');
157
+ I.seeInField('Address', '123 Main St.');
158
+ I.click('Continue to checkout');
147
159
  });
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
160
  ```
158
161
 
159
- What are special options here?
162
+ A few things worth noting:
160
163
 
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.
164
+ - **`secret()`** wraps the card number so it is masked (`****`) in logs and reports. Use it for any sensitive value see [Secrets](/secrets).
165
+ - Never use a real card number. Payment providers like Stripe publish [test card numbers](https://docs.stripe.com/testing) for exactly this.
166
+ - This is a static demo page with no backend, so we verify by reading field values back with `I.seeInField`. On a real shop you would assert a confirmation, e.g. `I.see('Your order has been placed')`.
163
167
 
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.
168
+ ### A Negative Scenario
165
169
 
166
- What a test is complete you can run it with:
170
+ Good test suites cover failures too. The form validates on submit — submitting it empty shows error messages. CodeceptJS doesn't allow multiple scenarios in one file's suite to nest, but you can add as many `Scenario` blocks as you like:
167
171
 
168
- ```
169
- npx codeceptjs run
172
+ ```js
173
+ Scenario('shows validation errors on empty submit', ({ I }) => {
174
+ I.amOnPage('/docs/4.0/examples/checkout/');
175
+ I.click('Continue to checkout');
176
+ I.see('Valid first name is required.');
177
+ });
170
178
  ```
171
179
 
172
- If you are annoyed to see a browser window you can use `HEADLESS` environment variable:
180
+ ### Running the Test
173
181
 
182
+ ```bash
183
+ npx codeceptjs run --steps
174
184
  ```
175
- HEADLESS=true codeceptjs run
176
- ```
177
- for Windows users HEADLESS should be set in a different manner:
178
185
 
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!
186
+ `--steps` prints every step as it runs. Useful flags while developing:
183
187
 
184
- ## Refactoring
188
+ - `--steps` — print each step
189
+ - `--debug` — steps plus extra debug output (recommended while writing tests)
190
+ - `--verbose` — everything, including the promise chain
185
191
 
186
- What if you need to check more purchases? Should you copy paste your code for that?
192
+ Set a breakpoint to inspect the page interactively by adding `pause()` to the scenario:
187
193
 
188
- No! You can use Page Object pattern to put repeating interactions into the reusable functions.
194
+ ```js
195
+ Scenario('fill in the checkout form', ({ I }) => {
196
+ I.amOnPage('/docs/4.0/examples/checkout/');
197
+ I.fillField('First name', 'John');
198
+ pause(); // test stops here; type steps live in the browser
199
+ });
200
+ ```
189
201
 
190
- You can create a page object via next command:
202
+ In the pause shell you can type `I.click('...')`, inspect the page, and find better locators. See [Debugging](/debugging).
191
203
 
204
+ The browser is shown locally and runs headless on CI thanks to `setHeadlessWhen(process.env.CI)`. To force it either way for one run:
205
+
206
+ ```bash
207
+ npx codeceptjs run --headless
192
208
  ```
193
- npx codeceptjs gpo
209
+
210
+ Once the test is stable, run the whole suite:
211
+
212
+ ```bash
213
+ npx codeceptjs run
194
214
  ```
195
215
 
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:
216
+ ## Refactoring with a Page Object
197
217
 
198
- ```js
199
- include: {
200
- ...
201
- checkoutPage: './pages/Checkout.js',
202
- },
218
+ What if more tests need to fill this form? Copy-pasting steps doesn't scale. The **Page Object** pattern keeps locators and interactions in one reusable place.
203
219
 
204
- ```
205
- Now open this file:
220
+ Generate one:
206
221
 
207
- ```js
208
- const { I } = inject();
222
+ ```bash
223
+ npx codeceptjs gpo
224
+ ```
209
225
 
210
- export default {
226
+ Call it `Checkout`. It is created in `./pages/Checkout.js` and registered in `codecept.conf.js` under `include`:
211
227
 
212
- // insert your locators and methods here
228
+ ```js
229
+ export const config = {
230
+ // ...
231
+ include: {
232
+ checkoutPage: './pages/Checkout.js',
233
+ },
213
234
  }
214
235
  ```
215
236
 
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:
237
+ Page objects are **classes**. Move the form interactions into named methods:
217
238
 
218
239
  ```js
219
240
  const { I } = inject();
220
241
 
221
- export default {
242
+ class CheckoutPage {
243
+ url = '/docs/4.0/examples/checkout/'
244
+
245
+ open() {
246
+ I.amOnPage(this.url);
247
+ I.see('Checkout form');
248
+ }
222
249
 
223
- fillShippingAddress(name, address, city, state, zip) {
224
- I.fillField('Name', name);
250
+ fillBillingAddress({ firstName, lastName, username, address, country, state, zip }) {
251
+ I.fillField('First name', firstName);
252
+ I.fillField('Last name', lastName);
253
+ I.fillField('Username', username);
225
254
  I.fillField('Address', address);
226
- I.fillField('City', city);
227
- I.fillField('State', state);
255
+ I.selectOption('Country', country);
256
+ I.selectOption('State', state);
228
257
  I.fillField('Zip', zip);
229
- },
258
+ }
230
259
 
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
- },
260
+ payWithCard(name, number) {
261
+ I.click('Credit card');
262
+ I.fillField('Name on card', name);
263
+ I.fillField('Credit card number', secret(number));
264
+ }
237
265
 
238
- checkout() {
239
- I.click('Checkout');
240
- },
266
+ submit() {
267
+ I.click('Continue to checkout');
268
+ }
241
269
  }
270
+
271
+ export default CheckoutPage
242
272
  ```
243
273
 
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.
274
+ > `inject()` returns a lazy proxy, so it's safe to destructure `I` before the class. Export the **class** CodeceptJS auto-instantiates it. (Plain-object page objects still work but classes support lifecycle hooks and inheritance.)
275
+
276
+ The test now reads at the business level. Inject `checkoutPage` by the name you set in the config:
245
277
 
246
278
  ```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!');
279
+ Feature('Checkout');
280
+
281
+ Scenario('complete a checkout', ({ I, checkoutPage }) => {
282
+ checkoutPage.open();
283
+ checkoutPage.fillBillingAddress({
284
+ firstName: 'John',
285
+ lastName: 'Doe',
286
+ username: 'johndoe',
287
+ address: '123 Main St.',
288
+ country: 'United States',
289
+ state: 'California',
290
+ zip: '10001',
291
+ });
292
+ checkoutPage.payWithCard('John Doe', '4111 1111 1111 1111');
293
+ checkoutPage.submit();
294
+
295
+ I.seeInField('First name', 'John');
260
296
  });
261
297
  ```
262
298
 
263
- As you see the code of a test was reduced. And we can write the similar tests on the same manner.
299
+ Shorter, intention-revealing, and every other checkout test can reuse the same methods. As coverage grows, add methods to the page object instead of duplicating steps.
300
+
301
+ ## Going Further
302
+
303
+ When you have many tests, run them in parallel using Node workers:
304
+
305
+ ```bash
306
+ npx codeceptjs run-workers 3
307
+ ```
308
+
309
+ From here, explore:
264
310
 
265
- By applying more and more cases you can test a website to all behaviors.
311
+ - [Locators](/locators) every locating strategy in depth
312
+ - [Page Objects](/pageobjects) — fragments, step objects, lifecycle hooks
313
+ - [Data-driven tests](/data) — run one scenario over many inputs
314
+ - [Debugging](/debugging) — `pause()`, the interactive shell, and AI-assisted debugging
315
+ - [Continuous Integration](/continuous-integration) — running the suite on CI
266
316
 
267
317
  ## Summary
268
318
 
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.
319
+ If you are just starting with test automation, CodeceptJS lets you describe tests in near-natural language and handles waiting and retries for you. If you already know JavaScript, page objects and dependency injection keep your suite focused on business behavior — which is what keeps tests stable and maintainable as the app grows.
270
320
 
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.
321
+ > [▶ Next: CodeceptJS Basics](/basics/)
322
+ </content>
323
+ </invoke>
package/docs/webdriver.md CHANGED
@@ -9,56 +9,11 @@ How does your client, manager, or tester, or any other non-technical person, kno
9
9
 
10
10
  End-to-End tests can cover standard but complex scenarios from a user's perspective. With e2e tests you can be confident that users, following all defined scenarios, won't get errors. We check **functionality of application and a user interface** (UI) as well.
11
11
 
12
- ## What is Selenium WebDriver
12
+ We use [webdriverio](https://webdriver.io) library to run tests over WebDriver. To proceed you need to have [CodeceptJS installed](/quickstart#using-selenium-webdriver) and `WebDriver` helper selected.
13
13
 
14
- The standard and proved way to run browser test automation over years is Selenium WebDriver. Over years this technology was standardized and works over all popular browsers and operating systems. There are cloud services like SauceLabs or BrowserStack which allow executing such browsers in the cloud. The superset of WebDriver protocol is also used to test [native and hybrid mobile applications](/mobile).
14
+ 🛩️ No Selenium Server, ChromeDriver, GeckoDriver, or driver services to install or start. Since WebdriverIO 9, driver management is fully automatic WebdriverIO downloads and starts the matching driver for you. Read more [here](https://webdriver.io/blog/2023/07/31/driver-management/).
15
15
 
16
- Let's clarify the terms:
17
-
18
- * Selenium - is a toolset for browser test automation
19
- * WebDriver - a standard protocol for communicating between test framework and browsers
20
- * JSON Wire - an older version of such protocol
21
-
22
- We use [webdriverio](https://webdriver.io) library to run tests over WebDriver.
23
-
24
- To proceed you need to have [CodeceptJS installed](/quickstart#using-selenium-webdriver) and `WebDriver` helper selected.
25
-
26
- Selenium WebDriver may be complicated from start, as it requires following tools to be installed and started.
27
-
28
- 1. Selenium Server - to execute and send commands to browser
29
- 2. ChromeDriver or GeckoDriver - to allow browsers to run in automated mode.
30
-
31
- > Those tools can be easily installed via NPM. Use [selenium-standalone](https://www.npmjs.com/package/selenium-standalone) to automatically install them.
32
-
33
- You can also use `@wdio/selenium-standalone-service` package, to install and start Selenium Server for your tests automatically.
34
-
35
- ```
36
- npm i @wdio/selenium-standalone-service --save-dev
37
- ```
38
-
39
- Enable it in config inside plugins section:
40
-
41
- ```js
42
- export const config = {
43
- // ...
44
- // inside condecept.conf.js
45
- plugins: {
46
- wdio: {
47
- enabled: true,
48
- services: ['selenium-standalone']
49
- }
50
- }
51
- }
52
- ```
53
-
54
- > ⚠ It is not recommended to use wdio plugin & selenium-standalone when running tests in parallel. Consider **switching to Selenoid** if you need parallel run or using cloud services.
55
-
56
- 🛩️ With the release of WebdriverIO version v8.14.0, and onwards, all driver management hassles are now a thing of the past 🙌. Read more [here](https://webdriver.io/blog/2023/07/31/driver-management/).
57
- One of the significant advantages of this update is that you can now get rid of any driver services you previously had to manage, such as
58
- `wdio-chromedriver-service`, `wdio-geckodriver-service`, `wdio-edgedriver-service`, `wdio-safaridriver-service`, and even `@wdio/selenium-standalone-service`.
59
-
60
- For those who require custom driver options, fear not; WebDriver Helper allows you to pass in driver options through custom WebDriver configuration.
61
- If you have a custom grid, use a cloud service, or prefer to run your own driver, there's no need to worry since WebDriver Helper will only start a driver when there are no other connection information settings like hostname or port specified.
16
+ WebDriver Helper only starts a driver automatically when no connection information (like `host` or `port`) is specified. If you have a custom grid, use a cloud service, or prefer to run your own driver, set those connection options and that endpoint is used instead.
62
17
 
63
18
  Example:
64
19
 
@@ -138,26 +93,6 @@ keepCookies: true,
138
93
 
139
94
  > ▶ More config options available on [WebDriver helper reference](/helpers/WebDriver#configuration)
140
95
 
141
- ### ChromeDriver without Selenium
142
-
143
- If you want to run tests using raw ChromeDriver (which also supports WebDriver protocol) avoiding Selenium Server, you should provide following configuration:
144
-
145
- ```js
146
- port: 9515,
147
- browser: 'chrome',
148
- path: '/',
149
- ```
150
-
151
- > If you face issues connecting to WebDriver, please check that corresponding server is running on a specified port. If host is other than `localhost` or port is other than `4444`, update the configuration.
152
-
153
- ### Selenium in Docker (Selenoid)
154
-
155
- Browsers can be executed in Docker containers. This is useful when testing on Continous Integration server.
156
- We recommend using [Selenoid](https://aerokube.com/selenoid/) to run browsers in container.
157
-
158
- CodeceptJS has [Selenoid plugin](/plugins#selenoid) which can automagically load browser container setup.
159
-
160
-
161
96
  ### Headless Mode
162
97
 
163
98
  The bundled `@codeceptjs/configure` toggles headless mode for WebDriver — for chrome/firefox it injects `--headless` into the matching capability args automatically:
@@ -203,9 +138,7 @@ desiredCapabilities: {
203
138
 
204
139
  ### Cloud Providers
205
140
 
206
- WebDriver protocol works over HTTP, so you need to have a Selenium Server to be running or any other service that will launch a browser for you. That's why you may need to specify `host`, `port`, `protocol`, and `path` parameters.
207
-
208
- By default, those parameters are set to connect to local Selenium Server, but they should be changed if you want to run tests via [Cloud Providers](/helpers/WebDriver#cloud-providers). You may also need `user` and `key` parameters to authenticate on cloud service.
141
+ By default, WebdriverIO starts a local driver automatically, so no connection parameters are needed. To run tests via [Cloud Providers](/helpers/WebDriver#cloud-providers) instead, specify `host`, `port`, `protocol`, and `path` parameters pointing to the service. You may also need `user` and `key` parameters to authenticate on the cloud service.
209
142
 
210
143
  There are also [browser and platform specific capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities). Services like SauceLabs, BrowserStack or browser vendors can provide their own specific capabilities for more tuning.
211
144
 
@@ -352,7 +285,7 @@ Scenario('create todo item', ({ I }) => {
352
285
 
353
286
  > [▶ Working example of CodeceptJS WebDriver tests](https://github.com/DavertMik/codeceptjs-webdriver-example) for TodoMVC application.
354
287
 
355
- WebDriver helper supports standard [CSS/XPath and text locators](/locators) as well as non-trivial [React locators](/react) and [Shadow DOM](/shadow).
288
+ WebDriver helper supports standard [CSS/XPath and text locators](/locators) as well as [Shadow DOM](/shadow) and [ARIA locators](/locators#aria-locators).
356
289
 
357
290
  ### Grabbers
358
291
 
@@ -481,7 +414,7 @@ If it's hard to define what to wait, it is recommended to use [retries](/basics/
481
414
 
482
415
  ## Configuring CI
483
416
 
484
- To develop tests it's fine to use local Selenium Server and window mode. Setting up WebDriver on remote CI (Continous Integration) server is different. If there is no desktop and no window mode on CI.
417
+ Locally, WebdriverIO starts the driver for you and tests run in window mode. On a remote CI (Continuous Integration) server there is usually no desktop, so window mode is not available.
485
418
 
486
419
  There are following options available:
487
420