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.
- package/README.md +39 -27
- package/bin/codecept.js +15 -2
- package/bin/codeceptq.js +49 -0
- package/bin/mcp-server.js +1187 -0
- package/docs/advanced.md +201 -0
- package/docs/agents.md +159 -0
- package/docs/ai.md +537 -0
- package/docs/aitrace.md +266 -0
- package/docs/api.md +332 -0
- package/docs/assertions.md +415 -0
- package/docs/auth.md +318 -0
- package/docs/basics.md +424 -0
- package/docs/bdd.md +539 -0
- package/docs/best.md +240 -0
- package/docs/bootstrap.md +132 -0
- package/docs/commands.md +352 -0
- package/docs/community-helpers.md +63 -0
- package/docs/configuration.md +230 -0
- package/docs/continuous-integration.md +497 -0
- package/docs/custom-helpers.md +297 -0
- package/docs/data.md +448 -0
- package/docs/debugging.md +332 -0
- package/docs/detox.md +235 -0
- package/docs/docker.md +136 -0
- package/docs/effects.md +179 -0
- package/docs/element-based-testing.md +295 -0
- package/docs/element-selection.md +125 -0
- package/docs/els.md +328 -0
- package/docs/examples.md +161 -0
- package/docs/heal.md +213 -0
- package/docs/helpers/ApiDataFactory.md +267 -0
- package/docs/helpers/Appium.md +1405 -0
- package/docs/helpers/Detox.md +665 -0
- package/docs/helpers/ExpectHelper.md +275 -0
- package/docs/helpers/FileSystem.md +152 -0
- package/docs/helpers/GraphQL.md +152 -0
- package/docs/helpers/GraphQLDataFactory.md +226 -0
- package/docs/helpers/JSONResponse.md +255 -0
- package/docs/helpers/Mochawesome.md +8 -0
- package/docs/helpers/MockRequest.md +377 -0
- package/docs/helpers/MockServer.md +212 -0
- package/docs/helpers/Playwright.md +2969 -0
- package/docs/helpers/Polly.md +44 -0
- package/docs/helpers/Protractor.md +1769 -0
- package/docs/helpers/Puppeteer-firefox.md +86 -0
- package/docs/helpers/Puppeteer.md +2690 -0
- package/docs/helpers/REST.md +289 -0
- package/docs/helpers/SoftExpectHelper.md +352 -0
- package/docs/helpers/WebDriver.md +2682 -0
- package/docs/hooks.md +339 -0
- package/docs/index.md +111 -0
- package/docs/installation.md +83 -0
- package/docs/internal-api.md +265 -0
- package/docs/internal-test-server.md +89 -0
- package/docs/locators.md +355 -0
- package/docs/mcp.md +485 -0
- package/docs/migration-4.md +556 -0
- package/docs/mobile.md +338 -0
- package/docs/pageobjects.md +399 -0
- package/docs/parallel.md +585 -0
- package/docs/playwright.md +714 -0
- package/docs/plugins.md +866 -0
- package/docs/puppeteer.md +314 -0
- package/docs/quickstart.md +120 -0
- package/docs/react.md +70 -0
- package/docs/reports.md +483 -0
- package/docs/retry.md +274 -0
- package/docs/secrets.md +150 -0
- package/docs/sessions.md +80 -0
- package/docs/shadow.md +68 -0
- package/docs/test-structure.md +275 -0
- package/docs/timeouts.md +183 -0
- package/docs/translation.md +247 -0
- package/docs/tutorial.md +271 -0
- package/docs/typescript.md +374 -0
- package/docs/web-element.md +251 -0
- package/docs/webdriver.md +708 -0
- package/docs/within.md +55 -0
- package/lib/ai.js +3 -2
- package/lib/aria.js +260 -0
- package/lib/assertions.js +18 -0
- package/lib/codecept.js +26 -23
- package/lib/command/check.js +2 -1
- package/lib/command/dryRun.js +24 -5
- package/lib/command/generate.js +2 -0
- package/lib/command/gherkin/snippets.js +5 -4
- package/lib/command/init.js +248 -269
- package/lib/command/list.js +150 -10
- package/lib/command/query.js +218 -0
- package/lib/command/run-multiple.js +2 -0
- package/lib/command/run-workers.js +2 -0
- package/lib/command/run.js +1 -1
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +77 -4
- package/lib/container.js +114 -17
- package/lib/effects.js +17 -0
- package/lib/element/WebElement.js +246 -2
- package/lib/els.js +12 -6
- package/lib/globals.js +32 -19
- package/lib/heal.js +4 -3
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +8 -8
- package/lib/helper/FileSystem.js +3 -2
- package/lib/helper/GraphQLDataFactory.js +2 -1
- package/lib/helper/Playwright.js +228 -162
- package/lib/helper/Puppeteer.js +208 -76
- package/lib/helper/WebDriver.js +173 -68
- package/lib/helper/errors/MultipleElementsFound.js +27 -110
- package/lib/helper/errors/NonFocusedType.js +8 -0
- package/lib/helper/extras/Download.js +45 -0
- package/lib/helper/extras/PlaywrightReactVueLocator.js +45 -36
- package/lib/helper/extras/elementSelection.js +58 -0
- package/lib/helper/extras/focusCheck.js +43 -0
- package/lib/helper/extras/richTextEditor.js +178 -0
- package/lib/helper/scripts/dropFile.js +11 -0
- package/lib/history.js +3 -2
- package/lib/html.js +103 -16
- package/lib/index.js +9 -1
- package/lib/listener/config.js +6 -4
- package/lib/listener/emptyRun.js +2 -1
- package/lib/listener/globalRetry.js +32 -6
- package/lib/listener/helpers.js +4 -1
- package/lib/listener/mocha.js +2 -1
- package/lib/listener/pageobjects.js +43 -0
- package/lib/listener/result.js +3 -2
- package/lib/locator.js +126 -3
- package/lib/mocha/cli.js +14 -2
- package/lib/mocha/factory.js +7 -2
- package/lib/mocha/inject.js +1 -1
- package/lib/mocha/scenarioConfig.js +2 -1
- package/lib/mocha/ui.js +5 -6
- package/lib/parser.js +2 -2
- package/lib/pause.js +38 -4
- package/lib/plugin/aiTrace.js +453 -0
- package/lib/plugin/analyze.js +1 -1
- package/lib/plugin/auth.js +3 -3
- package/lib/plugin/browser.js +77 -0
- package/lib/plugin/expose.js +159 -0
- package/lib/plugin/heal.js +44 -1
- package/lib/plugin/pageInfo.js +53 -49
- package/lib/plugin/pause.js +131 -0
- package/lib/plugin/pauseOnFail.js +10 -34
- package/lib/plugin/retryFailedStep.js +28 -19
- package/lib/plugin/screencast.js +287 -0
- package/lib/plugin/screenshot.js +563 -0
- package/lib/plugin/screenshotOnFail.js +8 -171
- package/lib/rerun.js +2 -1
- package/lib/result.js +2 -1
- package/lib/step/base.js +3 -2
- package/lib/step/config.js +15 -2
- package/lib/step/record.js +2 -2
- package/lib/store.js +72 -3
- package/lib/translation.js +2 -1
- package/lib/utils/mask_data.js +2 -1
- package/lib/utils/pluginParser.js +151 -0
- package/lib/utils/trace.js +297 -0
- package/lib/utils.js +77 -3
- package/lib/workers.js +52 -22
- package/package.json +19 -13
- package/typings/index.d.ts +19 -5
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -11
- package/docs/webapi/attachFile.mustache +0 -12
- package/docs/webapi/blur.mustache +0 -18
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -9
- package/docs/webapi/clearField.mustache +0 -9
- package/docs/webapi/click.mustache +0 -29
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -8
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -11
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/dontSeeTraffic.mustache +0 -13
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -16
- package/docs/webapi/flushNetworkTraffics.mustache +0 -5
- package/docs/webapi/focus.mustache +0 -13
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/grabWebElement.mustache +0 -9
- package/docs/webapi/grabWebElements.mustache +0 -9
- package/docs/webapi/moveCursorTo.mustache +0 -12
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -8
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -12
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/seeTraffic.mustache +0 -36
- package/docs/webapi/selectOption.mustache +0 -21
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/startRecordingTraffic.mustache +0 -8
- package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
- package/docs/webapi/stopRecordingTraffic.mustache +0 -5
- package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -21
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForCookie.mustache +0 -9
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForDisabled.mustache +0 -6
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
- package/lib/helper/AI.js +0 -214
- package/lib/listener/enhancedGlobalRetry.js +0 -110
- package/lib/plugin/enhancedRetryFailedStep.js +0 -99
- package/lib/plugin/htmlReporter.js +0 -3648
- package/lib/plugin/stepByStepReport.js +0 -427
- package/lib/plugin/subtitles.js +0 -89
- package/lib/retryCoordinator.js +0 -207
- package/typings/promiseBasedTypes.d.ts +0 -9469
- package/typings/types.d.ts +0 -11402
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /migration-4
|
|
3
|
+
title: Migrating from 3.x to 4.x
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrating from 3.x to 4.x
|
|
7
|
+
|
|
8
|
+
CodeceptJS 4.x is a major release. It moves the codebase from CommonJS to native ESM, drops several long-deprecated helpers and plugins, replaces legacy plugins with first-class APIs, and bumps most third-party dependencies.
|
|
9
|
+
|
|
10
|
+
This guide tells you exactly what to change in your project to upgrade.
|
|
11
|
+
|
|
12
|
+
## 1. Update Node and Package
|
|
13
|
+
|
|
14
|
+
CodeceptJS 4.x supports Node 16+, but Node 20 or newer is recommended.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install codeceptjs@4
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If you write tests in TypeScript, install `tsx`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install --save-dev tsx
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> 4.x replaces `ts-node/esm` with `tsx`. `ts-node/esm` is no longer recommended and emits a warning.
|
|
27
|
+
|
|
28
|
+
## 2. Switch Your Project to ESM
|
|
29
|
+
|
|
30
|
+
CodeceptJS 4.x ships as native ESM (`"type": "module"`). **Convert your project to ESM**.
|
|
31
|
+
Add to your `package.json`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"type": "module"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then convert your config, page objects, and custom helpers to ESM (sections below).
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Convert Custom Helpers
|
|
43
|
+
|
|
44
|
+
3.x:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
const Helper = require('@codeceptjs/helper')
|
|
48
|
+
|
|
49
|
+
class MyHelper extends Helper {
|
|
50
|
+
doSomething() { /* ... */ }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = MyHelper
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
4.x:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import Helper from '@codeceptjs/helper'
|
|
60
|
+
|
|
61
|
+
class MyHelper extends Helper {
|
|
62
|
+
doSomething() { /* ... */ }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default MyHelper
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Convert Page Objects
|
|
69
|
+
|
|
70
|
+
Replace `module.exports = { ... }` with `export default { ... }`.
|
|
71
|
+
|
|
72
|
+
Page objects gain new lifecycle hooks in 4.x: `_before`, `_after`, `_afterSuite`. They run automatically around suites that include the page object.
|
|
73
|
+
|
|
74
|
+
### Convert Programmatic Usage
|
|
75
|
+
|
|
76
|
+
3.x:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
const { codecept, container, event } = require('codeceptjs')
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
4.x:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
import codeceptjs, { container, event } from 'codeceptjs'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`Container.create()` and `Config.load()` are now **async**. Await them:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
const config = await Config.load('./codecept.conf.js')
|
|
92
|
+
await Container.create(config, opts)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 3. Remove Helpers That No Longer Exist
|
|
96
|
+
|
|
97
|
+
| Removed helper | What to do |
|
|
98
|
+
|----------------|------------|
|
|
99
|
+
| `Nightmare` | Switch to `Playwright`, `Puppeteer`, or `WebDriver`. |
|
|
100
|
+
| `Protractor` | Switch to `Playwright` or `WebDriver`. |
|
|
101
|
+
| `TestCafe` | Switch to `Playwright`. |
|
|
102
|
+
| `AI` | Use the top-level `ai:` config option and the new `aiTrace` plugin. |
|
|
103
|
+
| `SoftExpectHelper` | Use the `hopeThat` effect instead — see below. |
|
|
104
|
+
|
|
105
|
+
`Container.STANDARD_ACTING_HELPERS` no longer lists `TestCafe`.
|
|
106
|
+
|
|
107
|
+
### `SoftExpectHelper` → `hopeThat`
|
|
108
|
+
|
|
109
|
+
3.x shipped a `SoftExpectHelper` (`I.softAssert`, `I.softExpectEqual`, `I.flushSoftAssertions`, etc.) for soft assertions. It is gone in 4.x. Use the `hopeThat` effect — it works with **any** assertion that throws (built-in `I.see*`, your custom helper, `expect` from chai/jest, Node's `assert`).
|
|
110
|
+
|
|
111
|
+
3.x:
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
helpers: { SoftExpectHelper: {} }
|
|
115
|
+
|
|
116
|
+
// in scenario
|
|
117
|
+
I.softExpectEqual(user.name, 'jon')
|
|
118
|
+
I.softExpectContain(emails, 'jon@doe.com')
|
|
119
|
+
I.flushSoftAssertions()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
4.x:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
import { hopeThat } from 'codeceptjs/effects'
|
|
126
|
+
|
|
127
|
+
await hopeThat(() => assert.strictEqual(user.name, 'jon'))
|
|
128
|
+
await hopeThat(() => assert.ok(emails.includes('jon@doe.com')))
|
|
129
|
+
hopeThat.noErrors()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Each `hopeThat()` call records the failure as a note on the test and lets the scenario continue; `hopeThat.noErrors()` throws once at the end with every recorded failure if any happened. See [Effects: hopeThat](/effects#hopethat).
|
|
133
|
+
|
|
134
|
+
### Custom Assertion Libraries
|
|
135
|
+
|
|
136
|
+
No code changes are required for chai, expect, jest-style matchers, or Node's `assert` — just import them in your test files. With `noGlobals: true`, they work the same as before.
|
|
137
|
+
|
|
138
|
+
Heads up on chai: 3.x pinned `chai@4`; 4.x devDep is `chai@6`, which is **ESM-only** and drops some legacy APIs. If you import chai in your tests, switch to `import { expect } from 'chai'` and verify your matchers still resolve.
|
|
139
|
+
|
|
140
|
+
## 4. Replace or Remove Plugins
|
|
141
|
+
|
|
142
|
+
| Removed plugin | Replacement |
|
|
143
|
+
|----------------|-------------|
|
|
144
|
+
| `autoLogin` | **`auth` plugin** — see [Authorization](/auth). |
|
|
145
|
+
| `tryTo` | `import { tryTo } from 'codeceptjs/effects'` |
|
|
146
|
+
| `retryTo` | `import { retryTo } from 'codeceptjs/effects'` |
|
|
147
|
+
| `eachElement` | `import { eachElement } from 'codeceptjs/els'` |
|
|
148
|
+
| `commentStep` | `import step from 'codeceptjs/steps'` then `step.section('name')` / `step.endSection()` |
|
|
149
|
+
| `fakerTransform` | Import `@faker-js/faker` directly in tests. |
|
|
150
|
+
| `enhancedRetryFailedStep` | Merged into `retryFailedStep`. Rename in config. |
|
|
151
|
+
| `allure` | Use [@testomatio/reporter](https://testomat.io) or Mochawesome. |
|
|
152
|
+
| `htmlReporter` | Use an external reporter. |
|
|
153
|
+
| `wdio` | Configure WebdriverIO services directly in `helpers.WebDriver`. |
|
|
154
|
+
| `selenoid` | Run Selenoid externally. |
|
|
155
|
+
| `standardActingHelpers` | No longer needed; the list lives in core. |
|
|
156
|
+
|
|
157
|
+
### `autoLogin` → `auth`
|
|
158
|
+
|
|
159
|
+
3.x:
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
plugins: {
|
|
163
|
+
autoLogin: {
|
|
164
|
+
enabled: true,
|
|
165
|
+
saveToFile: true,
|
|
166
|
+
inject: 'login',
|
|
167
|
+
users: { admin: { login, check, fetch } },
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
4.x:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
plugins: {
|
|
176
|
+
auth: {
|
|
177
|
+
enabled: true,
|
|
178
|
+
users: {
|
|
179
|
+
admin: {
|
|
180
|
+
login: (I) => { /* ... */ },
|
|
181
|
+
check: (I) => { /* ... */ },
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Inject `login` and call `login('admin')` — same as before.
|
|
189
|
+
|
|
190
|
+
### Renamed Plugins
|
|
191
|
+
|
|
192
|
+
4.x unifies four plugins (`screenshot`, `pause`, `aiTrace`, `heal`) under a shared `on=` parameter. The old names live on as deprecated aliases that emit a warning and forward to the new plugin.
|
|
193
|
+
|
|
194
|
+
| Old plugin | New plugin | Notes |
|
|
195
|
+
| :------------------ | :------------------------------- | :------------------------------------------------- |
|
|
196
|
+
| `screenshotOnFail` | `screenshot` | Default `on='fail'`, same behavior |
|
|
197
|
+
| `pauseOnFail` | `pause` | Default `on='fail'`, same behavior |
|
|
198
|
+
| `stepByStepReport` | `screenshot` with `slides: true` | Use `on=step` to capture every step |
|
|
199
|
+
|
|
200
|
+
### New Plugins You Can Enable
|
|
201
|
+
|
|
202
|
+
- **`aiTrace`** — captures failure traces (DOM, console, network, screenshots) for AI debugging. See [AI Trace](/aitrace).
|
|
203
|
+
- **`pause`** — pauses execution on a chosen event or on failure. See [Debugging](/debugging).
|
|
204
|
+
- **`heal`** — self-heals failing steps with AI; narrow with `on=file|url`.
|
|
205
|
+
|
|
206
|
+
## 5. Update Removed and Changed APIs
|
|
207
|
+
|
|
208
|
+
### AI Config Now Uses Vercel AI SDK
|
|
209
|
+
|
|
210
|
+
3.x required a hand-written `request` function that called your provider's SDK directly. 4.x replaces this with [Vercel AI SDK](https://ai-sdk.dev) — pass a `model` and CodeceptJS handles the calls.
|
|
211
|
+
|
|
212
|
+
Install the SDK and the provider package you want:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
npm install ai @ai-sdk/openai
|
|
216
|
+
# or @ai-sdk/anthropic, @ai-sdk/google, @ai-sdk/mistral, @ai-sdk/groq, @ai-sdk/xai, @ai-sdk/azure, @ai-sdk/cohere
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
3.x:
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
ai: {
|
|
223
|
+
request: async messages => {
|
|
224
|
+
const OpenAI = require('openai')
|
|
225
|
+
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
|
|
226
|
+
const completion = await openai.chat.completions.create({
|
|
227
|
+
model: 'gpt-3.5-turbo',
|
|
228
|
+
messages,
|
|
229
|
+
})
|
|
230
|
+
return completion?.choices[0]?.message?.content
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
4.x:
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
import { openai } from '@ai-sdk/openai'
|
|
239
|
+
|
|
240
|
+
export default {
|
|
241
|
+
ai: {
|
|
242
|
+
model: openai('gpt-5'),
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The same shape works for every supported provider — swap `openai('gpt-5')` for `anthropic('claude-sonnet-4-6')`, `google('gemini-1.5-flash')`, etc. API keys still come from environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, ...).
|
|
248
|
+
|
|
249
|
+
The `request` function is no longer supported. Delete it from your config.
|
|
250
|
+
|
|
251
|
+
See [Testing with AI](/ai) for the full provider list and prompt customization.
|
|
252
|
+
|
|
253
|
+
### JSON Schema Validation: Joi → Zod
|
|
254
|
+
|
|
255
|
+
`I.seeResponseMatchesJsonSchema()` (from the `JSONResponse` helper) now validates with [Zod](https://zod.dev) instead of [Joi](https://joi.dev). Joi is gone from the dependency tree; Zod is bundled.
|
|
256
|
+
|
|
257
|
+
Rewrite your schemas:
|
|
258
|
+
|
|
259
|
+
3.x:
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
const Joi = require('joi')
|
|
263
|
+
|
|
264
|
+
I.seeResponseMatchesJsonSchema(Joi.object().keys({
|
|
265
|
+
name: Joi.string().required(),
|
|
266
|
+
email: Joi.string().email().required(),
|
|
267
|
+
age: Joi.number().integer().min(0),
|
|
268
|
+
}))
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
4.x:
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
import { z } from 'zod'
|
|
275
|
+
|
|
276
|
+
I.seeResponseMatchesJsonSchema(z.object({
|
|
277
|
+
name: z.string(),
|
|
278
|
+
email: z.string().email(),
|
|
279
|
+
age: z.number().int().min(0),
|
|
280
|
+
}))
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Or pass a callback that receives `z`:
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
I.seeResponseMatchesJsonSchema(z => z.object({
|
|
287
|
+
name: z.string(),
|
|
288
|
+
id: z.number(),
|
|
289
|
+
}))
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Common rewrites:
|
|
293
|
+
|
|
294
|
+
| Joi | Zod |
|
|
295
|
+
|-----|-----|
|
|
296
|
+
| `Joi.object().keys({...})` | `z.object({...})` |
|
|
297
|
+
| `Joi.string().required()` | `z.string()` (required by default) |
|
|
298
|
+
| `Joi.string().email()` | `z.string().email()` |
|
|
299
|
+
| `Joi.number().integer()` | `z.number().int()` |
|
|
300
|
+
| `Joi.array().items(...)` | `z.array(...)` |
|
|
301
|
+
| `Joi.string().optional()` | `z.string().optional()` |
|
|
302
|
+
| `Joi.date()` | `z.string().datetime()` or `z.date()` |
|
|
303
|
+
| `Joi.alternatives().try(a, b)` | `z.union([a, b])` |
|
|
304
|
+
|
|
305
|
+
Uninstall `joi` from your project if you only used it for CodeceptJS schemas:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
npm uninstall joi
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### `restart: 'browser'` removed (Playwright)
|
|
312
|
+
|
|
313
|
+
Use one of:
|
|
314
|
+
|
|
315
|
+
- `restart: 'session'` — reset session per test (default)
|
|
316
|
+
- `restart: 'context'` — new browser context per test
|
|
317
|
+
- `restart: 'keep'` — keep one browser across tests
|
|
318
|
+
|
|
319
|
+
### Custom Locator Strategy removed (Playwright)
|
|
320
|
+
|
|
321
|
+
The `customLocators` strategy registration in Playwright config is removed. Use the `customLocator` plugin or built-in ARIA locators (`{ role: 'button', name: 'Submit' }`).
|
|
322
|
+
|
|
323
|
+
### `I.retry()` is deprecated
|
|
324
|
+
|
|
325
|
+
Use the step options API:
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
import step from 'codeceptjs/steps'
|
|
329
|
+
|
|
330
|
+
I.click('Submit', step.retry(3))
|
|
331
|
+
I.fillField('Email', 'a@b.c', step.timeout(10))
|
|
332
|
+
I.click('Add', step.opts({ elementIndex: 2 }))
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### `within` Is Now an Effect
|
|
336
|
+
|
|
337
|
+
In 3.x, `within(...)` was a global statement available everywhere. In 4.x it's an effect alongside `tryTo`, `retryTo`, and `hopeThat`. Under `noGlobals: true` you must import it:
|
|
338
|
+
|
|
339
|
+
```js
|
|
340
|
+
import { within } from 'codeceptjs/effects'
|
|
341
|
+
|
|
342
|
+
await within('.signup-form', () => {
|
|
343
|
+
I.fillField('Email', 'a@b.c')
|
|
344
|
+
I.click('Submit')
|
|
345
|
+
})
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`within` returns a Promise — `await` it whenever you need its return value or want subsequent steps to wait for it. The same applies to `session`, which moved from global to a regular import (`import { session } from 'codeceptjs'`).
|
|
349
|
+
|
|
350
|
+
### Effects and Assertions Are Subpath Imports
|
|
351
|
+
|
|
352
|
+
```js
|
|
353
|
+
import { within, tryTo, retryTo, hopeThat } from 'codeceptjs/effects'
|
|
354
|
+
import { hopeThat } from 'codeceptjs/assertions'
|
|
355
|
+
import { eachElement, element, expectElement } from 'codeceptjs/els'
|
|
356
|
+
import step from 'codeceptjs/steps'
|
|
357
|
+
import store from 'codeceptjs/store'
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
`tryTo` and `hopeThat` now return `Promise<boolean>`. The 3.x generic `Promise<T | false>` signature is gone.
|
|
361
|
+
|
|
362
|
+
`hopeThat.noErrors()` is new — call it once at the end of a scenario to fail the test if any soft assertion failed.
|
|
363
|
+
|
|
364
|
+
### Globals Are Deprecated — `noGlobals: true` Is the New Default
|
|
365
|
+
|
|
366
|
+
Up to 3.x, almost everything was global: `Feature`, `Scenario`, `Before`, `pause`, `within`, `session`, `secret`, `Helper`, `actor`, `inject`, `share`, `locate`, `DataTable`, `Given`/`When`/`Then`, `codecept_dir`, `output_dir`.
|
|
367
|
+
|
|
368
|
+
In 4.x:
|
|
369
|
+
|
|
370
|
+
- `npx codeceptjs init` writes `noGlobals: true` into new configs.
|
|
371
|
+
- Projects without `noGlobals` set keep the old behavior but print a deprecation warning on every run:
|
|
372
|
+
|
|
373
|
+
> Global functions are deprecated. Use `import { Helper, pause, within, session } from "codeceptjs"` instead. Set `noGlobals: true` in config to disable globals.
|
|
374
|
+
|
|
375
|
+
To silence the warning, set `noGlobals: true`:
|
|
376
|
+
|
|
377
|
+
```js
|
|
378
|
+
// codecept.conf.js
|
|
379
|
+
export const config = {
|
|
380
|
+
noGlobals: true,
|
|
381
|
+
// ...
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
What changes when `noGlobals: true`:
|
|
386
|
+
|
|
387
|
+
| Symbol | With `noGlobals: true` |
|
|
388
|
+
|--------|------------------------|
|
|
389
|
+
| `Feature`, `Scenario`, `xFeature`, `xScenario`, `BeforeSuite`, `AfterSuite`, `Before`, `After`, `Background`, `BeforeAll`, `AfterAll` | **Still work in test files** — Mocha injects these into the test context. No import needed. |
|
|
390
|
+
| `pause()`, `inject()`, `share()` | **Still global.** Always available (with or without `noGlobals`) — they're the standard wiring/debugging entry points and run before any import would resolve. `pause` and `inject` are also exported from `codeceptjs` if you prefer explicit imports. |
|
|
391
|
+
| `codecept_dir`, `output_dir` | **Still global** (kept for backward compatibility with external plugins). |
|
|
392
|
+
| `within`, `session`, `secret`, `locate`, `dataTable`, `actor`, `codeceptjs` | Import from `codeceptjs`. |
|
|
393
|
+
| `Helper` (base class) | Import from `@codeceptjs/helper`. |
|
|
394
|
+
| `Given`, `When`, `Then`, `And`, `DefineParameterType` (BDD step definitions) | Available as globals **inside Gherkin step definition files** (CodeceptJS scope-injects them while loading the step files). No import needed. |
|
|
395
|
+
|
|
396
|
+
Imports for the new style:
|
|
397
|
+
|
|
398
|
+
```js
|
|
399
|
+
import { within, session, secret, locate, dataTable, actor } from 'codeceptjs'
|
|
400
|
+
import Helper from '@codeceptjs/helper'
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Test files written for 3.x keep working until you flip the flag.
|
|
404
|
+
|
|
405
|
+
### `wait*` Methods Resolve Relative URLs
|
|
406
|
+
|
|
407
|
+
`waitInUrl`, `waitUrlEquals`, and `waitCurrentPathEquals` now resolve a relative path against the helper's configured `url` before comparing. In 3.x a literal substring match against `window.location.href` would fail for relative paths.
|
|
408
|
+
|
|
409
|
+
```js
|
|
410
|
+
// helpers: { Playwright: { url: 'https://app.example.com' } }
|
|
411
|
+
|
|
412
|
+
I.waitUrlEquals('/dashboard') // matches https://app.example.com/dashboard
|
|
413
|
+
I.waitInUrl('/users') // matches any URL containing /users
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
`waitUrlEquals` error messages now include the actual URL the page was on when the wait timed out — easier to diagnose `/dashboard` vs `/dashboard?session=expired`.
|
|
417
|
+
|
|
418
|
+
## 6. Adopt New Behaviors
|
|
419
|
+
|
|
420
|
+
### Strict Mode
|
|
421
|
+
|
|
422
|
+
Playwright, Puppeteer, and WebDriver helpers support `strict: true`. Any locator that matches more than one element throws `MultipleElementsFound` instead of silently picking the first match.
|
|
423
|
+
|
|
424
|
+
```js
|
|
425
|
+
helpers: {
|
|
426
|
+
Playwright: { url: '...', strict: true },
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Per-step alternative: `I.click('a', step.opts({ exact: true }))`.
|
|
431
|
+
|
|
432
|
+
The error includes a `fetchDetails()` method that prints XPaths and HTML for every match.
|
|
433
|
+
|
|
434
|
+
### Element Index
|
|
435
|
+
|
|
436
|
+
Pick a specific match without writing a more specific locator:
|
|
437
|
+
|
|
438
|
+
```js
|
|
439
|
+
I.click('a', step.opts({ elementIndex: 2 }))
|
|
440
|
+
I.click('a', step.opts({ elementIndex: 'last' }))
|
|
441
|
+
I.fillField('input', 'x', step.opts({ elementIndex: -1 }))
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Unfocused Element Detection
|
|
445
|
+
|
|
446
|
+
`I.type()` and `I.pressKey()` throw `NonFocusedType` if no element has focus. Click or focus the field first.
|
|
447
|
+
|
|
448
|
+
### Context Parameter on Form Methods
|
|
449
|
+
|
|
450
|
+
`appendField`, `clearField`, `attachFile`, and `moveCursorTo` accept an optional second context argument, matching `fillField` and `click`.
|
|
451
|
+
|
|
452
|
+
### Other New Methods
|
|
453
|
+
|
|
454
|
+
- `I.seeCurrentPathEquals(path)` / `I.dontSeeCurrentPathEquals(path)` — compare the path ignoring query strings.
|
|
455
|
+
- `I.waitCurrentPathEquals(path, sec?)` — wait until the path matches.
|
|
456
|
+
- `I.seeFileDownloaded(name)`
|
|
457
|
+
- `I.clickXY(locator?, x, y)` — click at coordinates, either page-relative or element-relative.
|
|
458
|
+
- `I.grabAriaSnapshot(locator?)` — capture an accessibility-tree snapshot for the page or a region (Playwright).
|
|
459
|
+
- `I.grabWebElement(locator)` / `I.grabWebElements(locator)` — return helper-agnostic `WebElement` wrappers.
|
|
460
|
+
- `attachFile` — supports drag-and-drop dropzones.
|
|
461
|
+
- `fillField` — supports rich text editors (CKEditor, ProseMirror, etc.).
|
|
462
|
+
- BDD: `But` keyword is recognized.
|
|
463
|
+
|
|
464
|
+
### CLI Plugin Arguments
|
|
465
|
+
|
|
466
|
+
`-p` accepts colon-chained arguments, so plugins can be enabled and configured from the command line without editing config:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
npx codeceptjs run -p pause # pause on every failure
|
|
470
|
+
npx codeceptjs run -p pause:on=url:pattern=/checkout/* # pause when URL matches
|
|
471
|
+
npx codeceptjs run -p screenshot:on=step # screenshot every step
|
|
472
|
+
npx codeceptjs run -p browser:show # force visible browser
|
|
473
|
+
npx codeceptjs run -p browser:browser=firefox:windowSize=1024x768
|
|
474
|
+
npx codeceptjs run -p plugin1,plugin2:arg # multiple plugins
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Each argument after the plugin name is a `key=value` pair. `:` separates pairs. `;` is an inline alternative for visually grouping related pairs (e.g. `path=...;line=...`). Reserved keys: `on`, `path`, `line`, `pattern`.
|
|
478
|
+
|
|
479
|
+
The `browser` plugin is new in 4.x — it overrides the active browser helper (Playwright, Puppeteer, WebDriver, Appium) from the CLI, useful for ad-hoc local runs and CI matrices. See [Commands](/commands).
|
|
480
|
+
|
|
481
|
+
The old `-p all` magic keyword is gone (it conflicted with the colon syntax). Enable specific plugins explicitly: `-p pluginA,pluginB`.
|
|
482
|
+
|
|
483
|
+
### Workers: Events and Plugin Scope
|
|
484
|
+
|
|
485
|
+
Two notable changes for parallel runs:
|
|
486
|
+
|
|
487
|
+
- **Event dispatcher fires inside workers.** In 3.x, listeners attached to `event.dispatcher` only saw events from the main process. In 4.x, plugins and listeners observe per-test events inside each worker, so things like custom reporters and screenshot hooks work the same in single-process and worker modes ([#5464](https://github.com/codeceptjs/CodeceptJS/pull/5464)).
|
|
488
|
+
- **`runInParent` / `runInMain` plugin option.** Set to `false` on plugins that should only run inside worker children (default is `true`). Useful for plugins that aggregate per-worker state from the parent.
|
|
489
|
+
|
|
490
|
+
```js
|
|
491
|
+
plugins: {
|
|
492
|
+
myReporter: {
|
|
493
|
+
enabled: true,
|
|
494
|
+
runInParent: false, // only run in worker children
|
|
495
|
+
},
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### TypeScript Improvements
|
|
500
|
+
|
|
501
|
+
If you write tests in TypeScript, 4.x is significantly better:
|
|
502
|
+
|
|
503
|
+
- **`tsx` loader** instead of `ts-node/esm` — faster startup, better ESM compatibility. Install `tsx` (optional peer dep). `ts-node/esm` still works but emits a deprecation warning.
|
|
504
|
+
- **Error stack traces** point at `.ts` source lines, not transpiled output.
|
|
505
|
+
- **`__dirname` / `__filename`** are injected for TypeScript files that use them (ESM normally hides these globals).
|
|
506
|
+
- **Path aliases** from `tsconfig.json` (`paths`) are resolved at runtime — `import x from '@/utils'` works without extra runtime config.
|
|
507
|
+
- **`codecept.conf.ts`** supports top-level `await` via dynamic imports.
|
|
508
|
+
- **`steps_file.ts`** and TypeScript support objects load correctly across files.
|
|
509
|
+
|
|
510
|
+
## 7. Update Dependency Versions
|
|
511
|
+
|
|
512
|
+
If your project depends on these directly, check for breakage:
|
|
513
|
+
|
|
514
|
+
| Package | 3.x | 4.x |
|
|
515
|
+
|---------|-----|-----|
|
|
516
|
+
| `chai` | ^4 | ^6 (ESM-only) |
|
|
517
|
+
| `chai-as-promised` | 7 | 8 (ESM-only) |
|
|
518
|
+
| `@cucumber/gherkin` | 35 | 38 |
|
|
519
|
+
| `@cucumber/messages` | 29 | 32 |
|
|
520
|
+
| `chokidar` | 4 | 5 |
|
|
521
|
+
| `commander` | 11 | 14 |
|
|
522
|
+
| `@faker-js/faker` | 9 | 10 |
|
|
523
|
+
| `webdriverio` | 9.12 | 9.23 |
|
|
524
|
+
| `puppeteer` | 24.15 | 24.36 |
|
|
525
|
+
| `electron` | 38 | 40 |
|
|
526
|
+
| `typescript` | 5.8 | 5.9 |
|
|
527
|
+
| `testcafe` | 3.7.2 | **removed** |
|
|
528
|
+
| `inquirer-test` | 2.0.1 | **removed** |
|
|
529
|
+
| `joi` | 18 | **removed** — use `zod` |
|
|
530
|
+
| `zod` | — | added (^4) — schema validation in `JSONResponse` |
|
|
531
|
+
| `tsx` | — | added as optional peer |
|
|
532
|
+
| `@modelcontextprotocol/sdk` | — | added |
|
|
533
|
+
| `@testomatio/reporter` | — | added |
|
|
534
|
+
|
|
535
|
+
## 8. New Capabilities Worth Knowing
|
|
536
|
+
|
|
537
|
+
You don't need these to upgrade, but they unlock new workflows:
|
|
538
|
+
|
|
539
|
+
- **MCP server** — `bin/mcp-server.js` (also installed as `codeceptjs-mcp`) exposes CodeceptJS to AI agents through Model Context Protocol. See [MCP](/mcp).
|
|
540
|
+
- **WebElement wrapper** — `grabWebElements()` returns helper-agnostic `WebElement` instances with a unified API.
|
|
541
|
+
- **ARIA-first locators** — `{ role: 'button', name: 'Submit' }` works in Playwright, Puppeteer, and WebDriver. The `role` type is now first-class in `Locator`. See [Locators](/locators#aria-locators).
|
|
542
|
+
- **Locator DSL** — `locate(...)` gains `.withClass()`, `.not()` negation, raw-predicate helpers, and a `role` selector type.
|
|
543
|
+
- **Workers** — the `event` dispatcher fires inside worker processes, so listeners and plugins observe parallel runs the same way they observe single-process runs.
|
|
544
|
+
- **Path normalization** — file-path handling is normalized cross-platform; tests authored on Windows run unchanged on Linux/CI.
|
|
545
|
+
- **Test metadata** — the `Scenario` callback receives a `test` object with `test.tags`, `test.artifacts`, `test.meta`, and `test.notes` for custom reporting.
|
|
546
|
+
- **Security** — the `emptyFolder` utility (used by output cleanup) no longer shells out via `rm -rf`, closing a command-injection vector ([#5191](https://github.com/codeceptjs/CodeceptJS/pull/5191)).
|
|
547
|
+
|
|
548
|
+
## 9. Verify the Upgrade
|
|
549
|
+
|
|
550
|
+
1. `npx codeceptjs check` — surfaces config issues.
|
|
551
|
+
2. `npx codeceptjs run --debug` on a small smoke suite. Confirm the run starts and steps execute.
|
|
552
|
+
3. `npx codeceptjs run --workers 2` — confirm parallel execution.
|
|
553
|
+
4. TypeScript users: run with `tsx` installed and confirm error stack traces point at `.ts` files.
|
|
554
|
+
5. If you removed `autoLogin`: confirm sessions restore under the `auth` plugin.
|
|
555
|
+
6. If you used `tryTo` / `retryTo` / `eachElement` plugins: grep your tests for the old globals and switch to subpath imports.
|
|
556
|
+
7. CI: bump the Node version to 20+ if you were on 18 or below.
|