Commit fb1a602
docs: 4.x migration guide and ESM-only code samples (#5538)
* update docs
* updated docs, added browser plugin
* docs: 4.x migration guide and ESM-only code samples
- 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>
* docs: fix faker import + clarify codeceptjs internal-api intro
- 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>
* fix(ci): npm link codeceptjs in CI; drop dead joi types reference
* `@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>
* refactor(browser plugin): optional configure import + cleaner arg parser
* `@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>
* deps: pin @codeceptjs/expect-helper to ^4.0.0-beta.3
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>
* docs(locators): elevate semantic+context as the default pattern
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>
* Revert: drop npm link CI workaround
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>
* ci: self-link node_modules/codeceptjs to fix deps that import the package
@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>
* ci(host): register globalThis.codeceptjs so deps don't need bare import
@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>
* ci: drop self-symlink workaround now that companion betas read globalThis
@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>
* refactor(config): track per-hook ran flag, replace runHooksFrom indices
The old API exposed two coupled primitives — hooksCount() / runHooksFrom(N) —
that pushed positional bookkeeping onto the caller. Container.create snapshotted
the count before plugin boot and replayed everything past that index after.
Brittle: any future change that reorders or removes hooks would silently
re-run the wrong ones.
Replace with a per-hook { fn, ran } record and a single runPendingHooks(cfg)
that fires anything not yet applied to the current config. Caller no longer
deals with indices:
if (Config.runPendingHooks(config)) {
// re-feed helper config…
}
Behavior is unchanged for the existing flow:
- create() rebuilds config and re-runs every hook (marks all ran).
- A hook registered after create() is pending until runPendingHooks() picks it up.
- Hooks registered while runPendingHooks() is running are picked up in the
same pass (loop re-checks length each iteration).
Internal API only — no other call sites in the repo or test suite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: drop lib/host.js, install registry inline in the runner
lib/host.js was a separate module that did one thing: assign
globalThis.codeceptjs = { config, container, event, output, recorder, Helper }.
Imported as a side effect from lib/codecept.js (the runner) and
lib/plugin/browser.js (so the browser-plugin unit test would also get
the registry, since it imports the plugin directly without going through
the runner).
The indirection wasn't earning its keep — and it read like we were
quietly re-introducing the user-facing globals we just deprecated.
- Inline the assignment at the top of lib/codecept.js. The runner is the
one place that should own this; everything that goes through the CLI
hits this module first.
- Drop the import from lib/plugin/browser.js. Plugins shouldn't be
responsible for installing framework registries.
- The browser-plugin unit test bypasses the runner, so it now installs
globalThis.codeceptjs in its setup — same pattern we use in the
@codeceptjs/configure test suite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: install framework registry once via mocha require, drop per-test setup
Same idea as codeceptjs's own \`config.require\` option: list a setup
script in mocha's config and let it run once before any test. The
unit-test world is the only place that needs to fake \`globalThis.codeceptjs\`
(unit tests bypass the runner that normally installs it), so park the
five lines there and stop sprinkling them into individual test files.
- test/support/setup.mjs — was just chai.should(); now also installs
the framework registry (Config, container, event, output, recorder,
Helper) on globalThis.codeceptjs the same way lib/codecept.js does
for the live runner.
- .mocharc.mjs → .mocharc.cjs — mocha's config auto-discovery is
inconsistent with .mocharc.mjs across CLI shapes (recursive runs picked
it up, single-file runs didn't). The CJS form auto-loads reliably
whether you point mocha at a directory or a single file. The exposed
config is unchanged: \`require\` + \`extension\`.
- test/unit/plugin/browser_test.js — drop the per-test inline
\`globalThis.codeceptjs = ...\`; setup.mjs now covers it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(config): drop unparseable @type annotation that broke npm run def
The Array-of-object-literal form
/** @type {Array<{ fn: (cfg: object) => void, ran: boolean }>} */
is invalid JSDoc syntax for the version of jsdoc this repo's `npm run def`
runs through (it doesn't parse object-literal type expressions inside
generic params). Result: jsdoc bailed, def generation failed, both
"test (20.x)" and the runner test that calls `npm run def` went red.
The annotation was decoration only — the hook list is internal state.
Replace with a plain comment, ship the doc-regen of plugins.md the
def task produced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(config): for-of hook loops, swallow per-hook errors via applyHook
Three changes asked for on the previous hook refactor:
- Replace the for-i loops in Config.create and Config.runPendingHooks
with for-of. Both rely on Array iterator semantics — newly pushed
hooks (e.g. a hook that registers another hook) are still picked up
in the same pass because the iterator re-checks length on each step.
- Centralize hook execution in a single applyHook() helper that wraps
the call in try/finally. A broken hook now logs through
globalThis.codeceptjs.output (or stderr when the runner isn't up
yet) and is marked ran=true regardless, so a poison entry can't
block the rest of the pass or get retried by runPendingHooks.
Callers don't touch hook.ran themselves.
- Tighten the comment over the globalThis.codeceptjs block in
lib/codecept.js. The previous wording implied end-user projects
didn't need it — they do, because @codeceptjs/configure is
typically imported at the top of a user's codecept.conf.js and
registers hooks via the in-process registry before Config.load
even returns. setup.mjs handles the same contract for mocha tests
via .mocharc require.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: install globalThis.codeceptjs from each suite's own bootstrap
Drop the side-effect block from lib/codecept.js. The framework now lets
each test suite own the registry install via its own bootstrap script:
- mocha-driven tests (unit, runner, rest): .mocharc → test/support/setup.mjs
already runs before every file. setup.mjs calls installCodeceptjs().
- codeceptjs-runner-driven acceptance suites: each codecept.*.js config
references installCodeceptjs as its `bootstrap` field. The runner
invokes bootstrap after container.create and before tests start, so
globalThis.codeceptjs is in place by the time @codeceptjs/expect-helper's
Proxy is read at I.expect*() call time.
The shared installer lives in test/support/install-codeceptjs.js — five
lines, one job, idempotent. WebDriver's existing 5s selenium-wait
bootstrap calls installCodeceptjs() then waits, in that order.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: DavertMik <davert@testomat.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 6ca126f commit fb1a602
48 files changed
Lines changed: 1705 additions & 926 deletions
File tree
- docs
- helpers
- webapi
- lib
- helper
- plugin
- test
- acceptance
- support
- unit/plugin
- typings
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
| 31 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | 25 | | |
27 | | - | |
28 | 26 | | |
29 | 27 | | |
30 | 28 | | |
| |||
60 | 58 | | |
61 | 59 | | |
62 | 60 | | |
63 | | - | |
| 61 | + | |
64 | 62 | | |
65 | 63 | | |
66 | 64 | | |
| |||
94 | 92 | | |
95 | 93 | | |
96 | 94 | | |
97 | | - | |
| 95 | + | |
98 | 96 | | |
99 | 97 | | |
100 | 98 | | |
| |||
121 | 119 | | |
122 | 120 | | |
123 | 121 | | |
124 | | - | |
125 | | - | |
| 122 | + | |
| 123 | + | |
126 | 124 | | |
127 | 125 | | |
128 | 126 | | |
| |||
232 | 230 | | |
233 | 231 | | |
234 | 232 | | |
| 233 | + | |
235 | 234 | | |
236 | | - | |
237 | | - | |
238 | | - | |
| 235 | + | |
239 | 236 | | |
240 | 237 | | |
241 | 238 | | |
| |||
385 | 382 | | |
386 | 383 | | |
387 | 384 | | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
399 | | - | |
400 | | - | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
412 | | - | |
413 | | - | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
419 | | - | |
420 | | - | |
421 | | - | |
422 | | - | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
454 | | - | |
455 | | - | |
456 | | - | |
457 | | - | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
497 | | - | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
502 | | - | |
503 | | - | |
504 | | - | |
505 | | - | |
506 | | - | |
507 | 385 | | |
508 | 386 | | |
509 | 387 | | |
| |||
612 | 490 | | |
613 | 491 | | |
614 | 492 | | |
615 | | - | |
616 | | - | |
| 493 | + | |
| 494 | + | |
617 | 495 | | |
618 | 496 | | |
619 | 497 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
| 122 | + | |
123 | 123 | | |
124 | | - | |
125 | | - | |
| 124 | + | |
| 125 | + | |
126 | 126 | | |
127 | | - | |
| 127 | + | |
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| |||
0 commit comments