Skip to content

docs: 4.x migration guide and ESM-only code samples#5538

Open
DavertMik wants to merge 13 commits into4.xfrom
docs/4.x-migration-guide-and-esm-cleanup
Open

docs: 4.x migration guide and ESM-only code samples#5538
DavertMik wants to merge 13 commits into4.xfrom
docs/4.x-migration-guide-and-esm-cleanup

Conversation

@DavertMik
Copy link
Copy Markdown
Contributor

Summary

  • Adds docs/migration-4.md — a complete 3.x → 4.x migration guide covering the ESM switch, removed helpers/plugins, AI-config replacement (Vercel AI SDK), Joi → Zod, restart: 'browser' removal, within becoming an effect, noGlobals: true as the new default, wait* URL resolution, strict mode, CLI plugin args, workers events, and TypeScript loader changes.
  • Documents hopeThat in docs/effects.md as the soft-assertion replacement for the removed SoftExpectHelper. Clarifies that it works with any assertion library (built-in I.see*, assert, chai, jest matchers, etc.).
  • Converts ~70 CommonJS code samples to ESM across 19 docs: require()import, module.exportsexport default, exports.configexport const config. Fixed one dynamic-import-at-top-level regression in pageobjects.md.
  • Other small touch-ups: claude-sonnet-4-6 / gpt-5 in AI examples, ESM-friendly import 'dotenv/config' in best.md, import electron from 'electron' in playwright.md, prose around require('codeceptjs') updated in hooks.md / internal-api.md.

Files

  • New: docs/migration-4.md
  • Updated docs (CJS → ESM + various): ai, api, basics, bdd, best, commands, configuration, custom-helpers, data, effects, hooks, index, installation, internal-api, pageobjects, parallel, playwright, plugins, puppeteer, reports, secrets, translation, tutorial, webdriver

docs/migration-4.md intentionally keeps require() / module.exports in its 3.x: before-snippets so users can see what they had. docs/api.md's Joi-migration note and the For CommonJS Projects (CodeceptJS 3.x) block in docs/configuration.md are left as CJS for the same reason.

