# Editor setup

> For the complete documentation index, see [llms.txt](/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.
- 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, the first `lint` or `e2e` run after a package upgrade
creates the missing pieces automatically and prints one line about it.

:::caution[Upgrading from 0.27 or earlier]
The suite became its own npm package in 0.28.0, so the declarations moved
from `../node_modules/` to `./node_modules/`. `unotest/jsconfig.json` is
your file and nothing rewrites it — change that one `include` path by hand,
or let `npx @unotest/web init --force` rewrite it. Until you do,
autocomplete stays silently dead: the path simply resolves to nothing.
:::

Three files are involved:

| File | What it is |
| --- | --- |
| `unotest/jsconfig.json` | Points the IDE at the declaration files. Created once; yours after that. |
| `unotest/node_modules/@unotest/web/types/unotest-dsl.d.ts` | DSL 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.ts` | Your variable names, regenerated from `.env` / `.secrets` keys on every lint/run. Gitignored cache. |

Refresh on demand:

```sh
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` — one rule backed by the same
validator, severities from your `unotest/unotest.config.mjs`:

```sh
npm install --save-dev eslint @unotest/eslint-plugin
```

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

```js
// eslint.config.mjs
import unotest from "@unotest/eslint-plugin";

export default [...(await unotest.configs.recommended())];
```

## Remaining squiggles

Two cosmetic 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"** hint on in-scenario
  assignments (`ts = shell(...)`) — lower that inspection's severity under
  Settings → Editor → Inspections → JavaScript if it bothers you. VS Code
  does not semantic-check `.js` files without `checkJs` and stays quiet.
