e2e 0.15.1 → 0.16.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 +51 -24
- package/dist/.build.json +1 -1
- package/dist/agent/act-validation.d.ts +10 -1
- package/dist/agent/act-validation.js +48 -1
- package/dist/agent/act.d.ts +1 -2
- package/dist/agent/act.js +25 -8
- package/dist/agent/action-dispatcher.d.ts +0 -1
- package/dist/agent/action-dispatcher.js +0 -1
- package/dist/agent/action-names.d.ts +0 -1
- package/dist/agent/action-names.js +0 -1
- package/dist/agent/actions.d.ts +0 -1
- package/dist/agent/actions.js +0 -1
- package/dist/agent/agent-brand.d.ts +0 -1
- package/dist/agent/agent-brand.js +0 -1
- package/dist/agent/ai-sdk.d.ts +7 -1
- package/dist/agent/ai-sdk.js +11 -1
- package/dist/agent/call-options.d.ts +0 -1
- package/dist/agent/call-options.js +0 -1
- package/dist/agent/default-agent.d.ts +0 -1
- package/dist/agent/default-agent.js +0 -1
- package/dist/agent/derived.d.ts +0 -1
- package/dist/agent/derived.js +0 -1
- package/dist/agent/error.d.ts +16 -4
- package/dist/agent/error.js +25 -7
- package/dist/agent/executor.d.ts +0 -1
- package/dist/agent/executor.js +0 -1
- package/dist/agent/index.d.ts +0 -1
- package/dist/agent/index.js +0 -1
- package/dist/agent/interactive-step.d.ts +0 -1
- package/dist/agent/interactive-step.js +0 -1
- package/dist/agent/invocation.d.ts +0 -1
- package/dist/agent/invocation.js +10 -5
- package/dist/agent/ledger.d.ts +0 -1
- package/dist/agent/ledger.js +0 -1
- package/dist/agent/loop-guards.d.ts +0 -1
- package/dist/agent/loop-guards.js +0 -1
- package/dist/agent/model/adapter.d.ts +0 -1
- package/dist/agent/model/adapter.js +0 -1
- package/dist/agent/model/overflow.d.ts +0 -1
- package/dist/agent/model/overflow.js +0 -1
- package/dist/agent/model/provider-hints.d.ts +0 -1
- package/dist/agent/model/provider-hints.js +0 -1
- package/dist/agent/model/schema.d.ts +0 -1
- package/dist/agent/model/schema.js +0 -1
- package/dist/agent/model/sdk.d.ts +0 -1
- package/dist/agent/model/sdk.js +0 -1
- package/dist/agent/model/stall.d.ts +0 -1
- package/dist/agent/model/stall.js +0 -1
- package/dist/agent/model/tool-choice.d.ts +24 -2
- package/dist/agent/model/tool-choice.js +27 -2
- package/dist/agent/observation-budget.d.ts +0 -1
- package/dist/agent/observation-budget.js +0 -1
- package/dist/agent/observation-feed.d.ts +0 -1
- package/dist/agent/observation-feed.js +0 -1
- package/dist/agent/observation.d.ts +0 -1
- package/dist/agent/observation.js +0 -1
- package/dist/agent/operation-queue.d.ts +0 -1
- package/dist/agent/operation-queue.js +0 -1
- package/dist/agent/phases.d.ts +0 -1
- package/dist/agent/phases.js +0 -1
- package/dist/agent/pixels.d.ts +0 -1
- package/dist/agent/pixels.js +0 -1
- package/dist/agent/point-tap.d.ts +0 -1
- package/dist/agent/point-tap.js +0 -1
- package/dist/agent/primitives.d.ts +6 -1
- package/dist/agent/primitives.js +4 -2
- package/dist/agent/prompts.d.ts +0 -1
- package/dist/agent/prompts.js +0 -1
- package/dist/agent/protocol.d.ts +0 -1
- package/dist/agent/protocol.js +0 -1
- package/dist/agent/public.d.ts +0 -1
- package/dist/agent/public.js +0 -1
- package/dist/agent/reading.d.ts +0 -1
- package/dist/agent/reading.js +0 -1
- package/dist/agent/replay.d.ts +0 -1
- package/dist/agent/replay.js +0 -1
- package/dist/agent/screen-update.d.ts +0 -1
- package/dist/agent/screen-update.js +0 -1
- package/dist/agent/scroll-target.d.ts +0 -1
- package/dist/agent/scroll-target.js +0 -1
- package/dist/agent/secrets.d.ts +0 -1
- package/dist/agent/secrets.js +0 -1
- package/dist/agent/settle-policy.d.ts +0 -1
- package/dist/agent/settle-policy.js +0 -1
- package/dist/agent/step-accounting.d.ts +0 -1
- package/dist/agent/step-accounting.js +0 -1
- package/dist/agent/step-cache.d.ts +14 -4
- package/dist/agent/step-cache.js +13 -4
- package/dist/agent/tool-loop.d.ts +0 -1
- package/dist/agent/tool-loop.js +62 -10
- package/dist/agent/tool-output.d.ts +0 -1
- package/dist/agent/tool-output.js +0 -1
- package/dist/agent/tool.d.ts +0 -1
- package/dist/agent/tool.js +0 -1
- package/dist/agent/transcript-compaction.d.ts +0 -1
- package/dist/agent/transcript-compaction.js +0 -1
- package/dist/agent/upload-paths.d.ts +0 -1
- package/dist/agent/upload-paths.js +0 -1
- package/dist/agent/usage.d.ts +0 -1
- package/dist/agent/usage.js +0 -1
- package/dist/cache/anchors.d.ts +0 -1
- package/dist/cache/anchors.js +0 -1
- package/dist/cache/context.d.ts +19 -7
- package/dist/cache/context.js +15 -22
- package/dist/cache/decide.d.ts +0 -1
- package/dist/cache/decide.js +0 -1
- package/dist/cache/identity.d.ts +0 -1
- package/dist/cache/identity.js +0 -1
- package/dist/cache/recorder.d.ts +0 -1
- package/dist/cache/recorder.js +0 -1
- package/dist/cache/relocate.d.ts +0 -1
- package/dist/cache/relocate.js +0 -1
- package/dist/cache/route.d.ts +0 -1
- package/dist/cache/route.js +0 -1
- package/dist/cache/store.d.ts +0 -1
- package/dist/cache/store.js +0 -1
- package/dist/cache/template.d.ts +0 -1
- package/dist/cache/template.js +0 -1
- package/dist/cache/trace.d.ts +0 -1
- package/dist/cache/trace.js +0 -1
- package/dist/cli/bin.d.ts +0 -1
- package/dist/cli/bin.js +0 -1
- package/dist/cli/cache.d.ts +0 -1
- package/dist/cli/cache.js +0 -1
- package/dist/cli/docs-url.d.ts +0 -1
- package/dist/cli/docs-url.js +0 -1
- package/dist/cli/feedback.d.ts +0 -1
- package/dist/cli/feedback.js +0 -1
- package/dist/cli/guide.d.ts +0 -1
- package/dist/cli/guide.js +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +2 -3
- package/dist/cli/init/agent-skill.d.ts +0 -1
- package/dist/cli/init/agent-skill.js +0 -1
- package/dist/cli/init/engines.d.ts +0 -1
- package/dist/cli/init/engines.js +0 -1
- package/dist/cli/init/gateways.d.ts +0 -1
- package/dist/cli/init/gateways.js +0 -1
- package/dist/cli/init/mcp-config.d.ts +0 -1
- package/dist/cli/init/mcp-config.js +0 -1
- package/dist/cli/init/package.d.ts +0 -1
- package/dist/cli/init/package.js +0 -1
- package/dist/cli/init/scaffold.d.ts +1 -1
- package/dist/cli/init/scaffold.js +2 -2
- package/dist/cli/init/sibling-versions.json +1 -1
- package/dist/cli/init/versions.d.ts +0 -1
- package/dist/cli/init/versions.js +0 -1
- package/dist/cli/init.d.ts +0 -1
- package/dist/cli/init.js +0 -1
- package/dist/cli/mcp.d.ts +9 -2
- package/dist/cli/mcp.js +14 -2
- package/dist/cli/signals.d.ts +0 -1
- package/dist/cli/signals.js +0 -1
- package/dist/cli/skill.d.ts +0 -1
- package/dist/cli/skill.js +0 -1
- package/dist/cli/telemetry.d.ts +0 -1
- package/dist/cli/telemetry.js +1 -2
- package/dist/cli/wordmark.d.ts +0 -1
- package/dist/cli/wordmark.js +0 -1
- package/dist/collect/collect.d.ts +0 -1
- package/dist/collect/collect.js +3 -2
- package/dist/collect/registry.d.ts +6 -3
- package/dist/collect/registry.js +31 -14
- package/dist/collect/select.d.ts +0 -1
- package/dist/collect/select.js +0 -1
- package/dist/config/agent.d.ts +0 -1
- package/dist/config/agent.js +0 -1
- package/dist/config/app.d.ts +0 -1
- package/dist/config/app.js +0 -1
- package/dist/config/command.d.ts +0 -1
- package/dist/config/command.js +0 -1
- package/dist/config/diagnose.d.ts +0 -1
- package/dist/config/diagnose.js +0 -1
- package/dist/config/esm-hooks.d.ts +0 -1
- package/dist/config/esm-hooks.js +0 -1
- package/dist/config/load.d.ts +0 -1
- package/dist/config/load.js +0 -1
- package/dist/config/resolve.d.ts +0 -1
- package/dist/config/resolve.js +0 -1
- package/dist/config/secrets.d.ts +0 -1
- package/dist/config/secrets.js +0 -1
- package/dist/config/targets.d.ts +0 -1
- package/dist/config/targets.js +0 -1
- package/dist/config/validate.d.ts +0 -1
- package/dist/config/validate.js +0 -1
- package/dist/engine/contract.d.ts +0 -1
- package/dist/engine/contract.js +0 -1
- package/dist/engine/index.d.ts +1 -2
- package/dist/engine/index.js +4 -4
- package/dist/engine/manifest.d.ts +0 -1
- package/dist/engine/manifest.js +0 -1
- package/dist/engine/recording.d.ts +0 -1
- package/dist/engine/recording.js +0 -1
- package/dist/engine/resolve.d.ts +0 -1
- package/dist/engine/resolve.js +0 -1
- package/dist/engine/session.d.ts +0 -1
- package/dist/engine/session.js +0 -1
- package/dist/engine/surface.d.ts +0 -1
- package/dist/engine/surface.js +0 -1
- package/dist/engine/timing.d.ts +0 -1
- package/dist/engine/timing.js +0 -1
- package/dist/expect/async.d.ts +0 -1
- package/dist/expect/async.js +99 -58
- package/dist/expect/attempt.d.ts +0 -1
- package/dist/expect/attempt.js +0 -1
- package/dist/expect/index.d.ts +0 -1
- package/dist/expect/index.js +0 -1
- package/dist/expect/poll.d.ts +0 -1
- package/dist/expect/poll.js +0 -1
- package/dist/expect/soft.d.ts +0 -1
- package/dist/expect/soft.js +0 -1
- package/dist/expect/values.d.ts +0 -1
- package/dist/expect/values.js +1 -2
- package/dist/explore/body.d.ts +0 -1
- package/dist/explore/body.js +0 -1
- package/dist/explore/executor.d.ts +0 -1
- package/dist/explore/executor.js +0 -1
- package/dist/explore/index.d.ts +0 -1
- package/dist/explore/index.js +16 -2
- package/dist/explore/plan.d.ts +0 -1
- package/dist/explore/plan.js +0 -1
- package/dist/explore/progress.d.ts +0 -1
- package/dist/explore/progress.js +0 -1
- package/dist/explore/state.d.ts +0 -1
- package/dist/explore/state.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/internal/ai-trace.d.ts +0 -1
- package/dist/internal/ai-trace.js +0 -1
- package/dist/internal/atomic-write.d.ts +0 -1
- package/dist/internal/atomic-write.js +0 -1
- package/dist/internal/brands.d.ts +0 -1
- package/dist/internal/brands.js +0 -1
- package/dist/internal/debug.d.ts +0 -1
- package/dist/internal/debug.js +0 -1
- package/dist/internal/env.d.ts +0 -1
- package/dist/internal/env.js +0 -1
- package/dist/internal/errors.d.ts +0 -1
- package/dist/internal/errors.js +0 -1
- package/dist/internal/geometry.d.ts +0 -1
- package/dist/internal/geometry.js +0 -1
- package/dist/internal/git.d.ts +0 -1
- package/dist/internal/git.js +0 -1
- package/dist/internal/globs.d.ts +0 -1
- package/dist/internal/globs.js +0 -1
- package/dist/internal/ids.d.ts +0 -1
- package/dist/internal/ids.js +0 -1
- package/dist/internal/json-value.d.ts +0 -1
- package/dist/internal/json-value.js +0 -1
- package/dist/internal/keys.d.ts +0 -1
- package/dist/internal/keys.js +0 -1
- package/dist/internal/node-version.d.ts +0 -1
- package/dist/internal/node-version.js +0 -1
- package/dist/internal/objects.d.ts +0 -1
- package/dist/internal/objects.js +0 -1
- package/dist/internal/options.d.ts +0 -1
- package/dist/internal/options.js +0 -1
- package/dist/internal/package-manager.d.ts +0 -1
- package/dist/internal/package-manager.js +0 -1
- package/dist/internal/package-version.d.ts +0 -1
- package/dist/internal/package-version.js +0 -1
- package/dist/internal/paths.d.ts +0 -1
- package/dist/internal/paths.js +0 -1
- package/dist/internal/realm-slot.d.ts +0 -1
- package/dist/internal/realm-slot.js +0 -1
- package/dist/internal/recording-modes.d.ts +0 -1
- package/dist/internal/recording-modes.js +0 -1
- package/dist/internal/redact.d.ts +0 -1
- package/dist/internal/redact.js +0 -1
- package/dist/internal/regexp.d.ts +0 -1
- package/dist/internal/regexp.js +0 -1
- package/dist/internal/roles.d.ts +0 -1
- package/dist/internal/roles.js +0 -1
- package/dist/internal/skip.d.ts +0 -1
- package/dist/internal/skip.js +0 -1
- package/dist/internal/source.d.ts +0 -1
- package/dist/internal/source.js +0 -1
- package/dist/internal/standard-schema.d.ts +0 -1
- package/dist/internal/standard-schema.js +0 -1
- package/dist/internal/suggest.d.ts +0 -1
- package/dist/internal/suggest.js +0 -1
- package/dist/internal/text.d.ts +8 -1
- package/dist/internal/text.js +13 -2
- package/dist/internal/time.d.ts +0 -1
- package/dist/internal/time.js +0 -1
- package/dist/internal/urls.d.ts +0 -1
- package/dist/internal/urls.js +0 -1
- package/dist/internal/vcs.d.ts +0 -1
- package/dist/internal/vcs.js +0 -1
- package/dist/internal/zip.d.ts +0 -1
- package/dist/internal/zip.js +0 -1
- package/dist/locator/engine.d.ts +0 -1
- package/dist/locator/engine.js +0 -1
- package/dist/locator/expression.d.ts +0 -1
- package/dist/locator/expression.js +0 -1
- package/dist/locator/screen.d.ts +0 -1
- package/dist/locator/screen.js +0 -1
- package/dist/mcp/catalog.d.ts +4 -1
- package/dist/mcp/catalog.js +2 -3
- package/dist/mcp/config.d.ts +0 -1
- package/dist/mcp/config.js +0 -1
- package/dist/mcp/recording.d.ts +0 -1
- package/dist/mcp/recording.js +0 -1
- package/dist/mcp/server.d.ts +8 -1
- package/dist/mcp/server.js +8 -5
- package/dist/mcp/session.d.ts +4 -2
- package/dist/mcp/session.js +43 -21
- package/dist/mcp/sessions.d.ts +2 -1
- package/dist/mcp/sessions.js +5 -2
- package/dist/mcp/tools.d.ts +7 -6
- package/dist/mcp/tools.js +36 -11
- package/dist/mcp/usage.d.ts +61 -0
- package/dist/mcp/usage.js +73 -0
- package/dist/oauth/callback-server.d.ts +0 -1
- package/dist/oauth/callback-server.js +0 -1
- package/dist/oauth/chatgpt.d.ts +0 -1
- package/dist/oauth/chatgpt.js +0 -1
- package/dist/oauth/cli.d.ts +0 -1
- package/dist/oauth/cli.js +0 -1
- package/dist/oauth/copilot.d.ts +0 -1
- package/dist/oauth/copilot.js +0 -1
- package/dist/oauth/device-code.d.ts +0 -1
- package/dist/oauth/device-code.js +0 -1
- package/dist/oauth/errors.d.ts +0 -1
- package/dist/oauth/errors.js +0 -1
- package/dist/oauth/fetch.d.ts +0 -1
- package/dist/oauth/fetch.js +0 -1
- package/dist/oauth/grok.d.ts +0 -1
- package/dist/oauth/grok.js +0 -1
- package/dist/oauth/jwt.d.ts +0 -1
- package/dist/oauth/jwt.js +0 -1
- package/dist/oauth/login.d.ts +0 -1
- package/dist/oauth/login.js +0 -1
- package/dist/oauth/models.d.ts +0 -1
- package/dist/oauth/models.js +0 -1
- package/dist/oauth/pkce.d.ts +0 -1
- package/dist/oauth/pkce.js +0 -1
- package/dist/oauth/providers/github-copilot.d.ts +0 -1
- package/dist/oauth/providers/github-copilot.js +10 -3
- package/dist/oauth/providers/openai.d.ts +0 -1
- package/dist/oauth/providers/openai.js +1 -2
- package/dist/oauth/providers/xai.d.ts +0 -1
- package/dist/oauth/providers/xai.js +0 -1
- package/dist/oauth/providers.d.ts +0 -1
- package/dist/oauth/providers.js +0 -1
- package/dist/oauth/sse.d.ts +0 -1
- package/dist/oauth/sse.js +0 -1
- package/dist/oauth/store.d.ts +0 -1
- package/dist/oauth/store.js +0 -1
- package/dist/oauth/token-endpoint.d.ts +0 -1
- package/dist/oauth/token-endpoint.js +0 -1
- package/dist/oauth/types.d.ts +0 -1
- package/dist/oauth/types.js +0 -1
- package/dist/params.d.ts +0 -1
- package/dist/params.js +0 -1
- package/dist/report/build.d.ts +0 -1
- package/dist/report/build.js +0 -1
- package/dist/report/builtin.d.ts +0 -1
- package/dist/report/builtin.js +0 -1
- package/dist/report/code-frame.d.ts +0 -1
- package/dist/report/code-frame.js +0 -1
- package/dist/report/debug-steps.d.ts +0 -1
- package/dist/report/debug-steps.js +0 -1
- package/dist/report/explore-text.d.ts +0 -1
- package/dist/report/explore-text.js +0 -1
- package/dist/report/failure-text.d.ts +0 -1
- package/dist/report/failure-text.js +0 -1
- package/dist/report/format.d.ts +0 -1
- package/dist/report/format.js +0 -1
- package/dist/report/json.d.ts +0 -1
- package/dist/report/json.js +0 -1
- package/dist/report/junit.d.ts +0 -1
- package/dist/report/junit.js +0 -1
- package/dist/report/list-explore.d.ts +0 -1
- package/dist/report/list-explore.js +0 -1
- package/dist/report/list-model.d.ts +0 -1
- package/dist/report/list-model.js +0 -1
- package/dist/report/list-steps.d.ts +0 -1
- package/dist/report/list-steps.js +0 -1
- package/dist/report/list.d.ts +0 -1
- package/dist/report/list.js +0 -1
- package/dist/report/live-window.d.ts +0 -1
- package/dist/report/live-window.js +0 -1
- package/dist/report/markdown-text.d.ts +0 -1
- package/dist/report/markdown-text.js +0 -1
- package/dist/report/markdown.d.ts +0 -1
- package/dist/report/markdown.js +0 -1
- package/dist/report/outcome.d.ts +0 -1
- package/dist/report/outcome.js +0 -1
- package/dist/report/repeats.d.ts +0 -1
- package/dist/report/repeats.js +0 -1
- package/dist/report/running-tree.d.ts +0 -1
- package/dist/report/running-tree.js +0 -1
- package/dist/report/write.d.ts +0 -1
- package/dist/report/write.js +0 -1
- package/dist/run/app-ports.d.ts +0 -1
- package/dist/run/app-ports.js +0 -1
- package/dist/run/artifacts.d.ts +0 -1
- package/dist/run/artifacts.js +0 -1
- package/dist/run/budget.d.ts +0 -1
- package/dist/run/budget.js +0 -1
- package/dist/run/declared-processes.d.ts +0 -1
- package/dist/run/declared-processes.js +0 -1
- package/dist/run/events.d.ts +0 -1
- package/dist/run/events.js +0 -1
- package/dist/run/execute.d.ts +0 -1
- package/dist/run/execute.js +27 -13
- package/dist/run/extended-fixtures.d.ts +0 -1
- package/dist/run/extended-fixtures.js +0 -1
- package/dist/run/failure-evidence.d.ts +0 -1
- package/dist/run/failure-evidence.js +0 -1
- package/dist/run/fixture-recording.d.ts +0 -1
- package/dist/run/fixture-recording.js +0 -1
- package/dist/run/fixtures.d.ts +0 -1
- package/dist/run/fixtures.js +0 -1
- package/dist/run/in-process.d.ts +0 -1
- package/dist/run/in-process.js +0 -1
- package/dist/run/last-run.d.ts +0 -1
- package/dist/run/last-run.js +0 -1
- package/dist/run/managed-process.d.ts +0 -1
- package/dist/run/managed-process.js +0 -1
- package/dist/run/output.d.ts +0 -1
- package/dist/run/output.js +0 -1
- package/dist/run/process-pool.d.ts +0 -1
- package/dist/run/process-pool.js +0 -1
- package/dist/run/provision.d.ts +0 -1
- package/dist/run/provision.js +0 -1
- package/dist/run/realm.d.ts +2 -1
- package/dist/run/realm.js +1 -2
- package/dist/run/records.d.ts +0 -1
- package/dist/run/records.js +0 -1
- package/dist/run/retry.d.ts +0 -1
- package/dist/run/retry.js +0 -1
- package/dist/run/runner.d.ts +2 -1
- package/dist/run/runner.js +1 -2
- package/dist/run/scheduler.d.ts +0 -1
- package/dist/run/scheduler.js +0 -1
- package/dist/run/secrecy.d.ts +15 -1
- package/dist/run/secrecy.js +27 -2
- package/dist/run/serial.d.ts +0 -1
- package/dist/run/serial.js +0 -1
- package/dist/run/sessions.d.ts +0 -1
- package/dist/run/sessions.js +0 -1
- package/dist/run/standalone.d.ts +0 -1
- package/dist/run/standalone.js +3 -3
- package/dist/run/steps.d.ts +2 -3
- package/dist/run/steps.js +4 -2
- package/dist/run/trace-redaction.d.ts +0 -1
- package/dist/run/trace-redaction.js +0 -1
- package/dist/run/unit-runner.d.ts +0 -1
- package/dist/run/unit-runner.js +0 -1
- package/dist/run/units.d.ts +0 -1
- package/dist/run/units.js +0 -1
- package/dist/run/worker/entry.d.ts +0 -1
- package/dist/run/worker/entry.js +2 -3
- package/dist/run/worker/handle.d.ts +0 -1
- package/dist/run/worker/handle.js +0 -1
- package/dist/run/worker/protocol.d.ts +0 -1
- package/dist/run/worker/protocol.js +0 -1
- package/dist/run/worker/session.d.ts +0 -1
- package/dist/run/worker/session.js +0 -1
- package/dist/run/worker-models.d.ts +0 -1
- package/dist/run/worker-models.js +0 -1
- package/dist/secrets.d.ts +0 -1
- package/dist/secrets.js +0 -1
- package/dist/telemetry/checkout.d.ts +0 -1
- package/dist/telemetry/checkout.js +0 -1
- package/dist/telemetry/environment.d.ts +0 -1
- package/dist/telemetry/environment.js +0 -1
- package/dist/telemetry/events.d.ts +26 -10
- package/dist/telemetry/events.js +107 -13
- package/dist/telemetry/failure-kind.d.ts +0 -1
- package/dist/telemetry/failure-kind.js +0 -1
- package/dist/telemetry/posthog.d.ts +0 -1
- package/dist/telemetry/posthog.js +0 -1
- package/dist/telemetry/project.d.ts +0 -1
- package/dist/telemetry/project.js +0 -1
- package/dist/telemetry/store.d.ts +0 -1
- package/dist/telemetry/store.js +0 -1
- package/dist/telemetry/telemetry.d.ts +19 -8
- package/dist/telemetry/telemetry.js +26 -9
- package/dist/telemetry/token.d.ts +0 -1
- package/dist/telemetry/token.js +0 -1
- package/dist/types.d.ts +26 -24
- package/dist/types.js +0 -1
- package/docs/agent-steps.mdx +126 -0
- package/docs/agents.mdx +217 -0
- package/docs/api-testing.mdx +65 -0
- package/docs/authentication.mdx +345 -0
- package/docs/browser.mdx +440 -0
- package/docs/bug-bash.mdx +90 -0
- package/docs/cache.mdx +306 -0
- package/docs/ci.mdx +210 -0
- package/docs/coding-agents.mdx +183 -0
- package/docs/debugging.mdx +291 -0
- package/docs/executors.mdx +243 -0
- package/docs/explore.mdx +174 -0
- package/docs/github.mdx +184 -0
- package/docs/index.mdx +82 -0
- package/docs/integrations/eas.mdx +216 -0
- package/docs/integrations/index.mdx +24 -0
- package/docs/integrations/kernel.mdx +163 -0
- package/docs/migrate/cypress.mdx +124 -0
- package/docs/migrate/detox.mdx +140 -0
- package/docs/migrate/maestro.mdx +229 -0
- package/docs/migrate/playwright.mdx +430 -0
- package/docs/migrate/selenium.mdx +110 -0
- package/docs/mobile-ci.mdx +567 -0
- package/docs/mobile.mdx +595 -0
- package/docs/models.mdx +241 -0
- package/docs/quickstart.mdx +260 -0
- package/docs/reference/agent.mdx +524 -0
- package/docs/reference/app.mdx +72 -0
- package/docs/reference/cli.mdx +819 -0
- package/docs/reference/config.mdx +986 -0
- package/docs/reference/engine.mdx +1363 -0
- package/docs/reference/environment.mdx +113 -0
- package/docs/reference/errors.mdx +143 -0
- package/docs/reference/expect.mdx +546 -0
- package/docs/reference/mcp.mdx +205 -0
- package/docs/reference/mobile.mdx +522 -0
- package/docs/reference/reporters.mdx +216 -0
- package/docs/reference/screen.mdx +688 -0
- package/docs/reference/test.mdx +449 -0
- package/docs/reference/web.mdx +615 -0
- package/docs/security.mdx +308 -0
- package/docs/starting-your-app.mdx +231 -0
- package/docs/subscriptions.mdx +166 -0
- package/docs/telemetry.mdx +227 -0
- package/docs/tools.mdx +150 -0
- package/docs/viewports.mdx +146 -0
- package/docs/writing-an-engine.mdx +316 -0
- package/docs/writing-tests.mdx +256 -0
- package/package.json +5 -3
- package/skills/e2e/SKILL.md +4 -1
- package/skills/e2e/references/agent.md +3 -1
- package/skills/e2e/references/mcp.md +3 -0
- package/skills/e2e/references/setup.md +19 -4
- package/skills/e2e/references/writing-tests.md +11 -0
- package/dist/agent/act-validation.d.ts.map +0 -1
- package/dist/agent/act-validation.js.map +0 -1
- package/dist/agent/act.d.ts.map +0 -1
- package/dist/agent/act.js.map +0 -1
- package/dist/agent/action-dispatcher.d.ts.map +0 -1
- package/dist/agent/action-dispatcher.js.map +0 -1
- package/dist/agent/action-names.d.ts.map +0 -1
- package/dist/agent/action-names.js.map +0 -1
- package/dist/agent/actions.d.ts.map +0 -1
- package/dist/agent/actions.js.map +0 -1
- package/dist/agent/agent-brand.d.ts.map +0 -1
- package/dist/agent/agent-brand.js.map +0 -1
- package/dist/agent/ai-sdk.d.ts.map +0 -1
- package/dist/agent/ai-sdk.js.map +0 -1
- package/dist/agent/call-options.d.ts.map +0 -1
- package/dist/agent/call-options.js.map +0 -1
- package/dist/agent/default-agent.d.ts.map +0 -1
- package/dist/agent/default-agent.js.map +0 -1
- package/dist/agent/derived.d.ts.map +0 -1
- package/dist/agent/derived.js.map +0 -1
- package/dist/agent/error.d.ts.map +0 -1
- package/dist/agent/error.js.map +0 -1
- package/dist/agent/executor.d.ts.map +0 -1
- package/dist/agent/executor.js.map +0 -1
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/interactive-step.d.ts.map +0 -1
- package/dist/agent/interactive-step.js.map +0 -1
- package/dist/agent/invocation.d.ts.map +0 -1
- package/dist/agent/invocation.js.map +0 -1
- package/dist/agent/ledger.d.ts.map +0 -1
- package/dist/agent/ledger.js.map +0 -1
- package/dist/agent/loop-guards.d.ts.map +0 -1
- package/dist/agent/loop-guards.js.map +0 -1
- package/dist/agent/model/adapter.d.ts.map +0 -1
- package/dist/agent/model/adapter.js.map +0 -1
- package/dist/agent/model/overflow.d.ts.map +0 -1
- package/dist/agent/model/overflow.js.map +0 -1
- package/dist/agent/model/provider-hints.d.ts.map +0 -1
- package/dist/agent/model/provider-hints.js.map +0 -1
- package/dist/agent/model/schema.d.ts.map +0 -1
- package/dist/agent/model/schema.js.map +0 -1
- package/dist/agent/model/sdk.d.ts.map +0 -1
- package/dist/agent/model/sdk.js.map +0 -1
- package/dist/agent/model/stall.d.ts.map +0 -1
- package/dist/agent/model/stall.js.map +0 -1
- package/dist/agent/model/tool-choice.d.ts.map +0 -1
- package/dist/agent/model/tool-choice.js.map +0 -1
- package/dist/agent/observation-budget.d.ts.map +0 -1
- package/dist/agent/observation-budget.js.map +0 -1
- package/dist/agent/observation-feed.d.ts.map +0 -1
- package/dist/agent/observation-feed.js.map +0 -1
- package/dist/agent/observation.d.ts.map +0 -1
- package/dist/agent/observation.js.map +0 -1
- package/dist/agent/operation-queue.d.ts.map +0 -1
- package/dist/agent/operation-queue.js.map +0 -1
- package/dist/agent/phases.d.ts.map +0 -1
- package/dist/agent/phases.js.map +0 -1
- package/dist/agent/pixels.d.ts.map +0 -1
- package/dist/agent/pixels.js.map +0 -1
- package/dist/agent/point-tap.d.ts.map +0 -1
- package/dist/agent/point-tap.js.map +0 -1
- package/dist/agent/primitives.d.ts.map +0 -1
- package/dist/agent/primitives.js.map +0 -1
- package/dist/agent/prompts.d.ts.map +0 -1
- package/dist/agent/prompts.js.map +0 -1
- package/dist/agent/protocol.d.ts.map +0 -1
- package/dist/agent/protocol.js.map +0 -1
- package/dist/agent/public.d.ts.map +0 -1
- package/dist/agent/public.js.map +0 -1
- package/dist/agent/reading.d.ts.map +0 -1
- package/dist/agent/reading.js.map +0 -1
- package/dist/agent/replay.d.ts.map +0 -1
- package/dist/agent/replay.js.map +0 -1
- package/dist/agent/screen-update.d.ts.map +0 -1
- package/dist/agent/screen-update.js.map +0 -1
- package/dist/agent/scroll-target.d.ts.map +0 -1
- package/dist/agent/scroll-target.js.map +0 -1
- package/dist/agent/secrets.d.ts.map +0 -1
- package/dist/agent/secrets.js.map +0 -1
- package/dist/agent/settle-policy.d.ts.map +0 -1
- package/dist/agent/settle-policy.js.map +0 -1
- package/dist/agent/step-accounting.d.ts.map +0 -1
- package/dist/agent/step-accounting.js.map +0 -1
- package/dist/agent/step-cache.d.ts.map +0 -1
- package/dist/agent/step-cache.js.map +0 -1
- package/dist/agent/tool-loop.d.ts.map +0 -1
- package/dist/agent/tool-loop.js.map +0 -1
- package/dist/agent/tool-output.d.ts.map +0 -1
- package/dist/agent/tool-output.js.map +0 -1
- package/dist/agent/tool.d.ts.map +0 -1
- package/dist/agent/tool.js.map +0 -1
- package/dist/agent/transcript-compaction.d.ts.map +0 -1
- package/dist/agent/transcript-compaction.js.map +0 -1
- package/dist/agent/upload-paths.d.ts.map +0 -1
- package/dist/agent/upload-paths.js.map +0 -1
- package/dist/agent/usage.d.ts.map +0 -1
- package/dist/agent/usage.js.map +0 -1
- package/dist/cache/anchors.d.ts.map +0 -1
- package/dist/cache/anchors.js.map +0 -1
- package/dist/cache/context.d.ts.map +0 -1
- package/dist/cache/context.js.map +0 -1
- package/dist/cache/decide.d.ts.map +0 -1
- package/dist/cache/decide.js.map +0 -1
- package/dist/cache/identity.d.ts.map +0 -1
- package/dist/cache/identity.js.map +0 -1
- package/dist/cache/recorder.d.ts.map +0 -1
- package/dist/cache/recorder.js.map +0 -1
- package/dist/cache/relocate.d.ts.map +0 -1
- package/dist/cache/relocate.js.map +0 -1
- package/dist/cache/route.d.ts.map +0 -1
- package/dist/cache/route.js.map +0 -1
- package/dist/cache/store.d.ts.map +0 -1
- package/dist/cache/store.js.map +0 -1
- package/dist/cache/template.d.ts.map +0 -1
- package/dist/cache/template.js.map +0 -1
- package/dist/cache/trace.d.ts.map +0 -1
- package/dist/cache/trace.js.map +0 -1
- package/dist/cli/bin.d.ts.map +0 -1
- package/dist/cli/bin.js.map +0 -1
- package/dist/cli/cache.d.ts.map +0 -1
- package/dist/cli/cache.js.map +0 -1
- package/dist/cli/docs-url.d.ts.map +0 -1
- package/dist/cli/docs-url.js.map +0 -1
- package/dist/cli/feedback.d.ts.map +0 -1
- package/dist/cli/feedback.js.map +0 -1
- package/dist/cli/guide.d.ts.map +0 -1
- package/dist/cli/guide.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/init/agent-skill.d.ts.map +0 -1
- package/dist/cli/init/agent-skill.js.map +0 -1
- package/dist/cli/init/engines.d.ts.map +0 -1
- package/dist/cli/init/engines.js.map +0 -1
- package/dist/cli/init/gateways.d.ts.map +0 -1
- package/dist/cli/init/gateways.js.map +0 -1
- package/dist/cli/init/mcp-config.d.ts.map +0 -1
- package/dist/cli/init/mcp-config.js.map +0 -1
- package/dist/cli/init/package.d.ts.map +0 -1
- package/dist/cli/init/package.js.map +0 -1
- package/dist/cli/init/scaffold.d.ts.map +0 -1
- package/dist/cli/init/scaffold.js.map +0 -1
- package/dist/cli/init/versions.d.ts.map +0 -1
- package/dist/cli/init/versions.js.map +0 -1
- package/dist/cli/init.d.ts.map +0 -1
- package/dist/cli/init.js.map +0 -1
- package/dist/cli/mcp.d.ts.map +0 -1
- package/dist/cli/mcp.js.map +0 -1
- package/dist/cli/signals.d.ts.map +0 -1
- package/dist/cli/signals.js.map +0 -1
- package/dist/cli/skill.d.ts.map +0 -1
- package/dist/cli/skill.js.map +0 -1
- package/dist/cli/telemetry.d.ts.map +0 -1
- package/dist/cli/telemetry.js.map +0 -1
- package/dist/cli/wordmark.d.ts.map +0 -1
- package/dist/cli/wordmark.js.map +0 -1
- package/dist/collect/collect.d.ts.map +0 -1
- package/dist/collect/collect.js.map +0 -1
- package/dist/collect/registry.d.ts.map +0 -1
- package/dist/collect/registry.js.map +0 -1
- package/dist/collect/select.d.ts.map +0 -1
- package/dist/collect/select.js.map +0 -1
- package/dist/config/agent.d.ts.map +0 -1
- package/dist/config/agent.js.map +0 -1
- package/dist/config/app.d.ts.map +0 -1
- package/dist/config/app.js.map +0 -1
- package/dist/config/command.d.ts.map +0 -1
- package/dist/config/command.js.map +0 -1
- package/dist/config/diagnose.d.ts.map +0 -1
- package/dist/config/diagnose.js.map +0 -1
- package/dist/config/esm-hooks.d.ts.map +0 -1
- package/dist/config/esm-hooks.js.map +0 -1
- package/dist/config/load.d.ts.map +0 -1
- package/dist/config/load.js.map +0 -1
- package/dist/config/resolve.d.ts.map +0 -1
- package/dist/config/resolve.js.map +0 -1
- package/dist/config/secrets.d.ts.map +0 -1
- package/dist/config/secrets.js.map +0 -1
- package/dist/config/targets.d.ts.map +0 -1
- package/dist/config/targets.js.map +0 -1
- package/dist/config/validate.d.ts.map +0 -1
- package/dist/config/validate.js.map +0 -1
- package/dist/engine/contract.d.ts.map +0 -1
- package/dist/engine/contract.js.map +0 -1
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/manifest.d.ts.map +0 -1
- package/dist/engine/manifest.js.map +0 -1
- package/dist/engine/recording.d.ts.map +0 -1
- package/dist/engine/recording.js.map +0 -1
- package/dist/engine/resolve.d.ts.map +0 -1
- package/dist/engine/resolve.js.map +0 -1
- package/dist/engine/session.d.ts.map +0 -1
- package/dist/engine/session.js.map +0 -1
- package/dist/engine/surface.d.ts.map +0 -1
- package/dist/engine/surface.js.map +0 -1
- package/dist/engine/timing.d.ts.map +0 -1
- package/dist/engine/timing.js.map +0 -1
- package/dist/expect/async.d.ts.map +0 -1
- package/dist/expect/async.js.map +0 -1
- package/dist/expect/attempt.d.ts.map +0 -1
- package/dist/expect/attempt.js.map +0 -1
- package/dist/expect/index.d.ts.map +0 -1
- package/dist/expect/index.js.map +0 -1
- package/dist/expect/poll.d.ts.map +0 -1
- package/dist/expect/poll.js.map +0 -1
- package/dist/expect/soft.d.ts.map +0 -1
- package/dist/expect/soft.js.map +0 -1
- package/dist/expect/values.d.ts.map +0 -1
- package/dist/expect/values.js.map +0 -1
- package/dist/explore/body.d.ts.map +0 -1
- package/dist/explore/body.js.map +0 -1
- package/dist/explore/executor.d.ts.map +0 -1
- package/dist/explore/executor.js.map +0 -1
- package/dist/explore/index.d.ts.map +0 -1
- package/dist/explore/index.js.map +0 -1
- package/dist/explore/plan.d.ts.map +0 -1
- package/dist/explore/plan.js.map +0 -1
- package/dist/explore/progress.d.ts.map +0 -1
- package/dist/explore/progress.js.map +0 -1
- package/dist/explore/state.d.ts.map +0 -1
- package/dist/explore/state.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/ai-trace.d.ts.map +0 -1
- package/dist/internal/ai-trace.js.map +0 -1
- package/dist/internal/atomic-write.d.ts.map +0 -1
- package/dist/internal/atomic-write.js.map +0 -1
- package/dist/internal/brands.d.ts.map +0 -1
- package/dist/internal/brands.js.map +0 -1
- package/dist/internal/debug.d.ts.map +0 -1
- package/dist/internal/debug.js.map +0 -1
- package/dist/internal/env.d.ts.map +0 -1
- package/dist/internal/env.js.map +0 -1
- package/dist/internal/errors.d.ts.map +0 -1
- package/dist/internal/errors.js.map +0 -1
- package/dist/internal/geometry.d.ts.map +0 -1
- package/dist/internal/geometry.js.map +0 -1
- package/dist/internal/git.d.ts.map +0 -1
- package/dist/internal/git.js.map +0 -1
- package/dist/internal/globs.d.ts.map +0 -1
- package/dist/internal/globs.js.map +0 -1
- package/dist/internal/ids.d.ts.map +0 -1
- package/dist/internal/ids.js.map +0 -1
- package/dist/internal/json-value.d.ts.map +0 -1
- package/dist/internal/json-value.js.map +0 -1
- package/dist/internal/keys.d.ts.map +0 -1
- package/dist/internal/keys.js.map +0 -1
- package/dist/internal/node-version.d.ts.map +0 -1
- package/dist/internal/node-version.js.map +0 -1
- package/dist/internal/objects.d.ts.map +0 -1
- package/dist/internal/objects.js.map +0 -1
- package/dist/internal/options.d.ts.map +0 -1
- package/dist/internal/options.js.map +0 -1
- package/dist/internal/package-manager.d.ts.map +0 -1
- package/dist/internal/package-manager.js.map +0 -1
- package/dist/internal/package-version.d.ts.map +0 -1
- package/dist/internal/package-version.js.map +0 -1
- package/dist/internal/paths.d.ts.map +0 -1
- package/dist/internal/paths.js.map +0 -1
- package/dist/internal/realm-slot.d.ts.map +0 -1
- package/dist/internal/realm-slot.js.map +0 -1
- package/dist/internal/recording-modes.d.ts.map +0 -1
- package/dist/internal/recording-modes.js.map +0 -1
- package/dist/internal/redact.d.ts.map +0 -1
- package/dist/internal/redact.js.map +0 -1
- package/dist/internal/regexp.d.ts.map +0 -1
- package/dist/internal/regexp.js.map +0 -1
- package/dist/internal/roles.d.ts.map +0 -1
- package/dist/internal/roles.js.map +0 -1
- package/dist/internal/skip.d.ts.map +0 -1
- package/dist/internal/skip.js.map +0 -1
- package/dist/internal/source.d.ts.map +0 -1
- package/dist/internal/source.js.map +0 -1
- package/dist/internal/standard-schema.d.ts.map +0 -1
- package/dist/internal/standard-schema.js.map +0 -1
- package/dist/internal/suggest.d.ts.map +0 -1
- package/dist/internal/suggest.js.map +0 -1
- package/dist/internal/text.d.ts.map +0 -1
- package/dist/internal/text.js.map +0 -1
- package/dist/internal/time.d.ts.map +0 -1
- package/dist/internal/time.js.map +0 -1
- package/dist/internal/urls.d.ts.map +0 -1
- package/dist/internal/urls.js.map +0 -1
- package/dist/internal/vcs.d.ts.map +0 -1
- package/dist/internal/vcs.js.map +0 -1
- package/dist/internal/zip.d.ts.map +0 -1
- package/dist/internal/zip.js.map +0 -1
- package/dist/locator/engine.d.ts.map +0 -1
- package/dist/locator/engine.js.map +0 -1
- package/dist/locator/expression.d.ts.map +0 -1
- package/dist/locator/expression.js.map +0 -1
- package/dist/locator/screen.d.ts.map +0 -1
- package/dist/locator/screen.js.map +0 -1
- package/dist/mcp/catalog.d.ts.map +0 -1
- package/dist/mcp/catalog.js.map +0 -1
- package/dist/mcp/config.d.ts.map +0 -1
- package/dist/mcp/config.js.map +0 -1
- package/dist/mcp/recording.d.ts.map +0 -1
- package/dist/mcp/recording.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/session.d.ts.map +0 -1
- package/dist/mcp/session.js.map +0 -1
- package/dist/mcp/sessions.d.ts.map +0 -1
- package/dist/mcp/sessions.js.map +0 -1
- package/dist/mcp/tools.d.ts.map +0 -1
- package/dist/mcp/tools.js.map +0 -1
- package/dist/oauth/callback-server.d.ts.map +0 -1
- package/dist/oauth/callback-server.js.map +0 -1
- package/dist/oauth/chatgpt.d.ts.map +0 -1
- package/dist/oauth/chatgpt.js.map +0 -1
- package/dist/oauth/cli.d.ts.map +0 -1
- package/dist/oauth/cli.js.map +0 -1
- package/dist/oauth/copilot.d.ts.map +0 -1
- package/dist/oauth/copilot.js.map +0 -1
- package/dist/oauth/device-code.d.ts.map +0 -1
- package/dist/oauth/device-code.js.map +0 -1
- package/dist/oauth/errors.d.ts.map +0 -1
- package/dist/oauth/errors.js.map +0 -1
- package/dist/oauth/fetch.d.ts.map +0 -1
- package/dist/oauth/fetch.js.map +0 -1
- package/dist/oauth/grok.d.ts.map +0 -1
- package/dist/oauth/grok.js.map +0 -1
- package/dist/oauth/jwt.d.ts.map +0 -1
- package/dist/oauth/jwt.js.map +0 -1
- package/dist/oauth/login.d.ts.map +0 -1
- package/dist/oauth/login.js.map +0 -1
- package/dist/oauth/models.d.ts.map +0 -1
- package/dist/oauth/models.js.map +0 -1
- package/dist/oauth/pkce.d.ts.map +0 -1
- package/dist/oauth/pkce.js.map +0 -1
- package/dist/oauth/providers/github-copilot.d.ts.map +0 -1
- package/dist/oauth/providers/github-copilot.js.map +0 -1
- package/dist/oauth/providers/openai.d.ts.map +0 -1
- package/dist/oauth/providers/openai.js.map +0 -1
- package/dist/oauth/providers/xai.d.ts.map +0 -1
- package/dist/oauth/providers/xai.js.map +0 -1
- package/dist/oauth/providers.d.ts.map +0 -1
- package/dist/oauth/providers.js.map +0 -1
- package/dist/oauth/sse.d.ts.map +0 -1
- package/dist/oauth/sse.js.map +0 -1
- package/dist/oauth/store.d.ts.map +0 -1
- package/dist/oauth/store.js.map +0 -1
- package/dist/oauth/token-endpoint.d.ts.map +0 -1
- package/dist/oauth/token-endpoint.js.map +0 -1
- package/dist/oauth/types.d.ts.map +0 -1
- package/dist/oauth/types.js.map +0 -1
- package/dist/params.d.ts.map +0 -1
- package/dist/params.js.map +0 -1
- package/dist/report/build.d.ts.map +0 -1
- package/dist/report/build.js.map +0 -1
- package/dist/report/builtin.d.ts.map +0 -1
- package/dist/report/builtin.js.map +0 -1
- package/dist/report/code-frame.d.ts.map +0 -1
- package/dist/report/code-frame.js.map +0 -1
- package/dist/report/debug-steps.d.ts.map +0 -1
- package/dist/report/debug-steps.js.map +0 -1
- package/dist/report/explore-text.d.ts.map +0 -1
- package/dist/report/explore-text.js.map +0 -1
- package/dist/report/failure-text.d.ts.map +0 -1
- package/dist/report/failure-text.js.map +0 -1
- package/dist/report/format.d.ts.map +0 -1
- package/dist/report/format.js.map +0 -1
- package/dist/report/json.d.ts.map +0 -1
- package/dist/report/json.js.map +0 -1
- package/dist/report/junit.d.ts.map +0 -1
- package/dist/report/junit.js.map +0 -1
- package/dist/report/list-explore.d.ts.map +0 -1
- package/dist/report/list-explore.js.map +0 -1
- package/dist/report/list-model.d.ts.map +0 -1
- package/dist/report/list-model.js.map +0 -1
- package/dist/report/list-steps.d.ts.map +0 -1
- package/dist/report/list-steps.js.map +0 -1
- package/dist/report/list.d.ts.map +0 -1
- package/dist/report/list.js.map +0 -1
- package/dist/report/live-window.d.ts.map +0 -1
- package/dist/report/live-window.js.map +0 -1
- package/dist/report/markdown-text.d.ts.map +0 -1
- package/dist/report/markdown-text.js.map +0 -1
- package/dist/report/markdown.d.ts.map +0 -1
- package/dist/report/markdown.js.map +0 -1
- package/dist/report/outcome.d.ts.map +0 -1
- package/dist/report/outcome.js.map +0 -1
- package/dist/report/repeats.d.ts.map +0 -1
- package/dist/report/repeats.js.map +0 -1
- package/dist/report/running-tree.d.ts.map +0 -1
- package/dist/report/running-tree.js.map +0 -1
- package/dist/report/write.d.ts.map +0 -1
- package/dist/report/write.js.map +0 -1
- package/dist/run/app-ports.d.ts.map +0 -1
- package/dist/run/app-ports.js.map +0 -1
- package/dist/run/artifacts.d.ts.map +0 -1
- package/dist/run/artifacts.js.map +0 -1
- package/dist/run/budget.d.ts.map +0 -1
- package/dist/run/budget.js.map +0 -1
- package/dist/run/declared-processes.d.ts.map +0 -1
- package/dist/run/declared-processes.js.map +0 -1
- package/dist/run/events.d.ts.map +0 -1
- package/dist/run/events.js.map +0 -1
- package/dist/run/execute.d.ts.map +0 -1
- package/dist/run/execute.js.map +0 -1
- package/dist/run/extended-fixtures.d.ts.map +0 -1
- package/dist/run/extended-fixtures.js.map +0 -1
- package/dist/run/failure-evidence.d.ts.map +0 -1
- package/dist/run/failure-evidence.js.map +0 -1
- package/dist/run/fixture-recording.d.ts.map +0 -1
- package/dist/run/fixture-recording.js.map +0 -1
- package/dist/run/fixtures.d.ts.map +0 -1
- package/dist/run/fixtures.js.map +0 -1
- package/dist/run/in-process.d.ts.map +0 -1
- package/dist/run/in-process.js.map +0 -1
- package/dist/run/last-run.d.ts.map +0 -1
- package/dist/run/last-run.js.map +0 -1
- package/dist/run/managed-process.d.ts.map +0 -1
- package/dist/run/managed-process.js.map +0 -1
- package/dist/run/output.d.ts.map +0 -1
- package/dist/run/output.js.map +0 -1
- package/dist/run/process-pool.d.ts.map +0 -1
- package/dist/run/process-pool.js.map +0 -1
- package/dist/run/provision.d.ts.map +0 -1
- package/dist/run/provision.js.map +0 -1
- package/dist/run/realm.d.ts.map +0 -1
- package/dist/run/realm.js.map +0 -1
- package/dist/run/records.d.ts.map +0 -1
- package/dist/run/records.js.map +0 -1
- package/dist/run/retry.d.ts.map +0 -1
- package/dist/run/retry.js.map +0 -1
- package/dist/run/runner.d.ts.map +0 -1
- package/dist/run/runner.js.map +0 -1
- package/dist/run/scheduler.d.ts.map +0 -1
- package/dist/run/scheduler.js.map +0 -1
- package/dist/run/secrecy.d.ts.map +0 -1
- package/dist/run/secrecy.js.map +0 -1
- package/dist/run/serial.d.ts.map +0 -1
- package/dist/run/serial.js.map +0 -1
- package/dist/run/sessions.d.ts.map +0 -1
- package/dist/run/sessions.js.map +0 -1
- package/dist/run/standalone.d.ts.map +0 -1
- package/dist/run/standalone.js.map +0 -1
- package/dist/run/steps.d.ts.map +0 -1
- package/dist/run/steps.js.map +0 -1
- package/dist/run/trace-redaction.d.ts.map +0 -1
- package/dist/run/trace-redaction.js.map +0 -1
- package/dist/run/unit-runner.d.ts.map +0 -1
- package/dist/run/unit-runner.js.map +0 -1
- package/dist/run/units.d.ts.map +0 -1
- package/dist/run/units.js.map +0 -1
- package/dist/run/worker/entry.d.ts.map +0 -1
- package/dist/run/worker/entry.js.map +0 -1
- package/dist/run/worker/handle.d.ts.map +0 -1
- package/dist/run/worker/handle.js.map +0 -1
- package/dist/run/worker/protocol.d.ts.map +0 -1
- package/dist/run/worker/protocol.js.map +0 -1
- package/dist/run/worker/session.d.ts.map +0 -1
- package/dist/run/worker/session.js.map +0 -1
- package/dist/run/worker-models.d.ts.map +0 -1
- package/dist/run/worker-models.js.map +0 -1
- package/dist/secrets.d.ts.map +0 -1
- package/dist/secrets.js.map +0 -1
- package/dist/telemetry/checkout.d.ts.map +0 -1
- package/dist/telemetry/checkout.js.map +0 -1
- package/dist/telemetry/environment.d.ts.map +0 -1
- package/dist/telemetry/environment.js.map +0 -1
- package/dist/telemetry/events.d.ts.map +0 -1
- package/dist/telemetry/events.js.map +0 -1
- package/dist/telemetry/failure-kind.d.ts.map +0 -1
- package/dist/telemetry/failure-kind.js.map +0 -1
- package/dist/telemetry/posthog.d.ts.map +0 -1
- package/dist/telemetry/posthog.js.map +0 -1
- package/dist/telemetry/project.d.ts.map +0 -1
- package/dist/telemetry/project.js.map +0 -1
- package/dist/telemetry/store.d.ts.map +0 -1
- package/dist/telemetry/store.js.map +0 -1
- package/dist/telemetry/telemetry.d.ts.map +0 -1
- package/dist/telemetry/telemetry.js.map +0 -1
- package/dist/telemetry/token.d.ts.map +0 -1
- package/dist/telemetry/token.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Kernel browsers
|
|
3
|
+
sidebarTitle: Kernel
|
|
4
|
+
description: Run web targets in Kernel's hosted Chromium with the kernel() browser provider from @e2e-dev/kernel.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`kernel()` from `@e2e-dev/kernel` is a
|
|
8
|
+
[browser provider](/browser#hosted-browsers) for [Kernel](https://kernel.sh).
|
|
9
|
+
By default each worker slot gets its own hosted Chromium, created when the run
|
|
10
|
+
starts and deleted when it ends; `scope: 'attempt'` leases one per test
|
|
11
|
+
attempt instead. Tests and CI stay the same; the config changes only in the
|
|
12
|
+
target's `browser`.
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
<CodeGroup>
|
|
17
|
+
```bash npm
|
|
18
|
+
npm install --save-dev @e2e-dev/kernel @onkernel/sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```bash pnpm
|
|
22
|
+
pnpm add -D @e2e-dev/kernel @onkernel/sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```bash bun
|
|
26
|
+
bun add -d @e2e-dev/kernel @onkernel/sdk
|
|
27
|
+
```
|
|
28
|
+
</CodeGroup>
|
|
29
|
+
|
|
30
|
+
```ts title="e2e.config.ts"
|
|
31
|
+
import type { E2EConfig } from 'e2e';
|
|
32
|
+
import { web } from '@e2e-dev/web';
|
|
33
|
+
import { kernel } from '@e2e-dev/kernel';
|
|
34
|
+
|
|
35
|
+
export default {
|
|
36
|
+
targets: [
|
|
37
|
+
{
|
|
38
|
+
name: 'kernel',
|
|
39
|
+
engine: web({ browser: kernel() }),
|
|
40
|
+
app: { url: 'https://staging.example.com' },
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
} satisfies E2EConfig;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Set `KERNEL_API_KEY` in the environment `e2e run` starts in, such as a CI
|
|
47
|
+
secret. Each worker gets its own browser, so `workers` sets how many run at
|
|
48
|
+
once.
|
|
49
|
+
|
|
50
|
+
## Fill the screen
|
|
51
|
+
|
|
52
|
+
Size the screen with Kernel's `viewport` and set the web engine's
|
|
53
|
+
`viewport: null` so the page takes the window's size:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
web({
|
|
57
|
+
browser: kernel({ viewport: { width: 1920, height: 1080 } }),
|
|
58
|
+
viewport: null,
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Each attempt's window then opens maximized, and the page
|
|
63
|
+
[fills it](/viewports#fill-the-window): 1920 by 993 on a 1920 by 1080 screen,
|
|
64
|
+
after the tab strip and address bar. With a fixed web `viewport`, the page is
|
|
65
|
+
emulated at that size inside a smaller window, so Kernel's live view shows it
|
|
66
|
+
cut off or in part of the window.
|
|
67
|
+
|
|
68
|
+
## Options
|
|
69
|
+
|
|
70
|
+
`kernel(options)` takes Kernel's create-browser body as is: `stealth`,
|
|
71
|
+
`headless`, `timeout_seconds`, `profile`, `proxy_id`, `proxy`, `viewport`,
|
|
72
|
+
`extensions`, `region`, `tags`, and the rest of `BrowserCreateParams` in the
|
|
73
|
+
`@onkernel/sdk` you installed. On top of that:
|
|
74
|
+
|
|
75
|
+
| Option | Default | Meaning |
|
|
76
|
+
| -------- | ---------- | ------- |
|
|
77
|
+
| `scope` | `'worker'` | `'worker'`: one browser per worker slot for the run. `'attempt'`: a fresh browser per test attempt, retries included. See [Scopes](#scopes). |
|
|
78
|
+
| `replay` | `true` | How an attempt that records video is recorded. `true`, or Kernel's start-replay body (`framerate`, `max_duration_in_seconds`, `record_audio`): a Kernel replay of the browser's screen. `false`: the web engine's screencast of the page. See [Recordings](#recordings). |
|
|
79
|
+
|
|
80
|
+
## Scopes
|
|
81
|
+
|
|
82
|
+
`scope: 'worker'` keeps one browser per worker slot for the whole run and
|
|
83
|
+
gives every attempt a new browser context on it, as a local run does: a test
|
|
84
|
+
never sees another test's cookies, storage, or permissions. Kernel's initial
|
|
85
|
+
tab stays open behind the attempts' windows. A context the engine creates
|
|
86
|
+
does not share the browser's default context, so a Kernel `profile`'s saved
|
|
87
|
+
cookies and storage are not there.
|
|
88
|
+
|
|
89
|
+
`scope: 'attempt'` leases a fresh browser per attempt and runs the attempt in
|
|
90
|
+
that browser's default context, on its own first tab, so a `profile` applies
|
|
91
|
+
and the live view shows one tab. It costs a browser start per test and
|
|
92
|
+
carries the limits of a [per-attempt lease](/browser#hosted-browsers): no
|
|
93
|
+
`headers`, `basicAuth`, or `userAgent`, no `app.clearState()`, and no
|
|
94
|
+
[sessions](/authentication), which fail the run before any test.
|
|
95
|
+
|
|
96
|
+
## Recordings
|
|
97
|
+
|
|
98
|
+
An attempt that records [video](/reference/config#video) gets a Kernel
|
|
99
|
+
replay of the browser's screen, saved as `video/replay.mp4` under the
|
|
100
|
+
attempt's artifact directory. The replay shows the whole window, tabs and
|
|
101
|
+
address bar included, where the web engine's screencast shows only the page.
|
|
102
|
+
|
|
103
|
+
```ts title="e2e.config.ts"
|
|
104
|
+
export default {
|
|
105
|
+
targets: [
|
|
106
|
+
{
|
|
107
|
+
name: 'kernel',
|
|
108
|
+
engine: web({ browser: kernel(), viewport: null }),
|
|
109
|
+
app: { url: 'https://staging.example.com' },
|
|
110
|
+
video: 'retain-on-failure',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
} satisfies E2EConfig;
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
A test's own `video` overrides the target's, so one flow can keep its
|
|
117
|
+
recording even when it passes:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
test('checkout', { video: 'on' }, async ({ agent }) => {
|
|
121
|
+
await agent.act('Buy the first product in the catalog');
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
A replay has the screen's size, which Kernel's `viewport` sets, at Kernel's
|
|
126
|
+
default frame rate, 10 fps. Pass Kernel's start-replay body to change it:
|
|
127
|
+
`kernel({ replay: { framerate: 20, max_duration_in_seconds: 600 } })`. A
|
|
128
|
+
`framerate` above 20 needs `gpu: true` on the browser.
|
|
129
|
+
|
|
130
|
+
Kernel replays headed browsers only, its default. With `headless: true`, or
|
|
131
|
+
`replay: false`, the provider does not record, and the web engine records
|
|
132
|
+
its screencast of the page instead, as it does for a local browser.
|
|
133
|
+
|
|
134
|
+
## Downloads
|
|
135
|
+
|
|
136
|
+
`browser.waitForDownload` works as it does locally. Each browser saves downloads
|
|
137
|
+
under `/tmp/e2e-downloads` on its own disk, and the provider reads the
|
|
138
|
+
finished file back through Kernel's browser filesystem API into the
|
|
139
|
+
attempt's artifacts, in both scopes.
|
|
140
|
+
|
|
141
|
+
## What the provider does
|
|
142
|
+
|
|
143
|
+
- Tags every browser `e2e_run`, `e2e_target`, `e2e_slot`, and, per attempt,
|
|
144
|
+
`e2e_attempt`, merged over the `tags` you pass, so a session in Kernel's
|
|
145
|
+
dashboard names the run that started it.
|
|
146
|
+
- Deletes, when the run ends, every browser still active with the run's
|
|
147
|
+
`e2e_run` and `e2e_target` tags: the browser of a worker that died
|
|
148
|
+
mid-attempt, in either scope, is released with the run rather than left
|
|
149
|
+
running.
|
|
150
|
+
- Defaults `timeout_seconds` to 600, the backstop for a run that dies
|
|
151
|
+
itself before it can delete its browsers: Kernel deletes an idle browser
|
|
152
|
+
after that long. Pass your own to change it.
|
|
153
|
+
- Logs `browser <id>, watch at <live view URL>` to the reporter as each
|
|
154
|
+
browser is created: at the start of the run in `worker` scope, and from
|
|
155
|
+
the worker for each attempt's browser in `attempt` scope and for a
|
|
156
|
+
replacement after a browser dropped.
|
|
157
|
+
- Deletes a browser that arrives after its request was cancelled, and treats
|
|
158
|
+
one Kernel no longer knows as already deleted.
|
|
159
|
+
|
|
160
|
+
A missing `KERNEL_API_KEY` or a Kernel error fails the lease with that
|
|
161
|
+
message. In `worker` scope that ends the run before any test, and the
|
|
162
|
+
browsers other slots got are still deleted; in `attempt` scope it fails the
|
|
163
|
+
attempt.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: From Cypress
|
|
3
|
+
description: Replace Cypress command chains with async tests and keep your data-cy attributes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
e2e tests run in Node. Use `await` for UI actions and call Node functions
|
|
7
|
+
directly for work previously handled by `cy.task`. Both suites can stay in
|
|
8
|
+
the project while you migrate one spec at a time.
|
|
9
|
+
|
|
10
|
+
Start with the [quickstart](/quickstart) to install e2e and configure a model
|
|
11
|
+
for the agent calls shown below.
|
|
12
|
+
|
|
13
|
+
## Config
|
|
14
|
+
|
|
15
|
+
| Cypress | e2e |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `baseUrl` | `app: { url }` on the target |
|
|
18
|
+
| `start-server-and-test` | `app: { url, command }`, see [Starting your app](/starting-your-app) |
|
|
19
|
+
| `viewportWidth`, `viewportHeight` | `web({ viewport })` |
|
|
20
|
+
| `data-cy` selectors | `web({ testIdAttribute: 'data-cy' })`, then `screen.getByTestId` |
|
|
21
|
+
| `retries` | `retries` |
|
|
22
|
+
| `env`, `Cypress.env()` | `process.env` |
|
|
23
|
+
| `cypress.env.json` secrets | `credentials` and `secrets`, see [Signing in](/authentication) |
|
|
24
|
+
| `cypress run --browser firefox` | A second target with `browser: 'firefox'` |
|
|
25
|
+
| Component testing | No equivalent |
|
|
26
|
+
|
|
27
|
+
```ts title="e2e.config.ts"
|
|
28
|
+
import type { E2EConfig } from 'e2e';
|
|
29
|
+
import { web } from '@e2e-dev/web';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
targets: [{
|
|
33
|
+
engine: web({ testIdAttribute: 'data-cy' }),
|
|
34
|
+
app: { url: 'http://localhost:3000' },
|
|
35
|
+
}],
|
|
36
|
+
} satisfies E2EConfig;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## A test, before and after
|
|
40
|
+
|
|
41
|
+
```js title="Cypress"
|
|
42
|
+
describe('todos', () => {
|
|
43
|
+
it('completes one', () => {
|
|
44
|
+
cy.visit('/todos');
|
|
45
|
+
cy.get('[data-cy=new-todo]').type('Buy milk{enter}');
|
|
46
|
+
cy.get('[data-cy=new-todo]').type('Walk the dog{enter}');
|
|
47
|
+
cy.contains('li', 'Buy milk').find('[data-cy=toggle]').click();
|
|
48
|
+
cy.get('[data-cy=todo]').should('have.length', 2);
|
|
49
|
+
cy.contains('1 item left').should('be.visible');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ts title="e2e"
|
|
55
|
+
import { describe, test } from '@e2e-dev/web';
|
|
56
|
+
import { expect } from 'e2e';
|
|
57
|
+
|
|
58
|
+
describe('todos', () => {
|
|
59
|
+
test('completes one', async ({ app, agent, screen }) => {
|
|
60
|
+
await app.open('/todos');
|
|
61
|
+
await agent.act('add todos "Buy milk" and "Walk the dog", then complete "Buy milk"');
|
|
62
|
+
await expect(screen.getByTestId('todo')).toHaveCount(2);
|
|
63
|
+
await expect(screen.getByText('1 item left')).toBeVisible();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API map
|
|
69
|
+
|
|
70
|
+
| Cypress | e2e |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `cy.visit(path)` | `app.open(path)` |
|
|
73
|
+
| `cy.get('[data-cy=x]')` | `screen.getByTestId('x')` |
|
|
74
|
+
| `cy.get('css')` | `browser.locator('css')`, not portable; prefer a role or label |
|
|
75
|
+
| `cy.contains('text')` | `screen.getByText('text', { exact: false })` |
|
|
76
|
+
| `cy.contains('li', 'text')` | `screen.getByRole('listitem').filter({ hasText: 'text' })` |
|
|
77
|
+
| `.find()`, `.within()` | Chain a query off the locator: `row.getByRole(...)` |
|
|
78
|
+
| `.first()`, `.eq(n)` | `.first()`, `.nth(n)` |
|
|
79
|
+
| `.click()`, `.dblclick()`, `.rightclick()` | `.tap()`, `.doubleTap()`, `.secondaryTap()` |
|
|
80
|
+
| `.type('text')` | `.fill('text')` replaces the content |
|
|
81
|
+
| `.type('{enter}')` | `.press('Enter')` |
|
|
82
|
+
| `.clear()`, `.check()`, `.select()` | `.clear()`, `.check()`, `.selectOption()` |
|
|
83
|
+
| `.selectFile()` | `.setInputFiles()` |
|
|
84
|
+
| `.should('be.visible')` | `await expect(locator).toBeVisible()` |
|
|
85
|
+
| `.should('have.text', t)`, `.should('contain', t)` | `.toHaveText(t)`, `.toContainText(t)` |
|
|
86
|
+
| `.should('have.length', n)` | `.toHaveCount(n)` |
|
|
87
|
+
| `.should('have.value', v)` | `.toHaveValue(v)` |
|
|
88
|
+
| `.should('not.exist')` | `.toHaveCount(0)`; `toBeHidden()` also accepts a node that is still in the DOM |
|
|
89
|
+
| `cy.url().should('include', p)` | `expect(browser).toHaveURL(/p/)` |
|
|
90
|
+
| `cy.title()` | `expect(browser).toHaveTitle()` |
|
|
91
|
+
| `cy.intercept(url, body)` | `browser.route(url, route => route.fulfill({ json: body }))` |
|
|
92
|
+
| `cy.wait('@alias')` | `browser.waitForResponse(url)` |
|
|
93
|
+
| `cy.on('window:confirm')` | `browser.onDialog('accept')` |
|
|
94
|
+
| `cy.window()`, `cy.document()` | `browser.evaluate(() => ...)` |
|
|
95
|
+
| `cy.setCookie` | `browser.setCookies` |
|
|
96
|
+
| `cy.viewport` | `browser.setViewport` |
|
|
97
|
+
| `cy.session` | `test.setup` and `{ session }` |
|
|
98
|
+
| `cy.task`, `cy.exec`, `cy.request` | Node code: `fetch`, `fs`, your database client |
|
|
99
|
+
| `cy.fixture` | `import data from './fixture.json'` |
|
|
100
|
+
| `Cypress.Commands.add` | A function, or a fixture from `test.extend` |
|
|
101
|
+
| `cy.wait(ms)` | Use a locator assertion for the condition you need |
|
|
102
|
+
| `cypress open` | `npx e2e run --headed`, plus `--debug` for the step table |
|
|
103
|
+
|
|
104
|
+
Where the behavior differs from Cypress's:
|
|
105
|
+
|
|
106
|
+
- There is no chain. Each command is awaited on its own line and returns a
|
|
107
|
+
value, so `const text = await locator.textContent()` works.
|
|
108
|
+
- Actions and single-node reads or assertions need one match; several fail
|
|
109
|
+
with `LOCATOR_AMBIGUOUS`. Narrow with `.filter()`, `.first()`, or `.nth()`,
|
|
110
|
+
see [screen](/reference/screen).
|
|
111
|
+
|
|
112
|
+
## What to migrate first
|
|
113
|
+
|
|
114
|
+
Start with a spec that often breaks and whose fixed `cy.wait` calls can
|
|
115
|
+
become assertions on the condition the test needs.
|
|
116
|
+
|
|
117
|
+
<CardGroup cols={2}>
|
|
118
|
+
<Card title="Writing tests" icon="pen-to-square" href="/writing-tests">
|
|
119
|
+
Goals, checks, extraction, and the deterministic APIs.
|
|
120
|
+
</Card>
|
|
121
|
+
<Card title="Working with the browser" icon="globe" href="/browser">
|
|
122
|
+
Routes, dialogs, downloads, iframes, and page evaluation.
|
|
123
|
+
</Card>
|
|
124
|
+
</CardGroup>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: From Detox
|
|
3
|
+
description: Use your existing app build and testIDs with screen, expect, and agent goals.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`@e2e-dev/mobile` drives a simulator or emulator using your normal debug
|
|
7
|
+
or release build. It does not need the Detox framework. React Native
|
|
8
|
+
`testID` props work with `getByTestId` on both platforms.
|
|
9
|
+
|
|
10
|
+
Set up a target with the [mobile guide](/mobile) and a model with the
|
|
11
|
+
[quickstart](/quickstart). You can use the same simulator for each runner
|
|
12
|
+
while migrating one spec at a time.
|
|
13
|
+
|
|
14
|
+
## Config
|
|
15
|
+
|
|
16
|
+
| Detox (`.detoxrc.js`) | e2e |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `apps.<name>.binaryPath` | `app: { appPath }` on the target plus one `device.installApp()` per device in a fixture; the engine installs nothing on its own |
|
|
19
|
+
| `apps.<name>.bundleId` | `app: { bundleId: 'com.example.app' }` on the target, the app `app.open()` launches |
|
|
20
|
+
| `devices.<name>.device.type` | `mobile({ device: 'iPhone 17' })` |
|
|
21
|
+
| `configurations` | `targets`, one engine per platform |
|
|
22
|
+
| Jest config, `maxWorkers` | `workers`, one per device |
|
|
23
|
+
| `detox build` | Your normal build. No Detox framework, no `detox build` step |
|
|
24
|
+
| `device.launchApp({ permissions })` | `app.permissions` on the target, set before every fresh launch, or `device.openApp(app, { relaunch: true, permissions })` for one; `grant`, `deny`, `reset` for `YES`, `NO`, `unset` |
|
|
25
|
+
| `device.launchApp({ launchArgs })` | `app.launchArguments` on the target, or `device.openApp(app, { relaunch: true, launchArguments })` for one; a list of strings the platform launch command takes, not a map |
|
|
26
|
+
|
|
27
|
+
```ts title="e2e.config.ts"
|
|
28
|
+
import type { E2EConfig } from 'e2e';
|
|
29
|
+
import { mobile } from '@e2e-dev/mobile';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
targets: [
|
|
33
|
+
{
|
|
34
|
+
name: 'ios',
|
|
35
|
+
engine: mobile({ platform: 'ios' }),
|
|
36
|
+
app: { bundleId: 'com.example.app', appPath: 'ios/build/MyApp.app' },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'android',
|
|
40
|
+
engine: mobile({ platform: 'android' }),
|
|
41
|
+
app: { bundleId: 'com.example.app', appPath: 'android/app/build/outputs/apk/debug/app-debug.apk' },
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
workers: 1,
|
|
45
|
+
} satisfies E2EConfig;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## A test, before and after
|
|
49
|
+
|
|
50
|
+
```js title="Detox"
|
|
51
|
+
describe('login', () => {
|
|
52
|
+
beforeAll(async () => { await device.launchApp({ newInstance: true }); });
|
|
53
|
+
|
|
54
|
+
it('shows the home screen', async () => {
|
|
55
|
+
await element(by.id('email')).typeText('ada@example.test');
|
|
56
|
+
await element(by.id('password')).typeText('hunter2');
|
|
57
|
+
await element(by.text('Sign in')).tap();
|
|
58
|
+
await waitFor(element(by.id('home'))).toBeVisible().withTimeout(10000);
|
|
59
|
+
await expect(element(by.text('Welcome, Ada'))).toBeVisible();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```ts title="e2e"
|
|
65
|
+
import { test } from '@e2e-dev/mobile';
|
|
66
|
+
import { expect, credentials } from 'e2e';
|
|
67
|
+
|
|
68
|
+
test('shows the home screen', async ({ agent, app, screen }) => {
|
|
69
|
+
await app.open();
|
|
70
|
+
const ada = credentials.user('ada');
|
|
71
|
+
await agent.act('sign in as {username}', { params: { username: ada.username, password: ada.password } });
|
|
72
|
+
await expect(screen.getByTestId('home')).toBeVisible({ timeout: 10_000 });
|
|
73
|
+
await expect(screen.getByText('Welcome, Ada')).toBeVisible();
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`app.open()` launches the configured app fresh; nothing launches on its own.
|
|
78
|
+
The password comes from [configured credentials](/authentication).
|
|
79
|
+
|
|
80
|
+
## API map
|
|
81
|
+
|
|
82
|
+
| Detox | e2e |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `by.id('x')` | `screen.getByTestId('x')` |
|
|
85
|
+
| `by.text('t')` | `screen.getByText('t')` |
|
|
86
|
+
| `by.label('l')` | `screen.getByLabel('l')` |
|
|
87
|
+
| `by.type('RCTImageView')` | `device.locator('role=Image')`, agent-device's selector syntax |
|
|
88
|
+
| `by.id('x').withAncestor(by.id('row'))` | `screen.getByTestId('row').getByTestId('x')` |
|
|
89
|
+
| `.atIndex(n)` | `.nth(n)` |
|
|
90
|
+
| `.tap()`, `.multiTap(2)`, `.longPress()` | `.tap()`, `.doubleTap()`, `.longPress()` |
|
|
91
|
+
| `.tap({ x, y })` | `.tap({ position: { x, y } })` |
|
|
92
|
+
| `.typeText(t)`, `.replaceText(t)` | `.fill(t)` replaces the content |
|
|
93
|
+
| `.clearText()` | `.clear()` |
|
|
94
|
+
| `.tapReturnKey()` | `.press('Enter')` |
|
|
95
|
+
| `.swipe('up', 'fast')` | `.swipe({ direction: 'down', momentum: 'fast' })`: Detox names the finger's direction, e2e the content's |
|
|
96
|
+
| `.scroll(200, 'down')` | `screen.swipe({ direction: 'down' })` |
|
|
97
|
+
| `waitFor(el).toBeVisible().whileElement(list).scroll(...)` | `screen.scrollUntilVisible(el)` |
|
|
98
|
+
| `waitFor(el).toBeVisible().withTimeout(ms)` | `await expect(el).toBeVisible({ timeout: ms })` |
|
|
99
|
+
| `expect(el).toBeVisible()`, `.toExist()` | `.toBeVisible()` for visibility; `.toHaveCount(1)` for existence |
|
|
100
|
+
| `expect(el).not.toBeVisible()` | `.toBeHidden()` |
|
|
101
|
+
| `expect(el).toHaveText(t)` | `.toHaveText(t)` |
|
|
102
|
+
| `expect(el).toHaveToggleValue(true)` | `.toBeChecked()` |
|
|
103
|
+
| `expect(el).toHaveValue(v)` | `.toHaveValue(v)` |
|
|
104
|
+
| `device.launchApp({ newInstance: true })` | `app.restart()` |
|
|
105
|
+
| `device.launchApp({ delete: true })` | `app.clearState()` |
|
|
106
|
+
| `device.reloadReactNative()` | No equivalent. `app.restart()` is the nearest |
|
|
107
|
+
| `device.sendToHome()`, `device.pressBack()` | `device.home()`, `device.back()` |
|
|
108
|
+
| `device.setLocation(lat, lon)` | `device.setLocation({ latitude, longitude })` |
|
|
109
|
+
| `device.setOrientation('landscape')` | `device.setOrientation('landscape-left')` |
|
|
110
|
+
| `device.setBiometricEnrollment(true)` | `device.enrollBiometrics('faceid', true)` |
|
|
111
|
+
| `device.matchFace()`, `device.unmatchFace()` | `device.setBiometrics('faceid', 'match' \| 'nonmatch')` |
|
|
112
|
+
| `device.setStatusBar`, `device.setURLBlacklist` | No equivalent |
|
|
113
|
+
| `device.disableSynchronization()` | No equivalent. e2e waits through actions and retrying assertions. |
|
|
114
|
+
| `device.takeScreenshot()` | `app.screenshot('label')`, subject to the secret policy |
|
|
115
|
+
| `:ios:` / `:android:` in a test name | `{ platforms: ['ios'] }` on the test |
|
|
116
|
+
|
|
117
|
+
Where the behavior differs from Detox's:
|
|
118
|
+
|
|
119
|
+
- Actions and single-node reads or assertions need one match; several fail
|
|
120
|
+
with `LOCATOR_AMBIGUOUS`. Narrow with `.filter()`, `.first()`, or `.nth()`,
|
|
121
|
+
see [screen](/reference/screen).
|
|
122
|
+
- No `test.setup` or `{ session }` on a device, see
|
|
123
|
+
[what differs from the web](/mobile#what-differs-from-the-web).
|
|
124
|
+
|
|
125
|
+
`by.text` is an exact match in Detox and `getByText` is exact here too.
|
|
126
|
+
|
|
127
|
+
## What to migrate first
|
|
128
|
+
|
|
129
|
+
Start with a flow that needs frequent maintenance. If its screens take time
|
|
130
|
+
to settle, configure the engine's
|
|
131
|
+
[`settle` and `transition` options](/reference/mobile#engine).
|
|
132
|
+
|
|
133
|
+
<CardGroup cols={2}>
|
|
134
|
+
<Card title="Testing iOS and Android" icon="mobile-screen" href="/mobile">
|
|
135
|
+
Configure your app and devices.
|
|
136
|
+
</Card>
|
|
137
|
+
<Card title="Mobile engine reference" icon="book" href="/reference/mobile">
|
|
138
|
+
Every option, the `device` fixture, and the tool pack.
|
|
139
|
+
</Card>
|
|
140
|
+
</CardGroup>
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: From Maestro
|
|
3
|
+
description: Move Maestro flows to TypeScript with locators, assertions, and agent goals.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Translate Maestro commands into awaited TypeScript calls. Keep exact
|
|
7
|
+
interactions as locator calls, or give the agent a goal that covers several
|
|
8
|
+
of them. Both runners can use the same simulator or emulator.
|
|
9
|
+
|
|
10
|
+
Set up a target with the [mobile guide](/mobile) and a model with the
|
|
11
|
+
[quickstart](/quickstart), then move one flow at a time. This page maps each
|
|
12
|
+
Maestro command to its e2e counterpart and says whether it exists. The
|
|
13
|
+
reference pages hold the details: [screen](/reference/screen),
|
|
14
|
+
[expect](/reference/expect), [test](/reference/test), and the
|
|
15
|
+
[mobile engine](/reference/mobile).
|
|
16
|
+
|
|
17
|
+
## Config
|
|
18
|
+
|
|
19
|
+
| Maestro | e2e | Status |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `appId` at the top of every flow | `app: { bundleId: 'com.example.app' }` on the target, the app `app.open()` launches | renamed |
|
|
22
|
+
| a different `appId` per flow | `device.openApp(id)` inside the test, or separate app-specific configs and runs; every test runs on every selected target | renamed |
|
|
23
|
+
| `--platform ios` | `mobile({ platform: 'ios' })`, one engine per platform | renamed |
|
|
24
|
+
| `--device` | `mobile({ device: 'iPhone 17' })`; a list is a pool, one worker per device | renamed |
|
|
25
|
+
| `.maestro/config.yaml` `flows` | `tests`, default `tests/**/*.e2e.ts`; Maestro runs one folder level, e2e recurses | renamed |
|
|
26
|
+
| `flows: ['!helper.yaml']` | a `tests` entry with a leading `!`: `tests: ['tests/**/*.e2e.ts', '!tests/helpers/**']` | renamed |
|
|
27
|
+
| `tags` and `--include-tags` | `{ tags: [...] }` on a test or group, `--tag` on the CLI | renamed |
|
|
28
|
+
| `--exclude-tags` | `--exclude-tag` | renamed |
|
|
29
|
+
| `env` and `${VAR}` | module constants, and `params` in a goal, see [Selectors](#selectors) | renamed |
|
|
30
|
+
| `MAESTRO_*` variables | `process.env` in the config; a password or token goes under `credentials` or `secrets` | renamed |
|
|
31
|
+
| `--format junit`, `--output` | `--reporter list,junit`, written to `.e2e/junit.xml` | renamed |
|
|
32
|
+
| `--format html` | no equivalent; `markdown` writes `.e2e/summary.md`, every run writes `.e2e/report.json` | missing |
|
|
33
|
+
| `properties` (JUnit `<property>`) | not yet | missing |
|
|
34
|
+
| `--shards`, `--shard-split` | `device: [...]` plus `workers` splits a target's files across devices on one machine; `--shard <index/total>` splits the suite across machines, see [Sharding](/ci#sharding) | renamed |
|
|
35
|
+
| `maestro record`, `startRecording` | `npx e2e run --video`, one MP4 of the device per attempt, or `video` in the config | renamed |
|
|
36
|
+
| `maestro test -c`, Maestro Studio | not yet; `npx e2e mcp` gives a coding agent a live session on the device, see [Coding agents](/coding-agents) | missing |
|
|
37
|
+
| `maestro hierarchy` | not yet; `device.locator` takes agent-device selectors for nodes `screen` cannot name | missing |
|
|
38
|
+
| Maestro Cloud | your CI, see [Continuous integration](/ci) | by design |
|
|
39
|
+
|
|
40
|
+
## A flow, before and after
|
|
41
|
+
|
|
42
|
+
```yaml title="Maestro"
|
|
43
|
+
appId: com.example.app
|
|
44
|
+
---
|
|
45
|
+
- launchApp:
|
|
46
|
+
clearState: true
|
|
47
|
+
- tapOn: "Get started"
|
|
48
|
+
- tapOn:
|
|
49
|
+
id: "email"
|
|
50
|
+
- inputText: "ada@example.test"
|
|
51
|
+
- tapOn: "Continue"
|
|
52
|
+
- assertVisible: "Check your inbox"
|
|
53
|
+
- scrollUntilVisible:
|
|
54
|
+
element: "Resend"
|
|
55
|
+
- assertVisible:
|
|
56
|
+
id: "resend"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```ts title="e2e"
|
|
60
|
+
import { test } from '@e2e-dev/mobile';
|
|
61
|
+
import { expect } from 'e2e';
|
|
62
|
+
|
|
63
|
+
test('asks for the email', async ({ app, agent, screen }) => {
|
|
64
|
+
await app.clearState();
|
|
65
|
+
await agent.act('get started with the email {email}', { params: { email: 'ada@example.test' } });
|
|
66
|
+
await expect(screen.getByText('Check your inbox')).toBeVisible();
|
|
67
|
+
await screen.scrollUntilVisible(screen.getByTestId('resend'));
|
|
68
|
+
await expect(screen.getByTestId('resend')).toBeVisible();
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The agent handles onboarding. Locator assertions check the confirmation and
|
|
73
|
+
the Resend control. The flow could also stay fully deterministic: every
|
|
74
|
+
`tapOn` has a `screen.getBy*(...).tap()` line.
|
|
75
|
+
|
|
76
|
+
## Command map
|
|
77
|
+
|
|
78
|
+
Calls on `screen`, `app`, `agent`, and `expect(locator)` run on every
|
|
79
|
+
target, a browser included. Calls on `device` run only on a device: a test that uses one
|
|
80
|
+
declares `requires: ['device']` so other targets skip it. `Status` is `same`,
|
|
81
|
+
`renamed`, `device only`, `by design` (see [Selectors](#selectors) and
|
|
82
|
+
[By design](#by-design)), or `missing`, with what to do today.
|
|
83
|
+
|
|
84
|
+
### App lifecycle
|
|
85
|
+
|
|
86
|
+
| Maestro | e2e | Status |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| `launchApp` | `app.open()`, the fresh launch of the target's `app.bundleId`; nothing launches on its own | renamed |
|
|
89
|
+
| `launchApp: { clearState: true }`, `clearState` | `app.clearState()` | renamed |
|
|
90
|
+
| `launchApp: { stopApp: false }` | `device.openApp(id)` without `relaunch` | device only |
|
|
91
|
+
| `launchApp: { arguments }` | `app.launchArguments` on the target, or `device.openApp(app, { relaunch: true, launchArguments })` for one launch; a list of strings, not a map | renamed |
|
|
92
|
+
| `launchApp: { permissions }` | `app.permissions` on the target, set before every fresh launch, or `device.openApp(app, { relaunch: true, permissions })` for one; `grant`, `deny`, `reset` for `allow`, `deny`, `unset`; no `all`, nothing is granted unless named | renamed |
|
|
93
|
+
| `stopApp`, `killApp` | `device.closeApp()` | device only |
|
|
94
|
+
| `stopApp`, then `launchApp` | `app.restart()` | renamed |
|
|
95
|
+
| `clearKeychain` | `device.clearKeychain()`, the whole simulator's keychain; iOS only | renamed |
|
|
96
|
+
| `openLink` | `device.openLink(url, { app })`; on iOS the link opens into `app`, default the pinned app | renamed |
|
|
97
|
+
| `addMedia` | not yet | missing |
|
|
98
|
+
| `back` | `app.back()`, or `device.back()` | renamed |
|
|
99
|
+
|
|
100
|
+
### Taps and input
|
|
101
|
+
|
|
102
|
+
| Maestro | e2e | Status |
|
|
103
|
+
| --- | --- | --- |
|
|
104
|
+
| `tapOn: "Text"` | `screen.getByText('Text').tap()`; exact, see [Selectors](#selectors) | renamed |
|
|
105
|
+
| `tapOn: { id: x }` | `screen.getByTestId('x').tap()` | renamed |
|
|
106
|
+
| `tapOn: { text, index: 2 }` | `.nth(2)` | renamed |
|
|
107
|
+
| `tapOn: { below: "Email" }`, `above`, `leftOf`, `rightOf`, `containsDescendants` | no equivalent, see [Selectors](#selectors) | by design |
|
|
108
|
+
| `tapOn: { point: "x,y" }` | `screen.tapAt({ x, y })`; inside a node, `.tap({ position: { x, y } })` | renamed |
|
|
109
|
+
| `retryTapIfNoChange`, `waitToSettleTimeoutMs` | `mobile({ settle, transition })`, engine-wide; no per-call knob | renamed |
|
|
110
|
+
| `doubleTapOn`, `longPressOn` | `.doubleTap()`, `.longPress({ duration })` | renamed |
|
|
111
|
+
| `inputText` | `screen.getByTestId('field').fill('text')` | renamed |
|
|
112
|
+
| `inputRandomEmail`, `inputRandomText`, `faker` | `unique()` around a value in `act` params so the cache still replays; any npm faker for the rest | renamed |
|
|
113
|
+
| `eraseText` | `.clear()` | renamed |
|
|
114
|
+
| `hideKeyboard` | `device.dismissKeyboard()`, the same dismiss key or center drag Maestro uses; fails only when the keyboard outlives both drags | renamed |
|
|
115
|
+
| `pressKey: Enter` | `.press('Enter')` on the field | renamed |
|
|
116
|
+
| `pressKey: Home`, `back` | `device.home()`, `device.back()` | device only |
|
|
117
|
+
| `pressKey: lock`, `power`, `volume up`, TV remote keys | not yet | missing |
|
|
118
|
+
| `copyTextFrom`, `pasteText` | `await locator.textContent()`, then `.fill(text)` | renamed |
|
|
119
|
+
| `setClipboard` | `device.setClipboard(text)`; `device.clipboard()` reads it | device only |
|
|
120
|
+
| `label: "..."` on a command | not yet; every `screen`, `device`, and `agent` call is a report step named by the call | missing |
|
|
121
|
+
|
|
122
|
+
### Gestures
|
|
123
|
+
|
|
124
|
+
| Maestro | e2e | Status |
|
|
125
|
+
| --- | --- | --- |
|
|
126
|
+
| `swipe: { direction: UP }` | `screen.swipe({ direction: 'down' })`, or `locator.swipe(...)` inside one node; Maestro names the finger's direction, e2e the content's | renamed |
|
|
127
|
+
| `swipe: { start, end }` | `screen.swipe({ from: { x, y }, to: { x, y } })` | renamed |
|
|
128
|
+
| `scroll` | `screen.swipe({ direction: 'down' })` | renamed |
|
|
129
|
+
| `scrollUntilVisible: { element }` | `screen.scrollUntilVisible(locator, { direction })` | renamed |
|
|
130
|
+
| `waitForAnimationToEnd` | an assertion on the settled state; `mobile({ settle, transition })` for the engine | renamed |
|
|
131
|
+
|
|
132
|
+
### Assertions and waits
|
|
133
|
+
|
|
134
|
+
| Maestro | e2e | Status |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| `assertVisible`, `assertNotVisible` | `await expect(locator).toBeVisible()`, `.toBeHidden()` | renamed |
|
|
137
|
+
| `assertVisible: { text, enabled: true }` | `.toBeVisible()` and `.toBeEnabled()` | renamed |
|
|
138
|
+
| `assertVisible: { checked, selected, focused }` | `.toBeChecked()`, `.toBeSelected()`, `.toBeFocused()` | renamed |
|
|
139
|
+
| `assertTrue: ${...}` | `expect(value).toBe(true)`, or `expect.poll` for a value that is still changing | renamed |
|
|
140
|
+
| `extendedWaitUntil: { visible, timeout }` | `.toBeVisible({ timeout })` | renamed |
|
|
141
|
+
| `assertScreenshot: { path, thresholdPercentage }` | not yet; `agent.assert('...', { vision: true })` is a judgment, not a pixel diff | missing |
|
|
142
|
+
| `assertDarkMode`, `assertLightMode` | not yet; assert on a themed control | missing |
|
|
143
|
+
| `retry: { maxRetries, commands }` | `expect.poll` for a value, `{ retries }` on the test for the flow | renamed |
|
|
144
|
+
| `takeScreenshot` | `app.screenshot('label')`, redacted, withheld after a secret fill | renamed |
|
|
145
|
+
|
|
146
|
+
### Device
|
|
147
|
+
|
|
148
|
+
| Maestro | e2e | Status |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| `setLocation` | `device.setLocation({ latitude, longitude })` | device only |
|
|
151
|
+
| `travel: { points }` | `device.setLocation` in a loop | device only |
|
|
152
|
+
| `setAirplaneMode`, `toggleAirplaneMode` | `device.setAirplaneMode(true)` or `false`, the state you want | device only |
|
|
153
|
+
| `setDarkMode`, `toggleDarkMode` | `device.setAppearance('dark')` or `'light'` | device only |
|
|
154
|
+
| `setOrientation` | `device.setOrientation('landscape-left')` | device only |
|
|
155
|
+
| `setPermissions` | `device.setPermission(name, 'grant' \| 'deny' \| 'reset')`, one permission per call, on the open app | device only |
|
|
156
|
+
| a second `appId` mid-flow | `device.openApp(id)`; the `open_app` tool lets the agent switch inside a goal, see [Agent tools](/mobile#agent-tools) | device only |
|
|
157
|
+
| platform-specific selectors | `device.locator('role=StaticText label="..."')`, agent-device's selector terms | device only |
|
|
158
|
+
|
|
159
|
+
### AI commands and flow control
|
|
160
|
+
|
|
161
|
+
| Maestro | e2e | Status |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `assertWithAI`, `assertNoDefectsWithAI` | `agent.assert('...')`, `agent.assert('...', { vision: true })` | renamed |
|
|
164
|
+
| `extractTextWithAI` | `agent.extract('...', { schema })` | renamed |
|
|
165
|
+
| `runFlow: file.yaml` | a function, or a fixture from `test.extend` | renamed |
|
|
166
|
+
| `runFlow: { when: { visible } }` | `if (await locator.isVisible()) { ... }`, see [Selectors](#selectors) | renamed |
|
|
167
|
+
| `optional: true` on a command | the same `isVisible()` check | renamed |
|
|
168
|
+
| `repeat: { times: n }`, `repeat: { while }` | a `for` or `while` loop | renamed |
|
|
169
|
+
| `runScript`, `evalScript`, `${output.x}` | TypeScript in the test | renamed |
|
|
170
|
+
| `http.get`, `http.post`, `json()` | Node `fetch`, see [Testing APIs](/api-testing) | renamed |
|
|
171
|
+
| `onFlowStart`, `onFlowComplete` | `beforeEach`, `afterEach` | renamed |
|
|
172
|
+
| `startRecording`, `stopRecording` | `test('x', { video: 'on' }, ...)` records that test's whole attempts, on a device the mobile engine records; no start and stop inside a test | renamed |
|
|
173
|
+
|
|
174
|
+
## Selectors
|
|
175
|
+
|
|
176
|
+
Maestro's selector shorthand does not port one to one. Five differences
|
|
177
|
+
account for most edits.
|
|
178
|
+
|
|
179
|
+
- Text and id are regular expressions in Maestro, so `tapOn: ".*Save.*"`
|
|
180
|
+
matches any text with Save in it. `getByText` is exact. Write
|
|
181
|
+
`getByText(/Save/)` for the pattern, or `{ exact: false }` for a
|
|
182
|
+
case-insensitive substring. `getByTestId` matches a string as the whole id;
|
|
183
|
+
write `getByTestId(/^row-/)` for a pattern.
|
|
184
|
+
- `index: 2` is `.nth(2)`. When several nodes match and no index is given,
|
|
185
|
+
Maestro taps the first one silently; e2e fails with `LOCATOR_AMBIGUOUS`.
|
|
186
|
+
Write `.first()` when the first match is what you mean.
|
|
187
|
+
- `optional: true` and `runFlow: { when: { visible } }` become
|
|
188
|
+
`if (await locator.isVisible())`. `isVisible()` is a read: `false` on zero
|
|
189
|
+
matches, `LOCATOR_AMBIGUOUS` on several. Add `{ visible: true }` to the
|
|
190
|
+
query or `.first()` to the locator when a hidden twin may exist.
|
|
191
|
+
- `below`, `above`, `leftOf`, `rightOf`, and `containsDescendants` have no
|
|
192
|
+
port. e2e has `filter({ has, hasText })` and chaining for structure and
|
|
193
|
+
nothing spatial; a selector anchored on layout breaks on the next redesign.
|
|
194
|
+
Anchor an unlabeled input with `getByLabel`, give it a test id, or hand the
|
|
195
|
+
step to a goal: `agent.act('enter {email} in the email field', { params })`
|
|
196
|
+
reads the screen and finds the field.
|
|
197
|
+
- `env:` and `${VAR}` become module constants, and `params` inside a goal:
|
|
198
|
+
`agent.act('sign in as {email}', { params: { email } })`. `MAESTRO_*`
|
|
199
|
+
variables become `process.env` in the config. A password or token goes
|
|
200
|
+
under `credentials` or `secrets`, so the model never sees the value.
|
|
201
|
+
|
|
202
|
+
## By design
|
|
203
|
+
|
|
204
|
+
These differ from Maestro on purpose and will stay that way.
|
|
205
|
+
|
|
206
|
+
- One match or `LOCATOR_AMBIGUOUS`, see [Selectors](#selectors).
|
|
207
|
+
- A password is a `Secret` the model never sees, see
|
|
208
|
+
[Signing in](/authentication).
|
|
209
|
+
- Every `device` call is a step. It lands in the report as `device.<method>`,
|
|
210
|
+
so a failure shows the exact call without a `label`.
|
|
211
|
+
- No agent-device client in tests. `device.locator` covers platform-specific
|
|
212
|
+
selectors; everything else goes through `screen`, `app`, `device`, and the
|
|
213
|
+
agent, so it is recorded and redacted.
|
|
214
|
+
- No `test.setup` or `session:` on a device, see
|
|
215
|
+
[what differs from the web](/mobile#what-differs-from-the-web).
|
|
216
|
+
|
|
217
|
+
## What to migrate first
|
|
218
|
+
|
|
219
|
+
Start with a flow whose `optional` steps and `runFlow: { when }` branches
|
|
220
|
+
often need updating.
|
|
221
|
+
|
|
222
|
+
<CardGroup cols={2}>
|
|
223
|
+
<Card title="Testing iOS and Android" icon="mobile-screen" href="/mobile">
|
|
224
|
+
Configure your app and devices.
|
|
225
|
+
</Card>
|
|
226
|
+
<Card title="Writing tests" icon="pen-to-square" href="/writing-tests">
|
|
227
|
+
Goals, checks, extraction, and the deterministic APIs.
|
|
228
|
+
</Card>
|
|
229
|
+
</CardGroup>
|