@e2edev/e2e 0.5.0 → 0.6.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 +64 -25
- package/dist/agent/act.d.ts +2 -2
- package/dist/agent/act.js +14 -37
- package/dist/agent/act.js.map +1 -1
- package/dist/agent/actions.d.ts +2 -2
- package/dist/agent/actions.d.ts.map +1 -1
- package/dist/agent/actions.js +1 -1
- package/dist/agent/ai-sdk.d.ts +1 -2
- package/dist/agent/ai-sdk.d.ts.map +1 -1
- package/dist/agent/ai-sdk.js +1 -2
- package/dist/agent/ai-sdk.js.map +1 -1
- package/dist/agent/default-agent.d.ts +10 -32
- package/dist/agent/default-agent.d.ts.map +1 -1
- package/dist/agent/default-agent.js +6 -13
- package/dist/agent/default-agent.js.map +1 -1
- package/dist/agent/derived.d.ts +1 -1
- package/dist/agent/derived.js +1 -1
- package/dist/agent/error.d.ts +2 -4
- package/dist/agent/error.d.ts.map +1 -1
- package/dist/agent/error.js +3 -5
- package/dist/agent/error.js.map +1 -1
- package/dist/agent/executor.d.ts +23 -52
- package/dist/agent/executor.d.ts.map +1 -1
- package/dist/agent/executor.js +1 -2
- package/dist/agent/executor.js.map +1 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +10 -7
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/invocation.d.ts +8 -6
- package/dist/agent/invocation.d.ts.map +1 -1
- package/dist/agent/invocation.js +9 -4
- package/dist/agent/invocation.js.map +1 -1
- package/dist/agent/ledger.d.ts +17 -12
- package/dist/agent/ledger.d.ts.map +1 -1
- package/dist/agent/ledger.js +6 -9
- package/dist/agent/ledger.js.map +1 -1
- package/dist/agent/model/adapter.d.ts +7 -4
- package/dist/agent/model/adapter.d.ts.map +1 -1
- package/dist/agent/model/adapter.js +2 -2
- package/dist/agent/model/adapter.js.map +1 -1
- package/dist/agent/model/router.d.ts +1 -1
- package/dist/agent/model/router.d.ts.map +1 -1
- package/dist/agent/model/router.js +1 -1
- package/dist/agent/model/router.js.map +1 -1
- package/dist/agent/model/sdk.d.ts +11 -1
- package/dist/agent/model/sdk.d.ts.map +1 -1
- package/dist/agent/model/sdk.js +54 -10
- package/dist/agent/model/sdk.js.map +1 -1
- package/dist/agent/observation.d.ts +7 -7
- package/dist/agent/observation.d.ts.map +1 -1
- package/dist/agent/observation.js +7 -7
- package/dist/agent/observation.js.map +1 -1
- package/dist/agent/phases.d.ts +3 -3
- package/dist/agent/phases.d.ts.map +1 -1
- package/dist/agent/phases.js +4 -4
- package/dist/agent/phases.js.map +1 -1
- package/dist/agent/primitives.d.ts +4 -25
- package/dist/agent/primitives.d.ts.map +1 -1
- package/dist/agent/primitives.js +3 -36
- package/dist/agent/primitives.js.map +1 -1
- package/dist/agent/prompts.d.ts +1 -1
- package/dist/agent/prompts.js +1 -1
- package/dist/agent/protocol.d.ts +2 -3
- package/dist/agent/protocol.d.ts.map +1 -1
- package/dist/agent/protocol.js +2 -3
- package/dist/agent/protocol.js.map +1 -1
- package/dist/agent/public.d.ts +8 -10
- package/dist/agent/public.d.ts.map +1 -1
- package/dist/agent/public.js +7 -8
- package/dist/agent/public.js.map +1 -1
- package/dist/agent/replay.d.ts +2 -2
- package/dist/agent/replay.d.ts.map +1 -1
- package/dist/agent/replay.js +1 -1
- package/dist/agent/secrets.d.ts +3 -3
- package/dist/agent/secrets.d.ts.map +1 -1
- package/dist/agent/secrets.js +4 -4
- package/dist/agent/secrets.js.map +1 -1
- package/dist/agent/step-cache.d.ts +1 -1
- package/dist/agent/step-cache.d.ts.map +1 -1
- package/dist/agent/step-cache.js +7 -1
- package/dist/agent/step-cache.js.map +1 -1
- package/dist/agent/tool-loop.d.ts +9 -33
- package/dist/agent/tool-loop.d.ts.map +1 -1
- package/dist/agent/tool-loop.js +15 -38
- package/dist/agent/tool-loop.js.map +1 -1
- package/dist/agent/tool.d.ts +4 -5
- package/dist/agent/tool.d.ts.map +1 -1
- package/dist/agent/tool.js +2 -7
- package/dist/agent/tool.js.map +1 -1
- package/dist/cache/anchors.d.ts +2 -2
- package/dist/cache/anchors.d.ts.map +1 -1
- package/dist/cache/anchors.js +1 -1
- package/dist/cache/context.d.ts +6 -1
- package/dist/cache/context.d.ts.map +1 -1
- package/dist/cache/context.js +2 -1
- package/dist/cache/context.js.map +1 -1
- package/dist/cache/decide.d.ts +1 -1
- package/dist/cache/decide.js +1 -1
- package/dist/cache/identity.d.ts +9 -9
- package/dist/cache/identity.d.ts.map +1 -1
- package/dist/cache/identity.js +6 -6
- package/dist/cache/identity.js.map +1 -1
- package/dist/cache/recorder.d.ts +4 -2
- package/dist/cache/recorder.d.ts.map +1 -1
- package/dist/cache/recorder.js +10 -1
- package/dist/cache/recorder.js.map +1 -1
- package/dist/cache/relocate.d.ts +2 -2
- package/dist/cache/relocate.d.ts.map +1 -1
- package/dist/cache/relocate.js +1 -1
- package/dist/cache/store.d.ts +1 -1
- package/dist/cache/store.js +1 -1
- package/dist/cache/trace.d.ts +16 -1
- package/dist/cache/trace.d.ts.map +1 -1
- package/dist/cache/trace.js +22 -1
- package/dist/cache/trace.js.map +1 -1
- package/dist/cli/bin.js +9 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/cache.d.ts +25 -0
- package/dist/cli/cache.d.ts.map +1 -0
- package/dist/cli/cache.js +249 -0
- package/dist/cli/cache.js.map +1 -0
- package/dist/cli/docs-url.d.ts +3 -0
- package/dist/cli/docs-url.d.ts.map +1 -0
- package/dist/cli/docs-url.js +3 -0
- package/dist/cli/docs-url.js.map +1 -0
- package/dist/cli/guide.d.ts +4 -0
- package/dist/cli/guide.d.ts.map +1 -0
- package/dist/cli/guide.js +16 -0
- package/dist/cli/guide.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +211 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/agent-skill.d.ts +34 -0
- package/dist/cli/init/agent-skill.d.ts.map +1 -0
- package/dist/cli/init/agent-skill.js +44 -0
- package/dist/cli/init/agent-skill.js.map +1 -0
- package/dist/cli/init/{backends.d.ts → engines.d.ts} +39 -32
- package/dist/cli/init/engines.d.ts.map +1 -0
- package/dist/cli/init/{backends.js → engines.js} +43 -34
- package/dist/cli/init/engines.js.map +1 -0
- package/dist/cli/init/package.d.ts +19 -3
- package/dist/cli/init/package.d.ts.map +1 -1
- package/dist/cli/init/package.js +20 -20
- package/dist/cli/init/package.js.map +1 -1
- package/dist/cli/init/scaffold.d.ts +3 -3
- package/dist/cli/init/scaffold.d.ts.map +1 -1
- package/dist/cli/init/scaffold.js +13 -12
- package/dist/cli/init/scaffold.js.map +1 -1
- package/dist/cli/init.d.ts +14 -2
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +104 -25
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/signals.d.ts +5 -2
- package/dist/cli/signals.d.ts.map +1 -1
- package/dist/cli/signals.js +9 -3
- package/dist/cli/signals.js.map +1 -1
- package/dist/cli/skill.d.ts +16 -0
- package/dist/cli/skill.d.ts.map +1 -0
- package/dist/cli/skill.js +57 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/collect/collect.d.ts +40 -3
- package/dist/collect/collect.d.ts.map +1 -1
- package/dist/collect/collect.js +142 -19
- package/dist/collect/collect.js.map +1 -1
- package/dist/collect/registry.d.ts +1 -1
- package/dist/collect/registry.d.ts.map +1 -1
- package/dist/collect/registry.js +2 -2
- package/dist/collect/registry.js.map +1 -1
- package/dist/collect/select.d.ts +1 -1
- package/dist/collect/select.d.ts.map +1 -1
- package/dist/collect/select.js +81 -8
- package/dist/collect/select.js.map +1 -1
- package/dist/config/agent.d.ts +14 -2
- package/dist/config/agent.d.ts.map +1 -1
- package/dist/config/agent.js +36 -11
- package/dist/config/agent.js.map +1 -1
- package/dist/config/app.d.ts +76 -19
- package/dist/config/app.d.ts.map +1 -1
- package/dist/config/app.js +159 -104
- package/dist/config/app.js.map +1 -1
- package/dist/config/diagnose.d.ts +15 -0
- package/dist/config/diagnose.d.ts.map +1 -0
- package/dist/config/diagnose.js +122 -0
- package/dist/config/diagnose.js.map +1 -0
- package/dist/config/load.d.ts +9 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +35 -3
- package/dist/config/load.js.map +1 -1
- package/dist/config/resolve.d.ts +8 -7
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +73 -40
- package/dist/config/resolve.js.map +1 -1
- package/dist/config/validate.d.ts +6 -2
- package/dist/config/validate.d.ts.map +1 -1
- package/dist/config/validate.js +20 -3
- package/dist/config/validate.js.map +1 -1
- package/dist/credentials.d.ts +1 -1
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +1 -1
- package/dist/credentials.js.map +1 -1
- package/dist/{backend → engine}/contract.d.ts +27 -19
- package/dist/engine/contract.d.ts.map +1 -0
- package/dist/{backend → engine}/contract.js +18 -18
- package/dist/engine/contract.js.map +1 -0
- package/dist/{backend → engine}/index.d.ts +141 -79
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/{backend → engine}/index.js +62 -37
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/session.d.ts +23 -0
- package/dist/engine/session.d.ts.map +1 -0
- package/dist/{backend → engine}/session.js +58 -51
- package/dist/engine/session.js.map +1 -0
- package/dist/{backend → engine}/surface.d.ts +11 -11
- package/dist/engine/surface.d.ts.map +1 -0
- package/dist/{backend → engine}/surface.js +2 -2
- package/dist/engine/surface.js.map +1 -0
- package/dist/engine/timing.d.ts.map +1 -0
- package/dist/engine/timing.js +8 -0
- package/dist/engine/timing.js.map +1 -0
- package/dist/expect/async.d.ts +1 -1
- package/dist/expect/async.d.ts.map +1 -1
- package/dist/expect/async.js +37 -1
- package/dist/expect/async.js.map +1 -1
- package/dist/expect/index.js +1 -1
- package/dist/expect/values.d.ts +1 -1
- package/dist/expect/values.d.ts.map +1 -1
- package/dist/expect/values.js +1 -1
- package/dist/expect/values.js.map +1 -1
- package/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/internal/brands.d.ts +1 -1
- package/dist/internal/brands.d.ts.map +1 -1
- package/dist/internal/brands.js +1 -1
- package/dist/internal/brands.js.map +1 -1
- package/dist/internal/errors.d.ts +37 -19
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +94 -44
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/globs.d.ts +2 -2
- package/dist/internal/globs.d.ts.map +1 -1
- package/dist/internal/globs.js +2 -2
- package/dist/internal/globs.js.map +1 -1
- package/dist/internal/ids.d.ts +3 -3
- package/dist/internal/ids.d.ts.map +1 -1
- package/dist/internal/ids.js +3 -3
- package/dist/internal/ids.js.map +1 -1
- package/dist/internal/node-version.d.ts +10 -0
- package/dist/internal/node-version.d.ts.map +1 -0
- package/dist/internal/node-version.js +28 -0
- package/dist/internal/node-version.js.map +1 -0
- package/dist/internal/objects.d.ts +21 -0
- package/dist/internal/objects.d.ts.map +1 -0
- package/dist/internal/objects.js +14 -0
- package/dist/internal/objects.js.map +1 -0
- package/dist/internal/package-manager.d.ts +10 -0
- package/dist/internal/package-manager.d.ts.map +1 -0
- package/dist/internal/package-manager.js +43 -0
- package/dist/internal/package-manager.js.map +1 -0
- package/dist/internal/redact.d.ts +1 -1
- package/dist/internal/redact.d.ts.map +1 -1
- package/dist/internal/redact.js +1 -1
- package/dist/internal/redact.js.map +1 -1
- package/dist/internal/suggest.d.ts +16 -0
- package/dist/internal/suggest.d.ts.map +1 -0
- package/dist/internal/suggest.js +61 -0
- package/dist/internal/suggest.js.map +1 -0
- package/dist/internal/text.d.ts +1 -1
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +1 -1
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/urls.d.ts +3 -3
- package/dist/internal/urls.d.ts.map +1 -1
- package/dist/internal/urls.js +8 -3
- package/dist/internal/urls.js.map +1 -1
- package/dist/locator/engine.d.ts +7 -7
- package/dist/locator/engine.d.ts.map +1 -1
- package/dist/locator/engine.js +14 -14
- package/dist/locator/engine.js.map +1 -1
- package/dist/locator/expression.d.ts +5 -3
- package/dist/locator/expression.d.ts.map +1 -1
- package/dist/locator/expression.js +25 -5
- package/dist/locator/expression.js.map +1 -1
- package/dist/locator/screen.d.ts +1 -1
- package/dist/locator/screen.d.ts.map +1 -1
- package/dist/locator/screen.js +3 -3
- package/dist/locator/screen.js.map +1 -1
- package/dist/report/build.d.ts +10 -9
- package/dist/report/build.d.ts.map +1 -1
- package/dist/report/build.js +25 -22
- package/dist/report/build.js.map +1 -1
- package/dist/report/code-frame.d.ts +8 -4
- package/dist/report/code-frame.d.ts.map +1 -1
- package/dist/report/code-frame.js +23 -18
- package/dist/report/code-frame.js.map +1 -1
- package/dist/report/debug-steps.js +1 -1
- package/dist/report/debug-steps.js.map +1 -1
- package/dist/report/format.d.ts +73 -0
- package/dist/report/format.d.ts.map +1 -0
- package/dist/report/format.js +147 -0
- package/dist/report/format.js.map +1 -0
- package/dist/report/junit.d.ts +1 -1
- package/dist/report/junit.d.ts.map +1 -1
- package/dist/report/junit.js +1 -1
- package/dist/report/junit.js.map +1 -1
- package/dist/report/list.d.ts +96 -47
- package/dist/report/list.d.ts.map +1 -1
- package/dist/report/list.js +489 -244
- package/dist/report/list.js.map +1 -1
- package/dist/report/live-window.d.ts +28 -0
- package/dist/report/live-window.d.ts.map +1 -0
- package/dist/report/live-window.js +102 -0
- package/dist/report/live-window.js.map +1 -0
- package/dist/report/write.d.ts +1 -1
- package/dist/report/write.d.ts.map +1 -1
- package/dist/report/write.js +1 -1
- package/dist/report/write.js.map +1 -1
- package/dist/run/budget.d.ts +2 -2
- package/dist/run/budget.js +2 -2
- package/dist/run/declared-processes.d.ts +30 -0
- package/dist/run/declared-processes.d.ts.map +1 -0
- package/dist/run/declared-processes.js +61 -0
- package/dist/run/declared-processes.js.map +1 -0
- package/dist/run/events.d.ts +30 -2
- package/dist/run/events.d.ts.map +1 -1
- package/dist/run/events.js.map +1 -1
- package/dist/run/execute.d.ts +19 -16
- package/dist/run/execute.d.ts.map +1 -1
- package/dist/run/execute.js +65 -67
- package/dist/run/execute.js.map +1 -1
- package/dist/run/fixture-recording.d.ts +10 -4
- package/dist/run/fixture-recording.d.ts.map +1 -1
- package/dist/run/fixture-recording.js +19 -6
- package/dist/run/fixture-recording.js.map +1 -1
- package/dist/run/fixtures.d.ts +2 -2
- package/dist/run/fixtures.d.ts.map +1 -1
- package/dist/run/fixtures.js +72 -44
- package/dist/run/fixtures.js.map +1 -1
- package/dist/run/in-process.d.ts +1 -1
- package/dist/run/in-process.js +1 -1
- package/dist/run/managed-process.d.ts +46 -9
- package/dist/run/managed-process.d.ts.map +1 -1
- package/dist/run/managed-process.js +136 -50
- package/dist/run/managed-process.js.map +1 -1
- package/dist/run/realm.d.ts +2 -2
- package/dist/run/realm.js +2 -2
- package/dist/run/runner.d.ts +23 -1
- package/dist/run/runner.d.ts.map +1 -1
- package/dist/run/runner.js +111 -40
- package/dist/run/runner.js.map +1 -1
- package/dist/run/scheduler.d.ts +5 -5
- package/dist/run/scheduler.d.ts.map +1 -1
- package/dist/run/scheduler.js +7 -7
- package/dist/run/scheduler.js.map +1 -1
- package/dist/run/serial.d.ts +10 -2
- package/dist/run/serial.d.ts.map +1 -1
- package/dist/run/serial.js +5 -3
- package/dist/run/serial.js.map +1 -1
- package/dist/run/sessions.d.ts +10 -10
- package/dist/run/sessions.d.ts.map +1 -1
- package/dist/run/sessions.js +11 -11
- package/dist/run/sessions.js.map +1 -1
- package/dist/run/steps.d.ts +3 -3
- package/dist/run/steps.d.ts.map +1 -1
- package/dist/run/steps.js +1 -1
- package/dist/run/steps.js.map +1 -1
- package/dist/run/units.d.ts +1 -1
- package/dist/run/units.js +1 -1
- package/dist/run/worker/entry.d.ts +1 -1
- package/dist/run/worker/entry.js +2 -2
- package/dist/run/worker/entry.js.map +1 -1
- package/dist/run/worker/protocol.d.ts +18 -6
- package/dist/run/worker/protocol.d.ts.map +1 -1
- package/dist/run/worker/protocol.js +1 -1
- package/dist/run/worker/protocol.js.map +1 -1
- package/dist/run/worker/session.d.ts +2 -2
- package/dist/run/worker/session.d.ts.map +1 -1
- package/dist/run/worker/session.js +5 -3
- package/dist/run/worker/session.js.map +1 -1
- package/dist/types.d.ts +58 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/package.json +13 -12
- package/skills/e2e/SKILL.md +110 -0
- package/skills/e2e/references/agent.md +210 -0
- package/skills/e2e/references/debugging.md +81 -0
- package/skills/e2e/references/running.md +153 -0
- package/skills/e2e/references/setup.md +238 -0
- package/skills/e2e/references/writing-tests.md +289 -0
- package/dist/backend/contract.d.ts.map +0 -1
- package/dist/backend/contract.js.map +0 -1
- package/dist/backend/index.d.ts.map +0 -1
- package/dist/backend/index.js.map +0 -1
- package/dist/backend/session.d.ts +0 -23
- package/dist/backend/session.d.ts.map +0 -1
- package/dist/backend/session.js.map +0 -1
- package/dist/backend/surface.d.ts.map +0 -1
- package/dist/backend/surface.js.map +0 -1
- package/dist/backend/timing.d.ts.map +0 -1
- package/dist/backend/timing.js +0 -8
- package/dist/backend/timing.js.map +0 -1
- package/dist/cli/init/backends.d.ts.map +0 -1
- package/dist/cli/init/backends.js.map +0 -1
- package/dist/report/live-status.d.ts +0 -51
- package/dist/report/live-status.d.ts.map +0 -1
- package/dist/report/live-status.js +0 -163
- package/dist/report/live-status.js.map +0 -1
- package/dist/run/fixture-legacy.d.ts +0 -36
- package/dist/run/fixture-legacy.d.ts.map +0 -1
- package/dist/run/fixture-legacy.js +0 -143
- package/dist/run/fixture-legacy.js.map +0 -1
- /package/dist/{backend → engine}/timing.d.ts +0 -0
|
@@ -1,50 +1,59 @@
|
|
|
1
|
-
/** CLI scaffold presets.
|
|
1
|
+
/** CLI scaffold presets. Engine packages are referenced as generated source, never imported. */
|
|
2
2
|
import os from 'node:os';
|
|
3
|
+
/** Engines version independently of the runner and pin the runner through their own peer range. */
|
|
4
|
+
const ENGINE_RANGE = '0.x';
|
|
3
5
|
/** Builds prompt choices and scaffolds with defaults for the machine running init. */
|
|
4
|
-
export function
|
|
6
|
+
export function getEnginePresets() {
|
|
5
7
|
const ios = os.platform() === 'darwin';
|
|
6
8
|
return [
|
|
7
|
-
{
|
|
8
|
-
id: 'none',
|
|
9
|
-
label: 'None',
|
|
10
|
-
hint: 'HTTP tests or your own backend',
|
|
11
|
-
dependencies: {},
|
|
12
|
-
imports: [],
|
|
13
|
-
config: ` app: { url: process.env.APP_URL ?? 'http://localhost:3000' },
|
|
14
|
-
// Add a backend here when your tests need to drive an app.
|
|
15
|
-
targets: [{ name: 'default', platform: 'custom' }],`,
|
|
16
|
-
example: `import { test, expect } from '@e2edev/e2e';
|
|
17
|
-
|
|
18
|
-
test('app responds', async () => {
|
|
19
|
-
const response = await fetch(process.env.APP_URL ?? 'http://localhost:3000');
|
|
20
|
-
expect(response.ok).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
`,
|
|
23
|
-
runCommand: 'APP_URL=http://localhost:3000 npx --no-install e2e run',
|
|
24
|
-
},
|
|
25
9
|
{
|
|
26
10
|
id: 'playwright',
|
|
27
11
|
label: 'Playwright',
|
|
28
12
|
hint: 'browser testing',
|
|
29
|
-
dependencies: { '@e2edev/playwright':
|
|
13
|
+
dependencies: { '@e2edev/playwright': ENGINE_RANGE },
|
|
30
14
|
imports: ["import { playwright } from '@e2edev/playwright';"],
|
|
31
|
-
config: ` app
|
|
32
|
-
targets: [{
|
|
15
|
+
config: ` // The engine declares the app it drives; APP_URL overrides the default at run time.
|
|
16
|
+
targets: [{
|
|
17
|
+
name: 'web',
|
|
18
|
+
platform: 'web',
|
|
19
|
+
engine: playwright({
|
|
20
|
+
url: process.env.APP_URL ?? 'http://localhost:3000',
|
|
21
|
+
// Let the runner start the dev server and wait for url to answer:
|
|
22
|
+
// command: { executable: 'npm', args: ['run', 'dev'] },
|
|
23
|
+
}),
|
|
24
|
+
}],`,
|
|
33
25
|
example: `import { test } from '@e2edev/playwright';
|
|
34
26
|
import { expect } from '@e2edev/e2e';
|
|
35
27
|
|
|
36
28
|
test('app opens', async ({ app, web }) => {
|
|
37
|
-
await app.open();
|
|
38
|
-
await expect(web
|
|
29
|
+
await app.open('/');
|
|
30
|
+
await expect(web.locator('body')).toBeVisible();
|
|
39
31
|
});
|
|
40
32
|
`,
|
|
41
33
|
aiExample: `
|
|
42
34
|
// Runs when E2E_MODEL and E2E_MODEL_API_KEY are set:
|
|
43
35
|
// test('the agent drives a flow', async ({ app, agent }) => {
|
|
44
|
-
// await app.open();
|
|
36
|
+
// await app.open('/');
|
|
45
37
|
// await agent.act('one goal in plain language');
|
|
46
38
|
// await agent.assert('one question about the screen');
|
|
47
39
|
// });
|
|
40
|
+
`,
|
|
41
|
+
runCommand: 'APP_URL=http://localhost:3000 npx --no-install e2e run',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'none',
|
|
45
|
+
label: 'None',
|
|
46
|
+
hint: 'HTTP tests or your own engine',
|
|
47
|
+
dependencies: {},
|
|
48
|
+
imports: [],
|
|
49
|
+
config: ` // Add an engine here when your tests need to drive an app.
|
|
50
|
+
targets: [{ name: 'default', platform: 'custom' }],`,
|
|
51
|
+
example: `import { test, expect } from '@e2edev/e2e';
|
|
52
|
+
|
|
53
|
+
test('app responds', async () => {
|
|
54
|
+
const response = await fetch(process.env.APP_URL ?? 'http://localhost:3000');
|
|
55
|
+
expect(response.ok).toBe(true);
|
|
56
|
+
});
|
|
48
57
|
`,
|
|
49
58
|
runCommand: 'APP_URL=http://localhost:3000 npx --no-install e2e run',
|
|
50
59
|
},
|
|
@@ -52,14 +61,14 @@ test('app opens', async ({ app, web }) => {
|
|
|
52
61
|
id: 'agent-device',
|
|
53
62
|
label: 'agent-device',
|
|
54
63
|
hint: 'mobile testing: iOS and Android',
|
|
55
|
-
dependencies: { '@e2edev/agent-device':
|
|
64
|
+
dependencies: { '@e2edev/agent-device': ENGINE_RANGE },
|
|
56
65
|
imports: ["import { agentDevice } from '@e2edev/agent-device';"],
|
|
57
66
|
config: ios
|
|
58
67
|
? ` // Requires Xcode and an iOS simulator. Replace Settings with your app's bundle ID.
|
|
59
|
-
targets: [{ name: 'ios', platform: 'ios',
|
|
68
|
+
targets: [{ name: 'ios', platform: 'ios', engine: agentDevice({ platform: 'ios', app: 'Settings' }) }],
|
|
60
69
|
workers: 1,`
|
|
61
70
|
: ` // Requires the Android SDK and an emulator. Replace com.android.settings with your app's package.
|
|
62
|
-
targets: [{ name: 'android', platform: 'android',
|
|
71
|
+
targets: [{ name: 'android', platform: 'android', engine: agentDevice({ platform: 'android', app: 'com.android.settings' }) }],
|
|
63
72
|
workers: 1,`,
|
|
64
73
|
example: `import { test } from '@e2edev/agent-device';
|
|
65
74
|
import { expect } from '@e2edev/e2e';
|
|
@@ -87,12 +96,12 @@ test('Settings opens', async ({ screen }) => {
|
|
|
87
96
|
},
|
|
88
97
|
];
|
|
89
98
|
}
|
|
90
|
-
export const
|
|
99
|
+
export const DEFAULT_ENGINE_ID = 'playwright';
|
|
91
100
|
/** Resolves a preset with the common shape used by scaffold generation. */
|
|
92
|
-
export function
|
|
93
|
-
const preset =
|
|
101
|
+
export function getEnginePreset(id) {
|
|
102
|
+
const preset = getEnginePresets().find((entry) => entry.id === id);
|
|
94
103
|
if (preset === undefined)
|
|
95
|
-
throw new Error(`unknown
|
|
104
|
+
throw new Error(`unknown engine: ${id}`);
|
|
96
105
|
return preset;
|
|
97
106
|
}
|
|
98
|
-
//# sourceMappingURL=
|
|
107
|
+
//# sourceMappingURL=engines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engines.js","sourceRoot":"","sources":["../../../src/cli/init/engines.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,OAAO,EAAE,MAAM,SAAS,CAAC;AAczB,mGAAmG;AACnG,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,sFAAsF;AACtF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ,CAAC;IACvC,OAAO;QACL;YACE,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,EAAE,oBAAoB,EAAE,YAAY,EAAE;YACpD,OAAO,EAAE,CAAC,kDAAkD,CAAC;YAC7D,MAAM,EAAE;;;;;;;;;MASR;YACA,OAAO,EAAE;;;;;;;CAOd;YACK,SAAS,EAAE;;;;;;;CAOhB;YACK,UAAU,EAAE,wDAAwD;SACrE;QACD;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,+BAA+B;YACrC,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,MAAM,EAAE;sDACwC;YAChD,OAAO,EAAE;;;;;;CAMd;YACK,UAAU,EAAE,wDAAwD;SACrE;QACD;YACE,EAAE,EAAE,cAAc;YAClB,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,iCAAiC;YACvC,YAAY,EAAE,EAAE,sBAAsB,EAAE,YAAY,EAAE;YACtD,OAAO,EAAE,CAAC,qDAAqD,CAAC;YAChE,MAAM,EAAE,GAAG;gBACT,CAAC,CAAC;;cAEI;gBACN,CAAC,CAAC;;cAEI;YACR,OAAO,EAAE;;;;iBAIE,GAAG,CAAC,CAAC,CAAC,iDAAiD,CAAC,CAAC,CAAC,wCAAwC;;CAElH;YACK,SAAS,EAAE,GAAG;gBACZ,CAAC,CAAC;;;;;;CAMT;gBACO,CAAC,CAAC;;;;;;CAMT;YACK,UAAU,EAAE,0BAA0B;SACvC;KACyC,CAAC;AAC/C,CAAC;AAGD,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAA+B,CAAC;AAEjE,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,EAAY;IAC1C,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** package.json reading
|
|
1
|
+
/** package.json reading and dependency additions for `e2e init`. */
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
declare const packageSchema: z.ZodObject<{
|
|
4
4
|
dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
@@ -6,6 +6,7 @@ declare const packageSchema: z.ZodObject<{
|
|
|
6
6
|
peerDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
7
7
|
optionalDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
8
8
|
packageManager: z.ZodOptional<z.ZodString>;
|
|
9
|
+
scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
9
10
|
}, z.core.$loose>;
|
|
10
11
|
type PackageManifest = z.infer<typeof packageSchema>;
|
|
11
12
|
/**
|
|
@@ -21,8 +22,11 @@ export declare function readPackage(cwd: string): {
|
|
|
21
22
|
peerDependencies?: Record<string, string> | undefined;
|
|
22
23
|
optionalDependencies?: Record<string, string> | undefined;
|
|
23
24
|
packageManager?: string | undefined;
|
|
25
|
+
scripts?: Record<string, string> | undefined;
|
|
24
26
|
};
|
|
25
27
|
};
|
|
28
|
+
/** Why a manifest failed to read: the JSON parser's own position, or the field that has the wrong shape. */
|
|
29
|
+
export declare function describeManifestError(cause: unknown): string;
|
|
26
30
|
/** Adds only missing dependencies to devDependencies and returns what was added. */
|
|
27
31
|
export declare function addDependencies(manifest: PackageManifest, dependencies: Readonly<Record<string, string>>): {
|
|
28
32
|
manifest: {
|
|
@@ -32,11 +36,23 @@ export declare function addDependencies(manifest: PackageManifest, dependencies:
|
|
|
32
36
|
peerDependencies?: Record<string, string> | undefined;
|
|
33
37
|
optionalDependencies?: Record<string, string> | undefined;
|
|
34
38
|
packageManager?: string | undefined;
|
|
39
|
+
scripts?: Record<string, string> | undefined;
|
|
40
|
+
};
|
|
41
|
+
additions: [string, string][];
|
|
42
|
+
};
|
|
43
|
+
/** Adds only missing scripts and returns what was added. */
|
|
44
|
+
export declare function addScripts(manifest: PackageManifest, scripts: Readonly<Record<string, string>>): {
|
|
45
|
+
manifest: {
|
|
46
|
+
[x: string]: unknown;
|
|
47
|
+
dependencies?: Record<string, string> | undefined;
|
|
48
|
+
devDependencies?: Record<string, string> | undefined;
|
|
49
|
+
peerDependencies?: Record<string, string> | undefined;
|
|
50
|
+
optionalDependencies?: Record<string, string> | undefined;
|
|
51
|
+
packageManager?: string | undefined;
|
|
52
|
+
scripts?: Record<string, string> | undefined;
|
|
35
53
|
};
|
|
36
54
|
additions: [string, string][];
|
|
37
55
|
};
|
|
38
|
-
/** The `packageManager` field wins, then a lockfile, then the manager that invoked the CLI, then npm. */
|
|
39
|
-
export declare function detectPackageManager(cwd: string, manifest: PackageManifest): string;
|
|
40
56
|
/** Serializes with the original manifest's indentation and newline convention. */
|
|
41
57
|
export declare function serializePackage(manifest: PackageManifest, original: string | undefined): string;
|
|
42
58
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../src/cli/init/package.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../src/cli/init/package.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAIpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,aAAa;;;;;;;iBAOjB,CAAC;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAErD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM;;;;;;;;;;;EAKtC;AAED,4GAA4G;AAC5G,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAO5D;AAQD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;;;;;;;;;;;EAOxG;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;;;;;;;;;;;EAO9F;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIhG"}
|
package/dist/cli/init/package.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** package.json reading
|
|
1
|
+
/** package.json reading and dependency additions for `e2e init`. */
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { z } from 'zod';
|
|
@@ -9,15 +9,8 @@ const packageSchema = z.looseObject({
|
|
|
9
9
|
peerDependencies: dependencyBlock,
|
|
10
10
|
optionalDependencies: dependencyBlock,
|
|
11
11
|
packageManager: z.string().optional(),
|
|
12
|
+
scripts: z.record(z.string(), z.string()).optional(),
|
|
12
13
|
});
|
|
13
|
-
const PACKAGE_MANAGERS = new Set(['npm', 'pnpm', 'yarn', 'bun']);
|
|
14
|
-
const LOCKFILES = [
|
|
15
|
-
['pnpm-lock.yaml', 'pnpm'],
|
|
16
|
-
['yarn.lock', 'yarn'],
|
|
17
|
-
['bun.lock', 'bun'],
|
|
18
|
-
['bun.lockb', 'bun'],
|
|
19
|
-
['package-lock.json', 'npm'],
|
|
20
|
-
];
|
|
21
14
|
/**
|
|
22
15
|
* Reads and validates the manifest, keeping its original text so edits can
|
|
23
16
|
* preserve formatting. A missing manifest starts as a private ESM package.
|
|
@@ -28,6 +21,15 @@ export function readPackage(cwd) {
|
|
|
28
21
|
const manifest = packageSchema.parse(original === undefined ? { private: true, type: 'module' } : JSON.parse(original));
|
|
29
22
|
return { original, manifest };
|
|
30
23
|
}
|
|
24
|
+
/** Why a manifest failed to read: the JSON parser's own position, or the field that has the wrong shape. */
|
|
25
|
+
export function describeManifestError(cause) {
|
|
26
|
+
if (cause instanceof z.ZodError) {
|
|
27
|
+
return cause.issues
|
|
28
|
+
.map((issue) => `${issue.path.length === 0 ? 'package.json' : issue.path.join('.')}: ${issue.message}`)
|
|
29
|
+
.join('; ');
|
|
30
|
+
}
|
|
31
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
32
|
+
}
|
|
31
33
|
/** True when any dependency section lists `name`, so existing versions and workspace links are kept. */
|
|
32
34
|
function declaresDependency(manifest, name) {
|
|
33
35
|
return [manifest.dependencies, manifest.devDependencies, manifest.peerDependencies, manifest.optionalDependencies]
|
|
@@ -43,17 +45,15 @@ export function addDependencies(manifest, dependencies) {
|
|
|
43
45
|
additions,
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
|
-
/**
|
|
47
|
-
export function
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
const invoking = process.env['npm_config_user_agent']?.split('/')[0];
|
|
56
|
-
return invoking !== undefined && PACKAGE_MANAGERS.has(invoking) ? invoking : 'npm';
|
|
48
|
+
/** Adds only missing scripts and returns what was added. */
|
|
49
|
+
export function addScripts(manifest, scripts) {
|
|
50
|
+
const additions = Object.entries(scripts).filter(([name]) => manifest.scripts?.[name] === undefined);
|
|
51
|
+
if (additions.length === 0)
|
|
52
|
+
return { manifest, additions };
|
|
53
|
+
return {
|
|
54
|
+
manifest: { ...manifest, scripts: { ...manifest.scripts, ...Object.fromEntries(additions) } },
|
|
55
|
+
additions,
|
|
56
|
+
};
|
|
57
57
|
}
|
|
58
58
|
/** Serializes with the original manifest's indentation and newline convention. */
|
|
59
59
|
export function serializePackage(manifest, original) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../../src/cli/init/package.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../../src/cli/init/package.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
/** Composes common setup, the selected
|
|
3
|
-
export declare function createScaffold(
|
|
1
|
+
import { type EngineId } from './engines.ts';
|
|
2
|
+
/** Composes common setup, the selected engine, and optional AI support. */
|
|
3
|
+
export declare function createScaffold(engineId: EngineId, ai: boolean): {
|
|
4
4
|
dependencies: {
|
|
5
5
|
'@e2edev/e2e': string;
|
|
6
6
|
ai?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/cli/init/scaffold.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/cli/init/scaffold.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAS9D,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO;;;;;;;;EA2B7D"}
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import { packageVersion } from '../../internal/package-version.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getEnginePreset } from './engines.js';
|
|
3
3
|
const AGENT_IMPORT = "import { createAgent } from '@e2edev/e2e/agent';";
|
|
4
4
|
const AGENT_CONFIG = ` // The model comes from E2E_MODEL; authenticate with E2E_MODEL_API_KEY.
|
|
5
|
+
// To call a provider directly, pass an AI SDK model: createAgent({ model: openai('gpt-5.4-mini') }).
|
|
5
6
|
agent: createAgent({
|
|
6
7
|
system: 'You are a thorough QA agent. Verify every outcome.',
|
|
7
8
|
}),`;
|
|
8
|
-
/** Composes common setup, the selected
|
|
9
|
-
export function createScaffold(
|
|
10
|
-
const
|
|
9
|
+
/** Composes common setup, the selected engine, and optional AI support. */
|
|
10
|
+
export function createScaffold(engineId, ai) {
|
|
11
|
+
const engine = getEnginePreset(engineId);
|
|
11
12
|
const imports = [
|
|
12
|
-
"import {
|
|
13
|
+
"import type { E2EConfig } from '@e2edev/e2e';",
|
|
13
14
|
...(ai ? [AGENT_IMPORT] : []),
|
|
14
|
-
...
|
|
15
|
+
...engine.imports,
|
|
15
16
|
];
|
|
16
17
|
const configFields = [
|
|
17
18
|
...(ai ? [AGENT_CONFIG] : []),
|
|
18
|
-
|
|
19
|
+
engine.config,
|
|
19
20
|
];
|
|
20
21
|
return {
|
|
21
22
|
dependencies: {
|
|
22
23
|
'@e2edev/e2e': `^${packageVersion(import.meta.url, '../../../package.json', '0.0.0')}`,
|
|
23
|
-
...
|
|
24
|
+
...engine.dependencies,
|
|
24
25
|
...(ai ? { ai: '^7.0.0' } : {}),
|
|
25
26
|
},
|
|
26
27
|
config: `${imports.join('\n')}
|
|
27
28
|
|
|
28
|
-
export default
|
|
29
|
+
export default {
|
|
29
30
|
${configFields.join('\n')}
|
|
30
|
-
}
|
|
31
|
+
} satisfies E2EConfig;
|
|
31
32
|
`,
|
|
32
|
-
example:
|
|
33
|
-
runCommand:
|
|
33
|
+
example: engine.example + (ai ? engine.aiExample ?? '' : ''),
|
|
34
|
+
runCommand: engine.runCommand,
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
//# sourceMappingURL=scaffold.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/cli/init/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/cli/init/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAiB,MAAM,cAAc,CAAC;AAE9D,MAAM,YAAY,GAAG,kDAAkD,CAAC;AACxE,MAAM,YAAY,GAAG;;;;MAIf,CAAC;AAEP,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,QAAkB,EAAE,EAAW;IAC5D,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG;QACd,+CAA+C;QAC/C,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,GAAG,MAAM,CAAC,OAAO;KAClB,CAAC;IACF,MAAM,YAAY,GAAG;QACnB,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM;KACd,CAAC;IAEF,OAAO;QACL,YAAY,EAAE;YACZ,aAAa,EAAE,IAAI,cAAc,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,uBAAuB,EAAE,OAAO,CAAC,EAAE;YACtF,GAAG,MAAM,CAAC,YAAY;YACtB,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC;QACD,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAG/B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;CAExB;QACG,OAAO,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC"}
|
package/dist/cli/init.d.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
/** Non-destructive project scaffolding
|
|
1
|
+
/** Non-destructive project scaffolding. */
|
|
2
2
|
export interface InitOptions {
|
|
3
3
|
yes?: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* The directory argument as the user typed it, when `cwd` was chosen from
|
|
6
|
+
* one; the closing `next:` line then starts with `cd` into it.
|
|
7
|
+
*/
|
|
8
|
+
directory?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Whether prompts can be answered. The CLI passes its terminal state; a
|
|
11
|
+
* non-interactive run without `--yes` stops before asking anything, since
|
|
12
|
+
* a prompt nobody can answer would otherwise wait forever.
|
|
13
|
+
*/
|
|
14
|
+
interactive?: boolean;
|
|
4
15
|
}
|
|
5
16
|
/**
|
|
6
17
|
* Runs `e2e init`. Every prompt happens before the first write, existing
|
|
7
18
|
* config and test files are never touched, and dependencies install only when
|
|
8
|
-
* the user asks.
|
|
19
|
+
* the user asks. The agent skill is offered once; later runs refresh the
|
|
20
|
+
* copies that exist and never add new locations.
|
|
9
21
|
*/
|
|
10
22
|
export declare function init(cwd: string, options?: InitOptions): Promise<number>;
|
|
11
23
|
//# sourceMappingURL=init.d.ts.map
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAgB3C,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAiBD;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoKlF"}
|
package/dist/cli/init.js
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
|
-
/** Non-destructive project scaffolding
|
|
1
|
+
/** Non-destructive project scaffolding. */
|
|
2
2
|
import * as clack from '@clack/prompts';
|
|
3
3
|
import { spawnSync } from 'node:child_process';
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import os from 'node:os';
|
|
5
6
|
import path from 'node:path';
|
|
6
7
|
import { esmPackageHint } from '../config/esm.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { detectPackageManager } from '../internal/package-manager.js';
|
|
9
|
+
import { DOCS_URL } from './docs-url.js';
|
|
10
|
+
import { findInstalledSkillDirs, planSkillInstall, SKILL_LOCATIONS } from './init/agent-skill.js';
|
|
11
|
+
import { getEnginePresets, DEFAULT_ENGINE_ID } from './init/engines.js';
|
|
12
|
+
import { addDependencies, addScripts, describeManifestError, readPackage, serializePackage } from './init/package.js';
|
|
9
13
|
import { createScaffold } from './init/scaffold.js';
|
|
14
|
+
import { MISSING_SKILL_MESSAGE, readSkillFiles } from './skill.js';
|
|
15
|
+
const CACHE_IGNORE_ENTRY = '.e2e/cache/';
|
|
10
16
|
const GITIGNORE_ENTRIES = [
|
|
11
17
|
'node_modules/',
|
|
12
18
|
'.e2e/artifacts/',
|
|
13
|
-
|
|
19
|
+
CACHE_IGNORE_ENTRY,
|
|
14
20
|
'.e2e/sessions/',
|
|
15
21
|
'.e2e/report.json',
|
|
16
22
|
'.e2e/ai-trace.json',
|
|
17
23
|
'.e2e/junit.xml',
|
|
24
|
+
'.e2e/logs/',
|
|
18
25
|
];
|
|
26
|
+
const SCRIPTS = { 'test:e2e': 'e2e run' };
|
|
19
27
|
/**
|
|
20
28
|
* Runs `e2e init`. Every prompt happens before the first write, existing
|
|
21
29
|
* config and test files are never touched, and dependencies install only when
|
|
22
|
-
* the user asks.
|
|
30
|
+
* the user asks. The agent skill is offered once; later runs refresh the
|
|
31
|
+
* copies that exist and never add new locations.
|
|
23
32
|
*/
|
|
24
33
|
export async function init(cwd, options = {}) {
|
|
25
|
-
clack.intro('e2e init');
|
|
34
|
+
clack.intro(options.directory === undefined ? 'e2e init' : `e2e init ${options.directory}`);
|
|
35
|
+
if (options.interactive === false && !options.yes) {
|
|
36
|
+
clack.log.error('e2e init asks questions and needs an interactive terminal; run it from a terminal, or pass --yes to accept the defaults (Playwright, AI on, no installation)');
|
|
37
|
+
return 2;
|
|
38
|
+
}
|
|
39
|
+
if (existsSync(cwd) && !statSync(cwd).isDirectory()) {
|
|
40
|
+
clack.log.error(`${options.directory ?? cwd} is a file, not a directory`);
|
|
41
|
+
return 2;
|
|
42
|
+
}
|
|
26
43
|
let pkg;
|
|
27
44
|
try {
|
|
28
45
|
pkg = readPackage(cwd);
|
|
29
46
|
}
|
|
30
|
-
catch {
|
|
31
|
-
clack.log.error('
|
|
47
|
+
catch (cause) {
|
|
48
|
+
clack.log.error(`${path.join(cwd, 'package.json')} could not be read: ${describeManifestError(cause)}; fix it before running e2e init`);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
const bundledSkill = readSkillFiles();
|
|
52
|
+
if (bundledSkill.length === 0) {
|
|
53
|
+
clack.log.error(MISSING_SKILL_MESSAGE);
|
|
32
54
|
return 2;
|
|
33
55
|
}
|
|
34
56
|
const existingConfig = ['e2e.config.ts', 'e2e.config.mts'].find((file) => existsSync(path.join(cwd, file)));
|
|
@@ -47,49 +69,73 @@ export async function init(cwd, options = {}) {
|
|
|
47
69
|
const existingIgnore = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : '';
|
|
48
70
|
const ignoreLines = existingIgnore.split(/\r?\n/);
|
|
49
71
|
const missingIgnore = GITIGNORE_ENTRIES.filter((entry) => !ignoreLines.includes(entry));
|
|
50
|
-
//
|
|
51
|
-
let
|
|
72
|
+
// Engine and AI are choices for a new config only; an existing config keeps its own dependencies.
|
|
73
|
+
let engine = existingConfig === undefined ? DEFAULT_ENGINE_ID : 'none';
|
|
52
74
|
let ai = existingConfig === undefined;
|
|
53
75
|
if (existingConfig === undefined && !options.yes) {
|
|
54
|
-
const
|
|
55
|
-
message: 'Which
|
|
56
|
-
initialValue:
|
|
57
|
-
options:
|
|
76
|
+
const selectedEngine = await clack.select({
|
|
77
|
+
message: 'Which engine?',
|
|
78
|
+
initialValue: DEFAULT_ENGINE_ID,
|
|
79
|
+
options: getEnginePresets().map(({ id, label, hint }) => ({ value: id, label, hint })),
|
|
58
80
|
});
|
|
59
|
-
if (clack.isCancel(
|
|
81
|
+
if (clack.isCancel(selectedEngine))
|
|
60
82
|
return cancelled();
|
|
61
|
-
|
|
83
|
+
engine = selectedEngine;
|
|
62
84
|
const enableAi = await clack.confirm({ message: 'Enable AI testing? Adds AI SDK v7.', initialValue: true });
|
|
63
85
|
if (clack.isCancel(enableAi))
|
|
64
86
|
return cancelled();
|
|
65
87
|
ai = enableAi;
|
|
66
88
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
89
|
+
// The skill goes where an earlier run put it; a project without one chooses.
|
|
90
|
+
let skillDirs = findInstalledSkillDirs(cwd);
|
|
91
|
+
if (skillDirs.length === 0) {
|
|
92
|
+
if (options.yes) {
|
|
93
|
+
skillDirs = SKILL_LOCATIONS.map((location) => location.dir);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
const selected = await clack.multiselect({
|
|
97
|
+
message: 'Install the e2e skill for coding agents?',
|
|
98
|
+
options: SKILL_LOCATIONS.map(({ dir, hint }) => ({ value: dir, label: dir, hint })),
|
|
99
|
+
initialValues: SKILL_LOCATIONS.map((location) => location.dir),
|
|
100
|
+
required: false,
|
|
101
|
+
});
|
|
102
|
+
if (clack.isCancel(selected))
|
|
103
|
+
return cancelled();
|
|
104
|
+
skillDirs = selected;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const skillInstalls = planSkillInstall(cwd, skillDirs, bundledSkill);
|
|
108
|
+
const scaffold = createScaffold(engine, ai);
|
|
109
|
+
const dependencies = addDependencies(pkg.manifest, scaffold.dependencies);
|
|
110
|
+
const { manifest, additions: scripts } = addScripts(dependencies.manifest, SCRIPTS);
|
|
111
|
+
if (dependencies.additions.length > 0) {
|
|
112
|
+
clack.log.info(`add dev dependencies: ${dependencies.additions.map(([name, version]) => `${name}@${version}`).join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
if (scripts.length > 0) {
|
|
115
|
+
clack.log.info(`add scripts: ${scripts.map(([name, command]) => `${name} (${command})`).join(', ')}`);
|
|
71
116
|
}
|
|
72
117
|
const files = [
|
|
73
|
-
...(pkg.original === undefined || additions.length > 0
|
|
118
|
+
...(pkg.original === undefined || dependencies.additions.length > 0 || scripts.length > 0
|
|
74
119
|
? [{ relative: 'package.json', content: serializePackage(manifest, pkg.original), existing: pkg.original !== undefined }]
|
|
75
120
|
: []),
|
|
76
121
|
...(existingConfig === undefined ? [{ relative: 'e2e.config.ts', content: scaffold.config, existing: false }] : []),
|
|
77
122
|
...(exampleExists ? [] : [{ relative: examplePath, content: scaffold.example, existing: false }]),
|
|
78
123
|
];
|
|
79
|
-
if (files.length === 0 && missingIgnore.length === 0) {
|
|
124
|
+
if (files.length === 0 && skillInstalls.length === 0 && missingIgnore.length === 0) {
|
|
80
125
|
clack.outro('nothing to create; project already initialized');
|
|
81
126
|
return 0;
|
|
82
127
|
}
|
|
83
128
|
if (!options.yes) {
|
|
84
129
|
const actions = [
|
|
85
130
|
...files.map((file) => `${file.existing ? 'update' : 'create'} ${file.relative}`),
|
|
131
|
+
...skillInstalls.map((install) => `${install.existing ? 'update' : 'create'} ${install.relative}/`),
|
|
86
132
|
...(missingIgnore.length > 0 ? ['update .gitignore'] : []),
|
|
87
133
|
];
|
|
88
134
|
const proceed = await clack.confirm({ message: `${actions.join(', ')}?` });
|
|
89
135
|
if (clack.isCancel(proceed) || !proceed)
|
|
90
136
|
return cancelled();
|
|
91
137
|
}
|
|
92
|
-
const manager = detectPackageManager(cwd, manifest);
|
|
138
|
+
const manager = detectPackageManager(cwd, manifest.packageManager);
|
|
93
139
|
let install = false;
|
|
94
140
|
if (!options.yes) {
|
|
95
141
|
const selected = await clack.confirm({ message: `Install dependencies with ${manager}?`, initialValue: true });
|
|
@@ -97,16 +143,31 @@ export async function init(cwd, options = {}) {
|
|
|
97
143
|
return cancelled();
|
|
98
144
|
install = selected;
|
|
99
145
|
}
|
|
146
|
+
// The first write; a directory named on the command line comes into being here.
|
|
147
|
+
mkdirSync(cwd, { recursive: true });
|
|
100
148
|
for (const file of files) {
|
|
101
149
|
const absolute = path.join(cwd, file.relative);
|
|
102
150
|
mkdirSync(path.dirname(absolute), { recursive: true });
|
|
103
151
|
writeFileSync(absolute, file.content, 'utf8');
|
|
104
152
|
clack.log.success(`${file.existing ? 'updated' : 'created'} ${file.relative}`);
|
|
105
153
|
}
|
|
154
|
+
for (const skill of skillInstalls) {
|
|
155
|
+
for (const file of skill.files) {
|
|
156
|
+
mkdirSync(path.dirname(file.absolute), { recursive: true });
|
|
157
|
+
writeFileSync(file.absolute, file.content, 'utf8');
|
|
158
|
+
}
|
|
159
|
+
clack.log.success(`${skill.existing ? 'updated' : 'created'} ${skill.relative}/ (${skill.files.length} files)`);
|
|
160
|
+
}
|
|
161
|
+
if (skillDirs.length === 0) {
|
|
162
|
+
clack.log.info('skipped the agent skill; agents can still print it with npx --no-install e2e guide');
|
|
163
|
+
}
|
|
106
164
|
if (missingIgnore.length > 0) {
|
|
107
165
|
const prefix = existingIgnore === '' || existingIgnore.endsWith('\n') ? '' : '\n';
|
|
108
166
|
writeFileSync(gitignorePath, `${existingIgnore}${prefix}${missingIgnore.join('\n')}\n`, 'utf8');
|
|
109
167
|
clack.log.success(`updated .gitignore (${missingIgnore.length} entries)`);
|
|
168
|
+
if (missingIgnore.includes(CACHE_IGNORE_ENTRY)) {
|
|
169
|
+
clack.log.info(`${CACHE_IGNORE_ENTRY} is ignored; committing agent.act replays is opt-in, see ${DOCS_URL}/reference/config#commit-your-traces`);
|
|
170
|
+
}
|
|
110
171
|
}
|
|
111
172
|
if (install) {
|
|
112
173
|
const result = spawnSync(manager, ['install'], { cwd, stdio: 'inherit', shell: process.platform === 'win32' });
|
|
@@ -117,9 +178,27 @@ export async function init(cwd, options = {}) {
|
|
|
117
178
|
return result.signal === 'SIGINT' ? 130 : 2;
|
|
118
179
|
}
|
|
119
180
|
}
|
|
120
|
-
|
|
181
|
+
if (!existsSync(path.join(cwd, 'tsconfig.json'))) {
|
|
182
|
+
clack.log.info('no tsconfig.json; add one for editor completions on e2e.config.ts and tests/');
|
|
183
|
+
}
|
|
184
|
+
const next = [
|
|
185
|
+
options.directory === undefined ? undefined : `cd ${shellArgument(options.directory)}`,
|
|
186
|
+
install ? undefined : `${manager} install`,
|
|
187
|
+
scaffold.runCommand,
|
|
188
|
+
].filter((step) => step !== undefined);
|
|
189
|
+
clack.outro(`next: ${next.join(', then ')}`);
|
|
121
190
|
return 0;
|
|
122
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* A path as the user will paste it into their shell: bare while every character
|
|
194
|
+
* is safe, otherwise quoted for the platform (single quotes for POSIX shells,
|
|
195
|
+
* double quotes for cmd and PowerShell), so `apps/my web` stays one argument.
|
|
196
|
+
*/
|
|
197
|
+
function shellArgument(value) {
|
|
198
|
+
if (/^[A-Za-z0-9_./@%+=:,-]+$/.test(value))
|
|
199
|
+
return value;
|
|
200
|
+
return os.platform() === 'win32' ? `"${value.replaceAll('"', '""')}"` : `'${value.replaceAll("'", "'\\''")}'`;
|
|
201
|
+
}
|
|
123
202
|
/** Cancellation is only reachable before the first write, so nothing needs undoing. */
|
|
124
203
|
function cancelled() {
|
|
125
204
|
clack.cancel('cancelled; no changes were made');
|