This documentation is available as Markdown. For the complete index, see llms.txt. Skip to content

Editor setup

For the complete documentation index, see llms.txt

Scenarios are plain .js with an implicit global vocabulary (click, getByRole, step, your LOGIN / PASSWORD variables). An untouched editor treats them as broken JavaScript: red squiggles, no completion. The fix ships with the package and wires itself.

What you get

  • Autocomplete and signature help for every DSL function.
  • Completion offers exactly what a scenario has: Math.round, s.trim(), new Map() complete; Date, setTimeout, document, which lint refuses, do not.
  • Hover docs — the same reference text as this site.
  • Locator chains resolve: getByRole('button').filter(...).first().
  • UPPER_SNAKE variables from unotest/.env / .secrets stop being “undefined” (names only — values never leave those files).
  • Helpers (flow_* in unotest/e2e/_helpers/) resolve from source, with go-to-definition into the real file.

How it wires

npx @unotest/web init sets everything up in a new project. In an existing project, or a checkout without unotest/jsconfig.json, cd unotest && npx @unotest/web types writes the missing pieces. Runs and lint never write the jsconfig themselves: a test run adds no files to your tree, so in a fresh checkout types is the step to take.

Four files are involved:

FileWhat it is
unotest/jsconfig.jsonPoints the IDE at the declaration files. Sets noLib: the scenario library below is the editor’s whole standard library. Written by init, or by npx @unotest/web types when missing; yours after that.
unotest/node_modules/@unotest/web/types/unotest-lib.d.tsThe scenario library — Math, JSON, Object, Map, Set, string, number and array methods — cut from TypeScript’s own declarations to what a scenario has. keys(), values() and entries() of a Map or a Set read as arrays, as they run.
unotest/node_modules/@unotest/web/types/unotest-dsl.d.tsDSL declarations, shipped with the package — always matches the installed version. The suite is its own npm package, so they live under unotest/, not at the project root.
.unotest/types/env.d.tsYour variable names, regenerated from .env / .secrets keys on every lint/run. Gitignored cache.

Refresh on demand:

Terminal window
cd unotest && npx @unotest/web types

Deliberately NOT type checking

checkJs stays off. The DSL has its own validator with rules an editor cannot know (npx @unotest/web lint, also run before every scenario run) — a second, diverging diagnostics engine would only disagree with it. The editor gains navigation and documentation; correctness stays with the linter.

ESLint (optional)

If your project runs ESLint, @unotest/eslint-plugin reports the exact same diagnostics as unotest-web lint — its rules are backed by the same validator, severities from your unotest/unotest.config.mjs:

Terminal window
npm install --save-dev eslint @unotest/eslint-plugin

That one goes wherever your ESLint already lives — it lints your repository, not the suite package.

eslint.config.mjs
import unotest from "@unotest/eslint-plugin";
export default [...(await unotest.configs.recommended())];

recommended() wires two rules: @unotest/dsl reports the validator’s errors, @unotest/dsl-warning its warnings. ESLint gives a severity to a rule, not to a report, hence two rules over one check — the file is validated once for both. Which diagnostic is an error and which a warning comes from linter.rules in unotest/unotest.config.mjs, as for the CLI.

To make warnings fail the build, raise the whole warning rule:

eslint.config.mjs
import unotest from "@unotest/eslint-plugin";
export default [
...(await unotest.configs.recommended()),
{ files: ["unotest/e2e/**/*.js"], rules: { "@unotest/dsl-warning": "error" } },
];

Wiring the plugin by hand instead of recommended(), name both rules, or the warnings are not reported at all:

rules: {
"@unotest/dsl": "error",
"@unotest/dsl-warning": "warn",
}

The plugin’s README has the rest: what recommended() sets besides the rules (files, globals, no-undef).

Remaining squiggles

Two sources that typings cannot fix:

  • Spellchecker on domain words inside strings ('listitem', '/dashboard/checkout') — add them to your project dictionary.
  • WebStorm’s “Implicitly declared global variable” on an assignment without a declaration (ts = shell(...)) — declare it, const ts = shell(...). lint reports it too, with the declaration to write.