e2e 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/.build.json +1 -1
- package/dist/agent/act.js +7 -4
- package/dist/agent/action-dispatcher.js +4 -5
- package/dist/agent/actions.d.ts +32 -23
- package/dist/agent/actions.js +38 -24
- package/dist/agent/ai-sdk.js +5 -4
- package/dist/agent/error.js +3 -3
- package/dist/agent/invocation.js +3 -4
- package/dist/agent/model/sdk.js +2 -0
- package/dist/agent/model/tool-choice.d.ts +9 -0
- package/dist/agent/model/tool-choice.js +14 -0
- package/dist/agent/observation-feed.d.ts +5 -6
- package/dist/agent/observation-feed.js +8 -11
- package/dist/agent/observation.d.ts +40 -11
- package/dist/agent/observation.js +109 -59
- package/dist/agent/phases.d.ts +7 -1
- package/dist/agent/phases.js +12 -3
- package/dist/agent/point-tap.d.ts +8 -8
- package/dist/agent/point-tap.js +1 -1
- package/dist/agent/prompts.js +3 -0
- package/dist/agent/replay.d.ts +19 -8
- package/dist/agent/replay.js +29 -29
- package/dist/agent/scroll-target.d.ts +2 -3
- package/dist/agent/step-cache.d.ts +43 -15
- package/dist/agent/step-cache.js +156 -67
- package/dist/agent/tool-loop.js +94 -5
- package/dist/cache/anchors.d.ts +72 -23
- package/dist/cache/anchors.js +233 -60
- package/dist/cache/context.d.ts +25 -14
- package/dist/cache/context.js +50 -8
- package/dist/cache/decide.d.ts +2 -2
- package/dist/cache/decide.js +4 -6
- package/dist/cache/identity.d.ts +18 -4
- package/dist/cache/identity.js +9 -4
- package/dist/cache/recorder.d.ts +15 -1
- package/dist/cache/recorder.js +36 -23
- package/dist/cache/rekeyed.d.ts +46 -0
- package/dist/cache/rekeyed.js +89 -0
- package/dist/cache/relocate.d.ts +14 -14
- package/dist/cache/relocate.js +33 -25
- package/dist/cache/route.d.ts +32 -33
- package/dist/cache/route.js +94 -50
- package/dist/cache/store.d.ts +6 -0
- package/dist/cache/store.js +21 -1
- package/dist/cache/trace.d.ts +53 -14
- package/dist/cache/trace.js +76 -30
- package/dist/cli/bin.js +2 -2
- package/dist/cli/index.js +43 -32
- package/dist/cli/init/engines.d.ts +1 -3
- package/dist/cli/init/engines.js +2 -2
- package/dist/cli/init/gateways.d.ts +1 -1
- package/dist/cli/init/gateways.js +11 -1
- package/dist/cli/init/mcp-config.d.ts +2 -1
- package/dist/cli/init/mcp-config.js +8 -3
- package/dist/cli/init/sibling-versions.json +1 -1
- package/dist/cli/init/versions.d.ts +0 -8
- package/dist/cli/init/versions.js +1 -10
- package/dist/cli/mcp.d.ts +3 -2
- package/dist/cli/mcp.js +52 -16
- package/dist/cli/run-output.d.ts +17 -0
- package/dist/cli/run-output.js +45 -0
- package/dist/collect/collect.js +8 -4
- package/dist/collect/registry.js +27 -16
- package/dist/config/compiled-files.d.ts +36 -0
- package/dist/config/compiled-files.js +50 -0
- package/dist/config/diagnose.js +21 -19
- package/dist/config/esm-hooks.d.ts +39 -44
- package/dist/config/esm-hooks.js +238 -63
- package/dist/config/load.d.ts +1 -7
- package/dist/config/load.js +23 -66
- package/dist/config/register.d.ts +8 -0
- package/dist/config/register.js +9 -0
- package/dist/config/resolve.d.ts +1 -0
- package/dist/config/resolve.js +33 -1
- package/dist/config/specifiers.d.ts +19 -0
- package/dist/config/specifiers.js +33 -0
- package/dist/config/tsconfig.d.ts +56 -0
- package/dist/config/tsconfig.js +115 -0
- package/dist/config/typescript.d.ts +19 -0
- package/dist/config/typescript.js +253 -0
- package/dist/engine/contract.d.ts +1 -0
- package/dist/engine/index.d.ts +4 -2
- package/dist/engine/session.js +2 -2
- package/dist/expect/async.js +4 -2
- package/dist/expect/poll-scope.d.ts +52 -0
- package/dist/expect/poll-scope.js +113 -0
- package/dist/expect/poll.js +33 -6
- package/dist/expect/values.js +11 -4
- package/dist/internal/abandoned.d.ts +11 -0
- package/dist/internal/abandoned.js +23 -0
- package/dist/internal/brands.d.ts +2 -0
- package/dist/internal/brands.js +2 -0
- package/dist/internal/client-identity.d.ts +9 -0
- package/dist/internal/client-identity.js +14 -0
- package/dist/internal/errors.d.ts +10 -3
- package/dist/internal/errors.js +23 -8
- package/dist/internal/node-version.d.ts +16 -7
- package/dist/internal/node-version.js +50 -15
- package/dist/internal/package-manager.js +1 -1
- package/dist/internal/realm-slot.d.ts +5 -4
- package/dist/internal/redact.d.ts +9 -4
- package/dist/internal/redact.js +120 -23
- package/dist/internal/time.d.ts +26 -4
- package/dist/internal/time.js +58 -14
- package/dist/internal/urls.d.ts +9 -5
- package/dist/internal/urls.js +19 -10
- package/dist/locator/engine.d.ts +12 -2
- package/dist/locator/engine.js +55 -14
- package/dist/locator/screen.js +59 -9
- package/dist/mcp/catalog.d.ts +3 -2
- package/dist/mcp/catalog.js +6 -6
- package/dist/mcp/output.d.ts +59 -0
- package/dist/mcp/output.js +129 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +9 -12
- package/dist/mcp/session.d.ts +8 -1
- package/dist/mcp/session.js +56 -15
- package/dist/mcp/tools.js +7 -5
- package/dist/oauth/chatgpt.js +3 -23
- package/dist/oauth/cli.js +1 -0
- package/dist/oauth/copilot.d.ts +5 -4
- package/dist/oauth/copilot.js +80 -7
- package/dist/oauth/grok.js +2 -1
- package/dist/oauth/models.js +2 -1
- package/dist/oauth/opencode-console.d.ts +10 -0
- package/dist/oauth/opencode-console.js +133 -0
- package/dist/oauth/providers/github-copilot.d.ts +12 -0
- package/dist/oauth/providers/github-copilot.js +77 -23
- package/dist/oauth/providers/opencode-console.d.ts +31 -0
- package/dist/oauth/providers/opencode-console.js +148 -0
- package/dist/oauth/providers.d.ts +2 -6
- package/dist/oauth/providers.js +3 -7
- package/dist/oauth/responses.d.ts +9 -0
- package/dist/oauth/responses.js +23 -0
- package/dist/report/build.d.ts +26 -0
- package/dist/report/build.js +16 -8
- package/dist/report/failure-text.d.ts +6 -1
- package/dist/report/failure-text.js +14 -4
- package/dist/report/format.d.ts +10 -5
- package/dist/report/format.js +12 -5
- package/dist/report/junit.js +11 -12
- package/dist/report/list.d.ts +12 -0
- package/dist/report/list.js +61 -24
- package/dist/report/markdown.d.ts +1 -1
- package/dist/report/markdown.js +37 -14
- package/dist/report/repeats.d.ts +6 -1
- package/dist/report/repeats.js +12 -3
- package/dist/run/artifacts.d.ts +22 -4
- package/dist/run/artifacts.js +71 -3
- package/dist/run/execute.d.ts +34 -5
- package/dist/run/execute.js +93 -44
- package/dist/run/extended-fixtures.js +6 -2
- package/dist/run/failure-evidence.js +10 -4
- package/dist/run/fixtures.js +6 -8
- package/dist/run/in-process.d.ts +2 -0
- package/dist/run/in-process.js +52 -10
- package/dist/run/last-run.d.ts +42 -8
- package/dist/run/last-run.js +121 -14
- package/dist/run/process-output.d.ts +73 -0
- package/dist/run/process-output.js +130 -0
- package/dist/run/provision.d.ts +2 -0
- package/dist/run/provision.js +1 -0
- package/dist/run/realm.d.ts +4 -1
- package/dist/run/realm.js +20 -6
- package/dist/run/records.d.ts +20 -4
- package/dist/run/records.js +26 -0
- package/dist/run/retry.d.ts +10 -1
- package/dist/run/retry.js +30 -12
- package/dist/run/runner.d.ts +9 -1
- package/dist/run/runner.js +101 -39
- package/dist/run/scheduler.js +255 -19
- package/dist/run/secrecy.d.ts +22 -19
- package/dist/run/secrecy.js +22 -18
- package/dist/run/serial.d.ts +75 -2
- package/dist/run/serial.js +243 -59
- package/dist/run/standalone.js +1 -1
- package/dist/run/steps.d.ts +0 -6
- package/dist/run/steps.js +3 -20
- package/dist/run/trace-redaction.d.ts +5 -6
- package/dist/run/trace-redaction.js +5 -6
- package/dist/run/worker/entry.js +40 -18
- package/dist/run/worker/handle.js +10 -5
- package/dist/run/worker/protocol.d.ts +85 -3
- package/dist/run/worker/session.d.ts +2 -0
- package/dist/run/worker/session.js +29 -0
- package/dist/telemetry/environment.d.ts +2 -1
- package/dist/telemetry/environment.js +12 -2
- package/dist/telemetry/events.js +1 -0
- package/dist/telemetry/project.d.ts +5 -6
- package/dist/telemetry/project.js +6 -11
- package/dist/telemetry/store.d.ts +5 -5
- package/dist/telemetry/store.js +5 -7
- package/dist/telemetry/telemetry.d.ts +2 -3
- package/dist/telemetry/telemetry.js +2 -4
- package/dist/types.d.ts +15 -6
- package/docs/agent-steps.mdx +1 -0
- package/docs/agents.mdx +7 -3
- package/docs/api-testing.mdx +2 -1
- package/docs/authentication.mdx +6 -3
- package/docs/browser.mdx +49 -12
- package/docs/bug-bash.mdx +2 -1
- package/docs/cache.mdx +66 -19
- package/docs/ci.mdx +14 -9
- package/docs/coding-agents.mdx +2 -1
- package/docs/core-concepts.mdx +208 -0
- package/docs/debugging.mdx +25 -12
- package/docs/decision-models.mdx +142 -0
- package/docs/example-projects.mdx +32 -0
- package/docs/executors.mdx +7 -2
- package/docs/explore.mdx +1 -0
- package/docs/github.mdx +14 -5
- package/docs/index.mdx +9 -5
- package/docs/integrations/eas.mdx +1 -0
- package/docs/integrations/index.mdx +1 -0
- package/docs/integrations/kernel.mdx +3 -2
- package/docs/migrate/cypress.mdx +26 -3
- package/docs/migrate/detox.mdx +24 -1
- package/docs/migrate/maestro.mdx +28 -4
- package/docs/migrate/playwright.mdx +44 -18
- package/docs/migrate/selenium.mdx +27 -3
- package/docs/mobile-ci.mdx +6 -5
- package/docs/mobile.mdx +96 -8
- package/docs/models.mdx +60 -9
- package/docs/quickstart.mdx +28 -16
- package/docs/reference/agent.mdx +13 -3
- package/docs/reference/app.mdx +2 -1
- package/docs/reference/cli.mdx +41 -18
- package/docs/reference/config.mdx +67 -13
- package/docs/reference/engine.mdx +25 -13
- package/docs/reference/environment.mdx +10 -2
- package/docs/reference/errors.mdx +13 -10
- package/docs/reference/expect.mdx +36 -13
- package/docs/reference/mcp.mdx +21 -8
- package/docs/reference/mobile.mdx +24 -13
- package/docs/reference/reporters.mdx +9 -2
- package/docs/reference/screen.mdx +49 -16
- package/docs/reference/test.mdx +32 -5
- package/docs/reference/web.mdx +133 -23
- package/docs/security.mdx +58 -42
- package/docs/subscriptions.mdx +92 -12
- package/docs/telemetry.mdx +9 -6
- package/docs/tools.mdx +1 -0
- package/docs/{starting-your-app.mdx → web.mdx} +157 -11
- package/docs/writing-an-engine.mdx +2 -1
- package/package.json +25 -8
- package/schema/report-v1.schema.json +14 -1
- package/skills/e2e/SKILL.md +5 -3
- package/skills/e2e/references/agent.md +33 -11
- package/skills/e2e/references/debugging.md +4 -4
- package/skills/e2e/references/mcp.md +8 -3
- package/skills/e2e/references/running.md +15 -9
- package/skills/e2e/references/setup.md +45 -16
- package/skills/e2e/references/writing-tests.md +35 -18
- package/docs/viewports.mdx +0 -146
- package/docs/writing-tests.mdx +0 -256
package/docs/reference/agent.mdx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: agent
|
|
3
3
|
description: Run agent actions, check conditions, and extract structured data.
|
|
4
|
+
icon: "robot"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Use `act` to interact with the app, `assert` to check the current screen,
|
|
@@ -191,7 +192,9 @@ Every `act` observation with unavailable semantics includes that image and
|
|
|
191
192
|
warning automatically. Earlier node ids are invalid, and the next successful
|
|
192
193
|
semantic capture presents the whole tree again. The screenshot shows the
|
|
193
194
|
current viewport; an unavailable tree does not prove that a control or
|
|
194
|
-
message is absent.
|
|
195
|
+
message is absent. After a secret fill there is no fallback: `act`, and a
|
|
196
|
+
judgment with `vision: true`, fails with `POLICY_DENIED` when semantic
|
|
197
|
+
capture times out before the step does.
|
|
195
198
|
|
|
196
199
|
If semantic capture fails, trace replay stops and the step cannot record a
|
|
197
200
|
new trace entry, even if the tree later recovers.
|
|
@@ -238,7 +241,12 @@ assert(assertion: string, options?: AssertOptions): Promise<void>;
|
|
|
238
241
|
|
|
239
242
|
Checks one fresh observation without polling. The judge sees only the
|
|
240
243
|
assertion and current observation, never prior steps or `act` summaries.
|
|
241
|
-
It answers `holds`, `fails`, or `inconclusive`.
|
|
244
|
+
It answers `holds`, `fails`, or `inconclusive`. When what the assertion is
|
|
245
|
+
about appears more than once, such as a total in a summary and on a pay
|
|
246
|
+
button, every instance must agree: one that contradicts it fails. Name
|
|
247
|
+
the place (`the order summary total is $42.00`) to judge only that one. A
|
|
248
|
+
claim about some item, such as `a todo is marked done`, still holds when one
|
|
249
|
+
item matches.
|
|
242
250
|
|
|
243
251
|
Throws `ASSERTION_FAILED` on a false judgment and `ASSERTION_INCONCLUSIVE`
|
|
244
252
|
when the screen did not show enough to decide. Both carry the explanation
|
|
@@ -271,7 +279,9 @@ Observes and judges at once. After a false or inconclusive judgment it
|
|
|
271
279
|
waits out `interval`, then observes every 500 ms (or every `interval`, when
|
|
272
280
|
shorter) without a model call, and judges again only once the screen
|
|
273
281
|
differs from the one last judged, pixels included under `vision`. Succeeds
|
|
274
|
-
on the first judgment that holds.
|
|
282
|
+
on the first judgment that holds. Judgments follow the `agent.assert`
|
|
283
|
+
rules, so a value shown in more than one place holds only once every
|
|
284
|
+
instance agrees.
|
|
275
285
|
|
|
276
286
|
Throws `STEP_TIMEOUT` on deadline expiry and `STEP_BUDGET_EXHAUSTED` on
|
|
277
287
|
budget exhaustion, each carrying the last judgment (with the same vision
|
package/docs/reference/app.mdx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: app
|
|
3
3
|
description: The portable app lifecycle fixture, available on every platform.
|
|
4
|
+
icon: "cube"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
`app` controls the app's lifecycle and captures screenshots. Each method
|
|
@@ -43,7 +44,7 @@ timeout. They do not accept per-call timeout options.
|
|
|
43
44
|
|
|
44
45
|
| Method | Timeout | Throws |
|
|
45
46
|
| --- | --- | --- |
|
|
46
|
-
| `open(path?)` | `config.timeout`, 120000 ms | `APP_URL_REQUIRED` for a path when the target declares no `app.url`, `POLICY_DENIED` for a
|
|
47
|
+
| `open(path?)` | `config.timeout`, 120000 ms | `APP_URL_REQUIRED` for a path when the target declares no `app.url`, `POLICY_DENIED` for a URL whose scheme is not `http:` or `https:` (`about:blank` aside), `APP_UNREACHABLE`, `ACTION_FAILED`, `UNSUPPORTED_CAPABILITY` without `session.open` on a target with a URL or without `session.restart` on one without (a device launches its pinned app) |
|
|
47
48
|
| `restart()` | `config.timeout`, 120000 ms | `ACTION_FAILED`, `ENGINE_FAILURE`, `UNSUPPORTED_CAPABILITY` without `session.restart` |
|
|
48
49
|
| `clearState()` | `config.timeout`, 120000 ms | `ACTION_FAILED`, `ENGINE_FAILURE`, `UNSUPPORTED_CAPABILITY` without `session.reset` |
|
|
49
50
|
| `back()` | `config.actionTimeout`, 30000 ms | `APP_NOT_OPEN`, `ACTION_FAILED`, `UNSUPPORTED_CAPABILITY` without `session.back` |
|
package/docs/reference/cli.mdx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: CLI
|
|
3
3
|
description: Commands, flags, output formats, and exit codes.
|
|
4
|
+
icon: "terminal"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
<CodeGroup>
|
|
@@ -56,7 +57,7 @@ bunx e2e --version
|
|
|
56
57
|
```
|
|
57
58
|
</CodeGroup>
|
|
58
59
|
|
|
59
|
-
The CLI needs Node.js 22.
|
|
60
|
+
The CLI needs Node.js 24.8 or newer, or 22.22.3 or newer on Node.js 22. Any package manager installs it (npm, pnpm, Yarn with or without Plug'n'Play, Bun); the CLI itself runs on Node.js, not on the Bun or Deno runtimes (`bunx e2e` runs it on Node.js). Under Yarn Plug'n'Play on Node.js 24.8 through 24.11.0, a `.cts` file fails to load (Node.js rejects the source Yarn's loader hands on); 24.11.1 and later load it.
|
|
60
61
|
|
|
61
62
|
## Help and version
|
|
62
63
|
|
|
@@ -96,9 +97,9 @@ For a new project, the wizard asks you to choose:
|
|
|
96
97
|
**Mobile (iOS/Android)** adds `@e2e-dev/mobile`, defaults to iOS on
|
|
97
98
|
macOS and Android elsewhere, and opens Settings. **None** adds nothing.
|
|
98
99
|
- A model provider or subscription for agent steps. Choose Vercel AI Gateway,
|
|
99
|
-
OpenRouter, an OpenAI-compatible endpoint, ChatGPT, GitHub Copilot,
|
|
100
|
-
SuperGrok. Choose None for tests that only use
|
|
101
|
-
the required packages and model config. Subscription users then sign in
|
|
100
|
+
OpenRouter, an OpenAI-compatible endpoint, ChatGPT, GitHub Copilot,
|
|
101
|
+
OpenCode Console, or SuperGrok. Choose None for tests that only use
|
|
102
|
+
locators. The wizard adds the required packages and model config. Subscription users then sign in
|
|
102
103
|
with `e2e login`. See [Models](/models) and [Subscriptions](/subscriptions).
|
|
103
104
|
- Where to install the agent skill (see [e2e guide](#e2e-guide)):
|
|
104
105
|
`.agents/skills/` for Codex, Cursor, Copilot, Gemini CLI, OpenCode, and
|
|
@@ -140,7 +141,10 @@ bunx e2e init --yes
|
|
|
140
141
|
```
|
|
141
142
|
</CodeGroup>
|
|
142
143
|
|
|
143
|
-
Re-running `init` keeps an existing config and adds no packages for it.
|
|
144
|
+
Re-running `init` keeps an existing config and adds no packages for it. MCP
|
|
145
|
+
registration keeps extra settings on the e2e server, such as environment
|
|
146
|
+
variables and client timeouts, even when repairing its launch command. A
|
|
147
|
+
current registration is left byte-for-byte unchanged. Once
|
|
144
148
|
a skill directory exists, later runs refresh copies that differ from the
|
|
145
149
|
installed version and never add a directory the project did not choose. A
|
|
146
150
|
`.claude/skills/e2e/` copy from an earlier version becomes the symlink when
|
|
@@ -164,6 +168,7 @@ npx e2e login openai # ChatGPT, browser sign-in
|
|
|
164
168
|
npx e2e login openai --device # sign in with a device code
|
|
165
169
|
npx e2e login github-copilot --from-gh # use your GitHub CLI login
|
|
166
170
|
npx e2e login github-copilot --client-id <id> [--enterprise-url <host>]
|
|
171
|
+
npx e2e login opencode-console # OpenCode Console, device code
|
|
167
172
|
npx e2e login spacexai # SuperGrok, device code
|
|
168
173
|
npx e2e login # choose a provider
|
|
169
174
|
```
|
|
@@ -173,6 +178,7 @@ pnpm exec e2e login openai # ChatGPT, browser sign-in
|
|
|
173
178
|
pnpm exec e2e login openai --device # sign in with a device code
|
|
174
179
|
pnpm exec e2e login github-copilot --from-gh # use your GitHub CLI login
|
|
175
180
|
pnpm exec e2e login github-copilot --client-id <id> [--enterprise-url <host>]
|
|
181
|
+
pnpm exec e2e login opencode-console # OpenCode Console, device code
|
|
176
182
|
pnpm exec e2e login spacexai # SuperGrok, device code
|
|
177
183
|
pnpm exec e2e login # choose a provider
|
|
178
184
|
```
|
|
@@ -182,6 +188,7 @@ bunx e2e login openai # ChatGPT, browser sign-in
|
|
|
182
188
|
bunx e2e login openai --device # sign in with a device code
|
|
183
189
|
bunx e2e login github-copilot --from-gh # use your GitHub CLI login
|
|
184
190
|
bunx e2e login github-copilot --client-id <id> [--enterprise-url <host>]
|
|
191
|
+
bunx e2e login opencode-console # OpenCode Console, device code
|
|
185
192
|
bunx e2e login spacexai # SuperGrok, device code
|
|
186
193
|
bunx e2e login # choose a provider
|
|
187
194
|
```
|
|
@@ -194,7 +201,7 @@ configuration.
|
|
|
194
201
|
|
|
195
202
|
| Argument or flag | Type | Default | Behavior |
|
|
196
203
|
| --- | --- | --- | --- |
|
|
197
|
-
| `[provider]` | `openai`, `github-copilot`, or `spacexai` | a picker | The subscription to sign in to |
|
|
204
|
+
| `[provider]` | `openai`, `github-copilot`, `opencode-console`, or `spacexai` | a picker | The subscription to sign in to |
|
|
198
205
|
| `--device` | boolean | `false` | ChatGPT: show a code to enter on another device instead of opening a browser |
|
|
199
206
|
| `--from-gh` | boolean | `false` | GitHub Copilot: reuse the token of the signed-in GitHub CLI |
|
|
200
207
|
| `--client-id <id>` | string | none | GitHub Copilot: the client id of your GitHub OAuth App with the device flow enabled |
|
|
@@ -239,10 +246,11 @@ bunx e2e models openai # one provider
|
|
|
239
246
|
</CodeGroup>
|
|
240
247
|
|
|
241
248
|
Asks the vendor which models the stored login serves and prints one line per
|
|
242
|
-
model: the id `chatgpt()`, `copilot()`, or `grok()`
|
|
243
|
-
for it, and its notes (reasoning levels, vision,
|
|
244
|
-
Copilot `not enabled` or `no chat
|
|
245
|
-
|
|
249
|
+
model: the id `chatgpt()`, `copilot()`, `opencodeConsole()`, or `grok()`
|
|
250
|
+
takes, the vendor's name for it, and its notes (reasoning levels, vision,
|
|
251
|
+
preview, hidden, for Copilot `not enabled` or `no chat or responses` when
|
|
252
|
+
`copilot()` cannot call it, and for OpenCode Console the plan, Zen or Go,
|
|
253
|
+
that serves it). Without a
|
|
246
254
|
stored login, or when the named provider has none, exits 1 with the sign-in
|
|
247
255
|
command; when one of several logins fails to list, the others still print and
|
|
248
256
|
the command exits 1. An unknown provider exits 2. See
|
|
@@ -277,15 +285,15 @@ See [Coding agents](/coding-agents).
|
|
|
277
285
|
|
|
278
286
|
<CodeGroup>
|
|
279
287
|
```bash npm
|
|
280
|
-
npx e2e mcp [--config <path>] [--target <name>] [--
|
|
288
|
+
npx e2e mcp [--config <path>] [--target <name>] [--headed] [--max-sessions <n>]
|
|
281
289
|
```
|
|
282
290
|
|
|
283
291
|
```bash pnpm
|
|
284
|
-
pnpm exec e2e mcp [--config <path>] [--target <name>] [--
|
|
292
|
+
pnpm exec e2e mcp [--config <path>] [--target <name>] [--headed] [--max-sessions <n>]
|
|
285
293
|
```
|
|
286
294
|
|
|
287
295
|
```bash bun
|
|
288
|
-
bunx e2e mcp [--config <path>] [--target <name>] [--
|
|
296
|
+
bunx e2e mcp [--config <path>] [--target <name>] [--headed] [--max-sessions <n>]
|
|
289
297
|
```
|
|
290
298
|
</CodeGroup>
|
|
291
299
|
|
|
@@ -342,6 +350,8 @@ A positional starting with `-` that names no file is a usage error, exit 2.
|
|
|
342
350
|
This is what `pnpm test:e2e -- --headed` produces: the `--` reaches e2e and
|
|
343
351
|
`--headed` would otherwise be taken for a file. The message names the direct
|
|
344
352
|
form, `pnpm exec e2e run --headed`.
|
|
353
|
+
For npm, the direct form is `npm exec -- e2e run --headed`; npm needs the
|
|
354
|
+
separator before the binary to pass its flags through.
|
|
345
355
|
|
|
346
356
|
When nothing is left to run, `NO_TESTS` names the cause: no file matched the
|
|
347
357
|
globs (with look-alike files such as `tests/login.test.ts`), a positional
|
|
@@ -359,7 +369,7 @@ or every test was filtered out.
|
|
|
359
369
|
| `--exclude-tag <tags>` | comma-separated or repeated | none | Leaves out every test carrying any of the tags, whatever `--tag` or a positional selected. A serial group still runs whole when any member is selected; tag the serial `describe` to exclude the flow. |
|
|
360
370
|
| `--grep <pattern>` | regular expression, repeatable | none | Only tests whose title matches one of the patterns. The text matched is the describe titles and the test title joined by one space (`checkout pays`); the file and the tags are not part of it. A bare pattern is case-sensitive; `'/pattern/i'` adds flags. A pattern that does not compile is a usage error, exit 2. |
|
|
361
371
|
| `--grep-invert <pattern>` | regular expression, repeatable | none | Leaves out every test whose title matches one of the patterns. Same text and pattern forms as `--grep`; both together keep the tests `--grep` matches minus the ones `--grep-invert` matches. |
|
|
362
|
-
| `--last-failed` | boolean | `false` | Only the tests the previous run did not pass, read from the `report.json` this run overwrites, `<output>/report.json` (`--output`, else the config's [`output`](/reference/config#output)): failed, timed out, interrupted, or skipped because a setup, a serial predecessor, a hook, or the worker failed, and every test it selected in the describe or file, on that target, of a `beforeAll` or `afterAll` that failed (for a setup, the tests that consume its session). A rerun that runs the hook again reports it again if it still fails
|
|
372
|
+
| `--last-failed` | boolean | `false` | Only the tests the previous run did not pass, read from the `report.json` this run overwrites, `<output>/report.json` (`--output`, else the config's [`output`](/reference/config#output)): failed, timed out, interrupted, or skipped because a setup, a serial predecessor, a hook, or the worker failed or `--max-failures` stopped the run first, and every test it selected in the describe or file, on that target, of a `beforeAll` or `afterAll` that failed (for a setup, the tests that consume its session). A rerun that runs the hook again reports it again if it still fails, and a rerun that runs any test of its scope without it failing resolves it. A test another filter (`--grep`, `--tag`, `--target`, `--agent`, a positional) leaves out of the rerun stays owed: the rerun's report carries its last result, and the hook failure whose scope it is in, under `run.carried`, the next `--last-failed` selects it again, and the [`@e2e-dev/github`](/github) page stays red until it passes (⏹️ for a test the run before interrupted). The rerun's own exit code and summary count only what it ran. It keeps the artifacts the previous report names and writes its own under `artifacts/rerun-<n>/`, so no attempt overwrites an earlier one's files. A test is named per target and agent. No report is `NO_LAST_RUN`; a previous run with nothing failed selects nothing, `NO_TESTS` unless `--pass-with-no-tests`. |
|
|
363
373
|
| `--shard <index/total>` | `2/3` | none | Runs one contiguous slice of the selected tests, cut once every other filter applied. Slices differ in size by at most one test, a serial group counts as one and is never split, and each shard brings only the setup tests its own tests need. Every shard runs the same command with a different index; the order is the report order, so the same suite shards the same way on every machine. A shard that gets no test is `NO_TESTS` unless `--pass-with-no-tests`. See [Sharding](/ci#sharding). |
|
|
364
374
|
| `--headed` | boolean | `false` | Visible UI when the engine supports it. |
|
|
365
375
|
| `--agent <names>` | comma-separated or repeated | `default` | Runs unpinned tests once per selected agent. For a test with `{ agent }`, selects the shared names when there is overlap; otherwise keeps the test's selection. An unknown name is `INVALID_CONFIG`. |
|
|
@@ -368,7 +378,7 @@ or every test was filtered out.
|
|
|
368
378
|
| `--repeat-each <n>` | integer, at least 1 | `1` | Runs every selected test this many times. Each run is a result of its own, with `repeat` 0 through `n - 1` and its own `id`; the list reporter titles the later runs `(repeat #1)`, `(repeat #2)`, and their artifacts go under a `repeat-<n>` directory. Setup tests run once. With the replay cache on, the first run records and the later ones replay, so pair it with `--no-cache` to exercise the model each time. The `list` summary adds a `Repeats` row (`1 of 2 tests passed all 5 runs`) and one line per test that did not pass every run, naming each run that failed; the `markdown` page carries the same tally. |
|
|
369
379
|
| `--max-failures <n>` | integer, at least 1 | none | Stops the run once this many tests have failed or timed out. Nothing more is dispatched, the tests running on other workers end as `interrupted`, and the tests not started, the rest of the file whose test reached the limit included, are skipped with cause `failure-limit` and the reason `run stopped after 3 failures (--max-failures 3)`. The exit code is the failures' own, 1, not 130. |
|
|
370
380
|
| `--reporter <ids>` | comma-separated list | config | Replaces the built-in IDs in `config.reporters`: `list`, `json`, `junit`, `markdown`. `json` with `list` is `INVALID_CONFIG`. [Reporter objects](/reference/reporters) in the config keep running. |
|
|
371
|
-
| `--output <dir>` | string | config, else `.e2e` | The results directory for this run, over the config's [`output`](/reference/config#output): the report, the reporter files, the AI trace, `artifacts/` (cleared once the run's tests start), and `sessions/`. Resolved from the project root; one the run cannot own is `INVALID_CONFIG`. The removed `--artifacts <dir>` fails with the `--output` it maps to: `--artifacts out/artifacts` is `--output out`, and a directory whose parent is the project root or outside it maps to `--output .e2e`. |
|
|
381
|
+
| `--output <dir>` | string | config, else `.e2e` | The results directory for this run, over the config's [`output`](/reference/config#output): the report, the reporter files, the AI trace, `artifacts/` (cleared once the run's tests start, down to what the previous report names on a `--last-failed` rerun), and `sessions/`. Resolved from the project root; one the run cannot own is `INVALID_CONFIG`. The removed `--artifacts <dir>` fails with the `--output` it maps to: `--artifacts out/artifacts` is `--output out`, and a directory whose parent is the project root or outside it maps to `--output .e2e`. |
|
|
372
382
|
| `--no-cache` | boolean | `false` | Replay cache off for this run, whatever `config.cache` says. |
|
|
373
383
|
| `--strict-cache` | boolean | `false` | Turns on `cache.strict` for this run: a step whose recording exists but no longer replays fails with `REPLAY_STALE` instead of handing off to the agent. See [Fail on a stale recording](/cache#fail-on-a-stale-recording). |
|
|
374
384
|
| `--pass-with-no-tests` | boolean | `false` | Exit 0 instead of `NO_TESTS` when nothing is selected. |
|
|
@@ -479,8 +489,8 @@ bunx e2e run --reporter list,junit
|
|
|
479
489
|
| --- | --- |
|
|
480
490
|
| `list` | Terminal progress, failures with code frames, and a run summary. On a TTY, live progress includes the current agent step, model turns, tool calls, and reasoning excerpts. Untrusted fields are capped at 8 KiB and stripped of control characters. |
|
|
481
491
|
| `json` | The report document to stdout and nothing else there, so `e2e run --reporter json \| jq` works. Same document as `<output>/report.json`, described by `schema/report-v1.schema.json` in the package. The shape changes only with the `schemaVersion` field (`report-1` today). Cannot be combined with `list`. |
|
|
482
|
-
| `junit` | `junit.xml` beside the report. One `<testsuite>` per file, one `<testcase>` per test-target pair named `title > path [target]`. A test-class error is a `<failure>`, any other an `<error>`, a skip a `<skipped>` with its reason. Run-level errors form a `run` suite. |
|
|
483
|
-
| `markdown` | `summary.md` beside the report with counts, cost, errors, and failure details. Failed and flaky tests also get a page under `failures/` there, with steps, model turns, and the screen at failure. Exploration runs show findings. [`@e2e-dev/github`](/github) uses this summary for pull request comments. |
|
|
492
|
+
| `junit` | `junit.xml` beside the report. One `<testsuite>` per file, one `<testcase>` per test-target pair named `title > path [target]`. A test-class error is a `<failure>`, any other an `<error>`, a skip a `<skipped>` with its reason. An interrupted test reached no verdict, so it is a `<skipped>` whose message starts `interrupted:`. Run-level errors form a `run` suite. |
|
|
493
|
+
| `markdown` | `summary.md` beside the report with counts, cost, errors, and failure details. Failed and flaky tests also get a page under `failures/` there, with steps, model turns, and the screen at failure. Interrupted tests are counted on their own and get no page. Exploration runs show findings. [`@e2e-dev/github`](/github) uses this summary for pull request comments. |
|
|
484
494
|
|
|
485
495
|
Every run that gets to its tests writes `report.json` under the [output directory](/reference/config#output)
|
|
486
496
|
(`.e2e` by default) whatever the reporters are, and the reporters' files
|
|
@@ -490,6 +500,16 @@ fails to start, an interrupt) writes none of them and leaves the previous
|
|
|
490
500
|
run's files in place; its errors are on the terminal and in the exit code. A `junit.xml` or `summary.md` that could not be written is a
|
|
491
501
|
line on stderr, never a run error.
|
|
492
502
|
|
|
503
|
+
`run.summary` in the report counts the results. `discovered` is every
|
|
504
|
+
test-target pair the runner collected and `selected` the ones this run
|
|
505
|
+
chose; the selection's left-out pairs are in `results` as `selected: false`
|
|
506
|
+
but in no other count. `passed`, `failed` (timed out included),
|
|
507
|
+
`interrupted`, `flaky`, and `skipped` count the selected results and add up
|
|
508
|
+
to `selected`. `interrupted` is a test the run stopped before its verdict
|
|
509
|
+
(a signal, `--max-failures`, or a run-level error such as
|
|
510
|
+
`MODEL_UNAVAILABLE`), never a failure. `executed` is the selected
|
|
511
|
+
results that ran at least one attempt.
|
|
512
|
+
|
|
493
513
|
With `--ai-trace`, the run also writes `<output>/ai-trace.json`: one entry per
|
|
494
514
|
model round trip with the exact prompt, tool definitions, response, usage,
|
|
495
515
|
and provider metadata. Observations in it are already redacted. Inline image
|
|
@@ -510,7 +530,10 @@ Signals escalate.
|
|
|
510
530
|
any test starts (during collection, an engine's `prepare`, or app
|
|
511
531
|
startup) writes no report and leaves the previous one in place.
|
|
512
532
|
2. A second signal forces. Workers dispose their engines at once and are
|
|
513
|
-
killed when the cleanup budget is spent. The report is still written
|
|
533
|
+
killed when the cleanup budget is spent. The report is still written,
|
|
534
|
+
and so are `junit.xml` and `summary.md` when the `junit` and
|
|
535
|
+
`markdown` reporters are on; a custom reporter's
|
|
536
|
+
`onRunFinished` is abandoned.
|
|
514
537
|
3. A third signal exits on the spot, after killing the process groups of every
|
|
515
538
|
app command the run started. A process attached through
|
|
516
539
|
`reuseExisting` is left alone.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: E2EConfig
|
|
3
3
|
description: Every configuration key, its default, its valid range, and the environment variables.
|
|
4
|
+
icon: "sliders"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Export an object from `e2e.config.ts` and use `satisfies E2EConfig` to check
|
|
@@ -69,10 +70,45 @@ It throws when the file is missing; guard it with `existsSync` from
|
|
|
69
70
|
`node:fs` when only some machines have one.
|
|
70
71
|
|
|
71
72
|
Config and test files run as ESM whatever the nearest `package.json` `type`
|
|
72
|
-
says, and so does
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
says, and so does every `.ts`, `.mts`, `.tsx`, and `.jsx` file they reach: a
|
|
74
|
+
helper by path, a package that exports its `.ts` source by name, or a `.ts`
|
|
75
|
+
file a CommonJS file requires. A `.cts` file is CommonJS, written with
|
|
76
|
+
`require`, `import x = require()`, and `export =`; its `import` statements are
|
|
77
|
+
not turned into `require` calls. A `.ts` file written with `require` or
|
|
78
|
+
`module.exports` fails to load: name it `.cts`. JavaScript keeps the format
|
|
79
|
+
its package declares.
|
|
80
|
+
|
|
81
|
+
e2e compiles TypeScript and JSX itself, and an import written in such a file
|
|
82
|
+
resolves the way TypeScript resolves it: `./helper.js` and `./helper` load
|
|
83
|
+
`helper.ts`, `./view.jsx` loads `view.tsx`, `./lib` loads the file
|
|
84
|
+
`lib/package.json` names as `main`, else `lib/index.ts`, a bare import that
|
|
85
|
+
`tsconfig.json` maps through `paths` or `baseUrl` loads the mapped file, and
|
|
86
|
+
a `#` import or package export that names a missing `./x.js`, `./x.jsx`, or
|
|
87
|
+
`./x` loads its `x.ts` or `x.tsx` source when imported (a `require()` of it fails as Node.js reports
|
|
88
|
+
it). An import written in a JavaScript file resolves
|
|
89
|
+
as Node.js resolves it.
|
|
90
|
+
|
|
91
|
+
The `tsconfig.json` is the nearest one above the file, or, when that one has
|
|
92
|
+
`references` and does not include the file itself (as Vite writes it), the
|
|
93
|
+
directly referenced one that does. e2e reads its `paths`, `baseUrl`, `jsx`, `jsxFactory`,
|
|
94
|
+
`jsxFragmentFactory`, `jsxImportSource`, `experimentalDecorators`,
|
|
95
|
+
`emitDecoratorMetadata`, `useDefineForClassFields` (and `target`, which sets
|
|
96
|
+
its default), and `verbatimModuleSyntax`, once per process and again for each
|
|
97
|
+
session `e2e mcp` opens. A `tsconfig.json` e2e cannot read, such as one that
|
|
98
|
+
`extends` a package that is not installed, is skipped with a warning.
|
|
99
|
+
TypeScript inside an installed package compiles without the project's
|
|
100
|
+
`tsconfig.json`.
|
|
101
|
+
|
|
102
|
+
e2e refuses, naming the file and line, two things it cannot compile:
|
|
103
|
+
auto-accessors (`accessor x = 1`) and decorators without
|
|
104
|
+
`experimentalDecorators`. Each file compiles on its own, without type
|
|
105
|
+
information, so a type imported without `import type` fails to load when the
|
|
106
|
+
import stays in the output (a decorated member's type under
|
|
107
|
+
`emitDecoratorMetadata`, a re-exported type); the error names the import to
|
|
108
|
+
change. A JSON file imported without `with { type: 'json' }` loads with its
|
|
109
|
+
parsed contents as the default export. Stack traces and failure locations
|
|
110
|
+
point at the TypeScript source, through another loader's source map too
|
|
111
|
+
(`NODE_OPTIONS=--import tsx`).
|
|
76
112
|
|
|
77
113
|
## Top level
|
|
78
114
|
|
|
@@ -96,6 +132,8 @@ export interface E2EConfig {
|
|
|
96
132
|
cleanupTimeout?: number;
|
|
97
133
|
/** Retries per test, 0 through 10; default 1 in CI, else 0. */
|
|
98
134
|
retries?: number;
|
|
135
|
+
/** Fail the run when a test skips itself after a soft failure or an earlier failed attempt; default false. */
|
|
136
|
+
failOnSkippedFailure?: boolean;
|
|
99
137
|
/** Parallel workers, 1 through 1024; default 1 in CI, else half the cores. An engine may cap it lower. */
|
|
100
138
|
workers?: number;
|
|
101
139
|
/** `{ store }` hands every artifact to a host store as it is produced. */
|
|
@@ -158,6 +196,17 @@ Every numeric value must be a safe integer. `projectId` falls back to
|
|
|
158
196
|
`package.json`. `workers` never exceeds what a target's engine declares. A
|
|
159
197
|
targeted agent action is bounded by the smaller of `actionTimeout` and 15 s.
|
|
160
198
|
|
|
199
|
+
## failOnSkippedFailure
|
|
200
|
+
|
|
201
|
+
Set `failOnSkippedFailure: true` to fail the run with exit code 1 when a test
|
|
202
|
+
skips after a soft assertion failure or skips a retry after an earlier failed
|
|
203
|
+
attempt. The default is `false`.
|
|
204
|
+
|
|
205
|
+
The test keeps its `skipped` status and reason. Its failures remain in the
|
|
206
|
+
report, and the CLI shows them under `Skipped After Failure` with either
|
|
207
|
+
setting. Clean skips, successful retries, and engine cleanup diagnostics do
|
|
208
|
+
not trigger this policy. A skip still stops the body and does not retry.
|
|
209
|
+
|
|
161
210
|
## targets
|
|
162
211
|
|
|
163
212
|
```ts
|
|
@@ -267,8 +316,9 @@ it (no `app.command`) is `INVALID_CONFIG`. An `app.command` with neither
|
|
|
267
316
|
|
|
268
317
|
### The app's site
|
|
269
318
|
|
|
270
|
-
A test or the agent may open any http(s) URL
|
|
271
|
-
|
|
319
|
+
A test or the agent may open any http(s) URL, and `about:blank`; every
|
|
320
|
+
other scheme (`file:`, `data:`, `javascript:`, `view-source:`, `blob:`) is
|
|
321
|
+
`POLICY_DENIED`. The site of `url`, its registrable domain
|
|
272
322
|
(`app.example.com` and `auth.example.com` are one site), scopes two things:
|
|
273
323
|
the browser engine's [`headers`](/reference/web#options) reach the
|
|
274
324
|
site and no other host, and child frames off the site stay out of
|
|
@@ -369,7 +419,7 @@ run.
|
|
|
369
419
|
| `report.json` | The canonical report; `--last-failed` reads the one here |
|
|
370
420
|
| `junit.xml`, `summary.md`, `failures/` | The `junit` and `markdown` reporters' files |
|
|
371
421
|
| `ai-trace.json` | `--ai-trace` |
|
|
372
|
-
| `artifacts/` | Screenshots, traces, videos, downloads, and logs, one directory per attempt. Cleared once a run's tests start, so it holds the latest run's evidence and nothing its report no longer names |
|
|
422
|
+
| `artifacts/` | Screenshots, traces, videos, downloads, and logs, one directory per attempt. Cleared once a run's tests start, so it holds the latest run's evidence and nothing its report no longer names. A `--last-failed` rerun keeps the files the report it reruns names and writes its own attempts under `artifacts/rerun-<n>/` |
|
|
373
423
|
| `sessions/` | The run's encrypted `test.setup` sessions, deleted when it ends |
|
|
374
424
|
| `videos/<session>/` | [`e2e mcp`](/reference/mcp#recording) session recordings |
|
|
375
425
|
|
|
@@ -754,8 +804,9 @@ export interface ModelInstance {
|
|
|
754
804
|
}
|
|
755
805
|
```
|
|
756
806
|
|
|
757
|
-
Construct the model in your config with an AI SDK provider.
|
|
758
|
-
|
|
807
|
+
Construct the model in your config with an AI SDK provider. You can use all
|
|
808
|
+
providers that support tool calls, see [AI SDK providers](/models#ai-sdk-providers).
|
|
809
|
+
For subscription sign-in, use the [`e2e/oauth/*` models](/subscriptions).
|
|
759
810
|
|
|
760
811
|
| Gateway | Constructor | Package | Reads |
|
|
761
812
|
| --- | --- | --- | --- |
|
|
@@ -798,7 +849,9 @@ Credentials and secrets are separate namespaces: `secrets.get(name)` returns a
|
|
|
798
849
|
reports know that handle as `<name>.password` (`<secret:admin.password>`), so
|
|
799
850
|
`credentials.admin` and `secrets.admin` can both exist; a `secrets` entry
|
|
800
851
|
named exactly `admin.password` beside an `admin` credential is
|
|
801
|
-
`INVALID_CONFIG`.
|
|
852
|
+
`INVALID_CONFIG`. So are two credentials whose names map to one
|
|
853
|
+
`E2E_USER_<NAME>_*` override, like `svc-a` and `svc_a` (see
|
|
854
|
+
[Environment variables](/reference/environment)).
|
|
802
855
|
|
|
803
856
|
```ts
|
|
804
857
|
/** Named test identity. The password remains an opaque Secret. */
|
|
@@ -824,7 +877,8 @@ export type SecretConfig = string | SecretProvider;
|
|
|
824
877
|
|
|
825
878
|
An entry is a static value, or a provider called on every authorized fill (a
|
|
826
879
|
vault lookup, a freshly computed TOTP). It is recorded in the config digest by
|
|
827
|
-
name only, and an `E2E_SECRET_<NAME>` override wins over both.
|
|
880
|
+
name only, and an `E2E_SECRET_<NAME>` override wins over both. Two entries whose
|
|
881
|
+
names map to one variable, like `api-key` and `api_key`, are `INVALID_CONFIG`. Every entry
|
|
828
882
|
must resolve to a string of at least 6 characters (code points) or a
|
|
829
883
|
function; anything else is `INVALID_CONFIG`. The minimum exists for redaction: every occurrence
|
|
830
884
|
of a value becomes `<secret:name>`, and a shorter value would take ordinary
|
|
@@ -877,7 +931,7 @@ See [Secrets that are not passwords](/authentication#secrets-that-are-not-passwo
|
|
|
877
931
|
In `read-write` mode the replay cache records an `agent.act()` only after a
|
|
878
932
|
later verification passes, such as a locator assertion or `agent.assert()`.
|
|
879
933
|
`read-only` replays existing entries and writes none; `off` disables both.
|
|
880
|
-
See [Caching
|
|
934
|
+
See [Caching](/cache).
|
|
881
935
|
|
|
882
936
|
```ts
|
|
883
937
|
/**
|
|
@@ -932,7 +986,7 @@ instead of a hand-off to the agent; see
|
|
|
932
986
|
`e2e init` adds `.e2e/cache/` to `.gitignore`, so committing entries is
|
|
933
987
|
opt-in. Remove that line to share replays with CI and teammates; CI stays
|
|
934
988
|
`read-only` unless `cache: 'read-write'` is set. See
|
|
935
|
-
[Caching
|
|
989
|
+
[Caching](/cache#commit-the-replay-cache).
|
|
936
990
|
|
|
937
991
|
## Run limits
|
|
938
992
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: e2e/engine
|
|
3
3
|
description: Build an engine with observations, actions, lifecycle hooks, and fixtures.
|
|
4
|
+
icon: "gear"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Import engine types and helpers from `e2e/engine`. `defineEngine` validates
|
|
@@ -709,7 +710,11 @@ export type PointerAction =
|
|
|
709
710
|
readonly direction: ScrollDirection;
|
|
710
711
|
readonly momentum?: Momentum;
|
|
711
712
|
}
|
|
712
|
-
| {
|
|
713
|
+
| {
|
|
714
|
+
readonly kind: 'swipeTo';
|
|
715
|
+
readonly target: ViewportPoint;
|
|
716
|
+
readonly durationMs?: number;
|
|
717
|
+
};
|
|
713
718
|
|
|
714
719
|
/** Every pointer action kind; what an engine declares in `pointerActions`. */
|
|
715
720
|
export type PointerActionKind = PointerAction['kind'];
|
|
@@ -923,6 +928,13 @@ export const RETRYABLE_ENGINE_ERROR_CODES: ReadonlySet<EngineErrorCode> = new Se
|
|
|
923
928
|
| `INVALID_STATE` | `APP_NOT_OPEN` | no |
|
|
924
929
|
| `ENGINE_FAILURE`, any non-`EngineError` | infrastructure `ENGINE_FAILURE` | no |
|
|
925
930
|
|
|
931
|
+
An `OPERATION_TIMEOUT` on a locate or read that started with under 100 ms of
|
|
932
|
+
a waiting call's deadline left, after one that completed, ends the wait
|
|
933
|
+
instead: an action's or `waitFor`'s `LOCATOR_NOT_FOUND`, or an assertion's
|
|
934
|
+
`ASSERTION_FAILED`, with the timeout as its cause. A negated assertion passes
|
|
935
|
+
there if its negation had held long enough by the time the read was cut off, as
|
|
936
|
+
`pollCondition` below describes.
|
|
937
|
+
|
|
926
938
|
An `EngineError` a contributed fixture method throws is mapped by the table
|
|
927
939
|
above, so a fixture over a session that ended reports `APP_NOT_OPEN` the way
|
|
928
940
|
an observation would. A method can also fail a step with the runner's own
|
|
@@ -960,8 +972,8 @@ Use these helpers to keep behavior consistent across engines:
|
|
|
960
972
|
| --- | --- |
|
|
961
973
|
| `matchesText(actual, pattern)`, `toTextPattern(match, { exact? })`, `describePattern(pattern)` | `TextPattern` matching for `locate` and text matchers; `toTextPattern` throws `INVALID_ARGUMENT` for a `match` that is neither a string nor a `RegExp` |
|
|
962
974
|
| `resolveExpression(expression, nodes, { selector? })` | The reference `locate`. Resolves one `LocatorExpression` over a semantic tree in document order, with `text` and `label` answering the innermost match when a container echoes a descendant's text. An engine whose tree is the whole truth (a device) calls it; a browser engine reproduces it. A `selector` needs the hook, a `frame` is `FRAME_NOT_FOUND` |
|
|
963
|
-
| `urlMatches(current, expected, baseHref)` | `toHaveURL`-style comparison; an `expected` that is neither a string nor a `RegExp` throws `INVALID_ARGUMENT`, as in `toTextPattern` |
|
|
964
|
-
| `pollCondition({ deadline, signal, negated, evaluate, onTimeout })`, `Deadline` | Assertion polling and the negation grace window |
|
|
975
|
+
| `urlMatches(current, expected, baseHref, ignoreCase?)` | `toHaveURL`-style comparison, `ignoreCase` as on the locator matchers; an `expected` that is neither a string nor a `RegExp` throws `INVALID_ARGUMENT`, as in `toTextPattern` |
|
|
976
|
+
| `pollCondition({ deadline, signal, negated, evaluate, onTimeout })`, `Deadline` | Assertion polling and the negation grace window. An `OPERATION_TIMEOUT` from an `evaluate` that started with under 100 ms of the deadline left, after one that completed, ends the poll: `onTimeout(cause)` builds the failure with it, and a negation passes if it had held long enough by the time that read was cut off. Bound each read `evaluate` makes by `deadline` (`context.operation(deadline.remaining())`): one on the action timeout can outlast the assertion's own |
|
|
965
977
|
| `validateJsonValue(value, label, rules?)` | Checks a value is plain JSON: a top-level `undefined` passes; a non-finite number, a cycle, an object that is not a plain object or array, or a function, symbol, bigint, or `undefined` inside is `INVALID_ARGUMENT` naming `label`. A `Secret` is `POLICY_DENIED` unless `rules.onSecret` throws its own; `rules.maxDepth` caps the nesting |
|
|
966
978
|
| `rejectUnknownKeys(label, value, keys, code?)` | Throws `INVALID_CONFIG` for the first own key of `value` outside `keys`, naming the nearest known key when one is a plausible typo (`web() has unknown key "viewprt"; did you mean "viewport"?`) and the known keys otherwise: the check the runner runs on its own config objects, for an engine factory's options. Pass `'INVALID_ARGUMENT'` as `code` for an object a test passes to a fixture method |
|
|
967
979
|
| `rejectUnknownOptions(api, options, known, code?)` | `INVALID_ARGUMENT` (or `code`, `INVALID_LOCATOR` for a locator option) for an option key a fixture method or matcher does not take, so a JavaScript caller's unsupported option fails instead of running on the default. `options` must be a plain object or `undefined`; a class instance or array is refused, and non-enumerable own keys count as keys |
|
|
@@ -1151,16 +1163,16 @@ startedAt }` for `stopVideo` to hand back. A `stop` that throws or returns
|
|
|
1151
1163
|
anything else is `ENGINE_FAILURE`, naming the provider and the lease. The
|
|
1152
1164
|
target argument's type is exported as `ProviderRecordingTarget`.
|
|
1153
1165
|
|
|
1154
|
-
|
|
1155
|
-
archive
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1166
|
+
When the session knows a secret value, the runner redacts every text entry in
|
|
1167
|
+
each trace archive, so a value a test spelled into a URL or the options the
|
|
1168
|
+
engine opened the attempt with (`resolveSecret`) never stay in it. After a
|
|
1169
|
+
secret fill it also drops the screencast frames: every `screencast/` entry,
|
|
1170
|
+
each `screencast-frame` record in a `.trace` entry, and any image a record
|
|
1171
|
+
names.
|
|
1160
1172
|
If redaction fails, it deletes the archives and records
|
|
1161
1173
|
`TRACE_WITHHELD`. Videos are unmasked and carry `redaction: 'incomplete'`.
|
|
1162
|
-
A `download` an engine attaches is the app's bytes:
|
|
1163
|
-
|
|
1174
|
+
A `download` an engine attaches is the app's bytes: when the session knows
|
|
1175
|
+
a secret value, the runner rewrites a text one (`.txt`,
|
|
1164
1176
|
`.csv`, `.json`, `.html`) through the ledger and labels it `complete`; every
|
|
1165
1177
|
other download keeps its bytes and carries `redaction: 'incomplete'`.
|
|
1166
1178
|
|
|
@@ -1185,8 +1197,8 @@ export interface EngineFixtureContext {
|
|
|
1185
1197
|
/**
|
|
1186
1198
|
* Resolves a navigation target against the base URL. Throws
|
|
1187
1199
|
* `APP_URL_REQUIRED` when the target declares no URL and `POLICY_DENIED`
|
|
1188
|
-
* for
|
|
1189
|
-
* re-implements the rule the harness owns.
|
|
1200
|
+
* for any scheme but `http:` and `https:` (`about:blank` aside), so a
|
|
1201
|
+
* fixture never re-implements the rule the harness owns.
|
|
1190
1202
|
*/
|
|
1191
1203
|
resolveUrl(url: string): string;
|
|
1192
1204
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Environment variables
|
|
3
3
|
description: Every variable the runner and the first-party engines read, and what each one does.
|
|
4
|
+
icon: "dollar-sign"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
These variables configure the runner and first-party packages. In the tables,
|
|
@@ -21,6 +22,7 @@ See [Models](/models) and [Subscriptions](/subscriptions).
|
|
|
21
22
|
| Variable | Reading | Effect |
|
|
22
23
|
| --- | --- | --- |
|
|
23
24
|
| `E2E_OAUTH_CREDENTIALS` | value | The stored subscription logins as JSON, the contents of `oauth.json`, for a machine nobody can sign in on. The `e2e/oauth/*` models and `e2e models` read it in place of `$XDG_CONFIG_HOME/e2e/oauth.json`; `e2e login` and `e2e logout` refuse to change it, and refreshed tokens are not written back |
|
|
25
|
+
| `OPENCODE_API_KEY` | value | An OpenCode Console service account key; `opencodeConsole()` uses it in place of the stored `opencode-console` login; `e2e models` still reads the stored login. OpenCode reads the same variable |
|
|
24
26
|
| `XDG_CONFIG_HOME` | value | Directory of the stored logins, `$XDG_CONFIG_HOME/e2e/oauth.json`; default `~/.config/e2e/oauth.json` |
|
|
25
27
|
|
|
26
28
|
## Credentials and secrets
|
|
@@ -32,7 +34,13 @@ See [Models](/models) and [Subscriptions](/subscriptions).
|
|
|
32
34
|
| `E2E_SECRET_<NAME>` | set | Replaces the value of `secrets.<name>` |
|
|
33
35
|
|
|
34
36
|
`<NAME>` is the name uppercased with every character outside `A-Z0-9`
|
|
35
|
-
replaced by `_`, so `power-user` becomes `E2E_USER_POWER_USER_USERNAME`.
|
|
37
|
+
replaced by `_`, so `power-user` becomes `E2E_USER_POWER_USER_USERNAME`. Two
|
|
38
|
+
credentials, or two secrets, whose names map to the same `<NAME>` (`api-key`
|
|
39
|
+
and `api_key` both read `E2E_SECRET_API_KEY`; `svc-a` and `svc_a` both read
|
|
40
|
+
`E2E_USER_SVC_A_USERNAME` and `_PASSWORD`) are `INVALID_CONFIG` at config
|
|
41
|
+
load, whether or not a variable is set, so one rotation never replaces two
|
|
42
|
+
entries; the message names the entries and the variables. A credential and a
|
|
43
|
+
secret may share a name, since their prefixes differ. A
|
|
36
44
|
variable for a name absent from the config is ignored. An empty value is
|
|
37
45
|
`INVALID_CONFIG`, and so is a password or secret shorter than 6 characters
|
|
38
46
|
(code points): redaction rewrites every occurrence of a value, and one that
|
|
@@ -50,7 +58,6 @@ short would take ordinary text with it.
|
|
|
50
58
|
| --- | --- | --- |
|
|
51
59
|
| `NO_COLOR` | set | Plain CLI output. Colors are otherwise on for a TTY or in CI and off when piped |
|
|
52
60
|
| `FORCE_COLOR` | set | Colored CLI output even when piped |
|
|
53
|
-
| `NODE_OPTIONS` | value | Inspected for a TypeScript `--import` loader, which decides how the runner registers its own module hooks for `.ts` config and test files |
|
|
54
61
|
| `TERM` | value | `dumb` draws the `e2e init` wordmark at rest, without animation, as in CI |
|
|
55
62
|
| `GITHUB_SHA`, `GITHUB_HEAD_REF`, `GITHUB_REF_NAME` | value | The commit and branch the report records under `run.vcs` when `git` cannot read the project root. `GITHUB_HEAD_REF` wins over `GITHUB_REF_NAME` |
|
|
56
63
|
|
|
@@ -100,6 +107,7 @@ What is sent and how to read it is on the [Telemetry](/telemetry) page.
|
|
|
100
107
|
| Variable | Reading | Effect |
|
|
101
108
|
| --- | --- | --- |
|
|
102
109
|
| `PLAYWRIGHT_BROWSERS_PATH` | value | Playwright's browser cache, honored by the engine's `prepare` hook |
|
|
110
|
+
| `PLAYWRIGHT_SKIP_BROWSER_GC` | value | Defaults to `1` for the engine's browser install, so it keeps other browsers in the cache. Set `0` to let the install remove them |
|
|
103
111
|
| `KERNEL_API_KEY` | value | The API key `kernel()` from `@e2e-dev/kernel` creates browsers with; unset, the browser lease fails. See [Kernel](/integrations/kernel) |
|
|
104
112
|
| `EXPO_TOKEN` | value | The Expo access token `easSimulators()` from `@e2e-dev/eas` starts and stops simulator sessions with; unset, it uses the eas-cli login in `.expo/state.json` under `HOME` (`USERPROFILE` on Windows), and with neither the device lease fails. See [EAS Simulators](/integrations/eas) |
|
|
105
113
|
| `HOME`, `USERPROFILE` | value | The home `easSimulators()` finds the eas-cli login under when `EXPO_TOKEN` is unset: `USERPROFILE` on Windows, `HOME` elsewhere, the OS user's home when unset |
|