BDD JavaScript / TypeScript API
Cucumber-js-shaped surface, native-backed. Step bodies in JS / TS run
through the same Rust TestRunner that drives Rust #[ferritest]
tests — same workers, retries, reporters, fixtures.
Step registration
Pattern can be a Cucumber expression (default) or a RegExp:
Per-step timeout
Per-step options object goes between pattern and handler:
Hooks
Tag expressions support the full boolean grammar: @smoke and not @wip,
(@fast or @critical) and not @wip.
After* hooks run even when earlier hooks or steps failed (cleanup
guarantee). Hook order: Before hooks run in ascending order, After
hooks run in descending — cleanup mirrors setup.
The World
this inside any step or hook is the World — a per-scenario object
carrying fixtures and helpers:
Custom World
setWorldConstructor is per-VM (last call wins). Fixtures (page,
context, browser, request) are augmented onto the instance after
construction.
Step return values
Parameter types
Built-in Cucumber expression parameters:
Custom parameter type
Or shorthand: defineParameterType("color", "red|green|blue").
Type inference: Given('I have {int} {string}', (count, item) => {})
gives count: number, item: string in TS-aware editors.
Data tables
A step that ends with a table receives a DataTable argument by name:
DataTable methods
Doc strings
A """ block after a step is passed as a string argument:
Media-type hints ("""json, """yaml) are parsed and surfaced in the
report but do not change the value type (always string).
Defaults and globals
setParallelCanAssign is accepted for cucumber-js compat but is inert:
ferridriver parallelises at the test-runner worker level (one VM per
worker), not cucumber-js's per-pickle scheduler.
Built-in Rust step library
There is a shipped Rust step library (ferridriver-bdd/src/steps/)
of 144 steps — see Built-in steps. Those are registered
via #[given] / #[when] macros on the Rust side and merge into the
same registry as your JS / TS steps. A .feature file can mix steps
from both languages freely.
Imports
No bare specifier resolution from inside extensions / steps outside
what rolldown can resolve at bundle time. There is no runtime
require() and no Node module loader.
See also
- BDD overview — Rust + JS, hybrid suites
- BDD running — CLI, reporters, profiles
- Extensions — sharing a file between MCP + BDD
- Sandbox —
process,fetch,fs, what is absent