Test plan

  • Render the docs site locally (npm run docs or whichever pipeline) and confirm the new migration guide appears in the sidebar.
  • Spot-check a converted sample (e.g. docs/custom-helpers.md, docs/internal-api.md) by copying it into a fresh npm init-style ESM project and confirming the import resolves.
  • Verify docs/effects.md renders the hopeThat example correctly.
  • Confirm intra-doc links (/effects#hopethat, /locators#aria-locators, /auth, /aitrace, /mcp, etc.) resolve.

🤖 Generated with Claude Code

DavertMik and others added 13 commits April 26, 2026 22:27
- Add docs/migration-4.md covering ESM switch, removed helpers
  (Nightmare/Protractor/TestCafe/AI/SoftExpect), removed plugins
  (autoLogin/tryTo/retryTo/eachElement/allure/htmlReporter/wdio/etc.),
  Vercel AI SDK, Joi → Zod, restart=browser removal, Custom Locator
  Strategy removal, within → effect, noGlobals: true default,
  wait* relative URL resolution, strict mode, elementIndex,
  CLI plugin args, workers events, TypeScript loader changes.
- Document hopeThat (soft assertions) in docs/effects.md as the
  replacement for SoftExpectHelper; clarify it works with any
  assertion library.
- Convert ~70 CJS code samples across 19 docs to ESM
  (require/module.exports/exports.config → import/export default).
- Fix dynamic require in pageobjects.md → static import.
- Update Anthropic example in ai.md to claude-sonnet-4-6 and
  OpenAI example to gpt-5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- data.md: faker is a named export; restore `import { faker }`
  and update the install hint from the legacy `faker` package
  to `@faker-js/faker`.
- internal-api.md: lead with the named-import form and demote
  the `codeceptjs` global to a footnote (it only exists when
  `noGlobals: false`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* `@codeceptjs/configure` and `@codeceptjs/expect-helper` both do
  `require('codeceptjs')` from inside their own packages. End users
  installing codeceptjs into a project's node_modules resolve fine —
  but in this repo (where the project IS codeceptjs) Node has nothing
  at node_modules/codeceptjs to resolve to, so those imports throw and
  helper/plugin loading fails on every CI run. Add `npm link && npm
  link codeceptjs` after install in playwright/puppeteer/webdriver/
  plugin/dtslint/test workflows. Documented in CLAUDE.md.

* `lib/plugin/browser.js`: route through `setBrowserConfig` from
  `@codeceptjs/configure` instead of duplicating the helper-mutation
  logic inline. The configure dep is the right primitive — removing
  the duplicate, single source of truth.

* `typings/index.d.ts`: drop `/// <reference types="joi" />`. joi is
  not used in any public type, the directive was leftover from a prior
  incarnation, and it broke `dtslint` (which looks for `@types/joi`,
  doesn't exist) and the def-runner test (failed-resolution alignment
  produced an undefined `resolutionDiagnostics` access in newer TS).

* Docs: `docs/configuration.md` setCommonPlugins table aligned with
  4.x plugin set (no eachElement, pauseOn instead of pauseOnFail);
  `docs/plugins.md` regen with aiTrace section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* `@codeceptjs/configure` is now imported dynamically. If it's not
  installed (e.g. user pinned a stripped-down dep set), the plugin
  prints a one-line hint and skips the override instead of crashing.
* Arg parsing rewritten as small composable functions: `parseArgs` →
  `parseArg` → `parseValue`. Uses `String.split('=')` instead of
  manual `indexOf`/`slice`. The hot loop is now a `reduce`.
* Drop number coercion — values stay as strings; helpers (and
  setBrowserConfig's regex parsers) coerce as needed. `true`/`false`
  still become real booleans for boolean-typed helper options.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both `@codeceptjs/configure@^4.0.0-beta.2` and
`@codeceptjs/expect-helper@^4.0.0-beta.3` are now native ESM with
codeceptjs declared as an optional peer dep, matching CodeceptJS 4.x.
Caret ranges pick up future 4.x betas, RCs, and the eventual stable
release without further package.json edits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reframe semantic locators (`I.click('Save', '.header')`) as the
recommended default for stable scenarios, not a prototyping
shortcut. Combined with a context, they read like prose, survive
ARIA/CSS refactors, and disambiguate duplicate labels — so they're
more precise than ARIA or CSS used alone.

- Intro: lead with the "semantic + context" recipe.
- Locator-types table: split semantic into "with context" (default)
  and "no context" (unique label / prototyping); document the
  combined pattern as a first-class type.
- Semantic section: front-load the "pair with a context" guidance
  and drop the "switch to strict locators once stable" line.
- Context section: explain why scoping every action is the
  default, not the special case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The workaround was needed only while @codeceptjs/configure and
@codeceptjs/expect-helper did `require('codeceptjs')` at load time.
After the configure import in lib/plugin/browser.js was made
optional and @codeceptjs/expect-helper was pinned to ^4.0.0-beta.3,
nothing in the repo's runtime depends on a self-resolving
node_modules/codeceptjs entry — `npm link` is dead code.

- Remove the `- run: npm link && npm link codeceptjs` step (and
  surrounding comment block) from dtslint, playwright, plugin,
  puppeteer, webdriver workflows, and both jobs in test.yml.
- Drop the matching "Local Development Setup" section from CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kage

@codeceptjs/configure and @codeceptjs/expect-helper both do top-level
`import 'codeceptjs'`. Both passing through the test config (e.g. the
`Expect: { require: '@codeceptjs/expect-helper' }` line in the
acceptance configs) means CodeceptJS itself can't start in CI without
node_modules/codeceptjs resolving — and the runtime deps load before
any helper or test does, so disabling `codecept check` alone wasn't
enough.

Replace the previous `npm link && npm link codeceptjs` workaround with
a single `ln -sfn .. node_modules/codeceptjs`. One symlink, no global
npm state.

Workflows updated: test, dtslint, playwright, puppeteer, webdriver, plugin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codeceptjs/configure and @codeceptjs/expect-helper currently do top-level
\`import 'codeceptjs'\`, which can't resolve inside this repo's CI (the
project IS the codeceptjs package, so npm doesn't drop a node_modules
entry to resolve to). The CI symlink works around it; the proper fix is
to give those packages an in-process handle so they don't need to look
up codeceptjs through Node's bare-specifier resolution.

This change is the codeceptjs-side prep:

- lib/host.js — sets globalThis.codeceptjs = { config, container, event,
  output, recorder, Helper } as a side-effect on import. Idempotent;
  matches the global @codeceptjs/helper already consults
  (\`global.codeceptjs || require('codeceptjs')\`).
- lib/codecept.js + lib/plugin/browser.js — eager import of host.js so
  the registry is populated before the user's codecept.conf.js loads
  any companion package.

Once @codeceptjs/configure and @codeceptjs/expect-helper ship versions
that read from globalThis.codeceptjs (instead of \`import 'codeceptjs'\`),
the CI symlink can be removed. Drop-in replacements for both packages
are in scripts/upstream-patches/ — apply them upstream and bump versions
in package.json.

End-user projects are unaffected: globalThis.codeceptjs is set in normal
runs too, so the new code path is the same code path everyone takes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…This

@codeceptjs/configure@4.0.0-beta.4 and @codeceptjs/expect-helper@4.0.0-beta.5
no longer do top-level `import 'codeceptjs'` — they read from the
globalThis.codeceptjs registry the runner sets up in lib/host.js. The
self-symlink that fed them a resolvable codeceptjs package in CI is no
longer needed.

- Bump @codeceptjs/configure to ^4.0.0-beta.4
- Bump @codeceptjs/expect-helper to ^4.0.0-beta.5
- Remove the `ln -sfn .. node_modules/codeceptjs` step from dtslint,
  playwright, plugin, puppeteer, webdriver, and test workflows
- Delete scripts/upstream-patches/ — the patches it documented are now
  released in the companion packages

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant