@e2edev/e2e 0.3.0 → 0.4.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.
Files changed (134) hide show
  1. package/README.md +32 -3
  2. package/dist/agent/act.d.ts.map +1 -1
  3. package/dist/agent/act.js +38 -46
  4. package/dist/agent/act.js.map +1 -1
  5. package/dist/agent/default-agent.d.ts.map +1 -1
  6. package/dist/agent/default-agent.js +10 -23
  7. package/dist/agent/default-agent.js.map +1 -1
  8. package/dist/agent/executor.d.ts +6 -0
  9. package/dist/agent/executor.d.ts.map +1 -1
  10. package/dist/agent/executor.js.map +1 -1
  11. package/dist/agent/invocation.d.ts +1 -6
  12. package/dist/agent/invocation.d.ts.map +1 -1
  13. package/dist/agent/invocation.js +4 -30
  14. package/dist/agent/invocation.js.map +1 -1
  15. package/dist/agent/observation.d.ts +2 -0
  16. package/dist/agent/observation.d.ts.map +1 -1
  17. package/dist/agent/observation.js +1 -0
  18. package/dist/agent/observation.js.map +1 -1
  19. package/dist/agent/public.d.ts +1 -1
  20. package/dist/agent/public.d.ts.map +1 -1
  21. package/dist/agent/public.js +1 -1
  22. package/dist/agent/public.js.map +1 -1
  23. package/dist/agent/step-cache.d.ts +2 -2
  24. package/dist/agent/step-cache.d.ts.map +1 -1
  25. package/dist/agent/step-cache.js +2 -2
  26. package/dist/agent/step-cache.js.map +1 -1
  27. package/dist/agent/tool.d.ts +11 -16
  28. package/dist/agent/tool.d.ts.map +1 -1
  29. package/dist/agent/tool.js +19 -13
  30. package/dist/agent/tool.js.map +1 -1
  31. package/dist/agent/usage.d.ts +27 -0
  32. package/dist/agent/usage.d.ts.map +1 -0
  33. package/dist/agent/usage.js +54 -0
  34. package/dist/agent/usage.js.map +1 -0
  35. package/dist/backend/index.d.ts +22 -5
  36. package/dist/backend/index.d.ts.map +1 -1
  37. package/dist/backend/index.js +2 -1
  38. package/dist/backend/index.js.map +1 -1
  39. package/dist/backend/session.d.ts.map +1 -1
  40. package/dist/backend/session.js +1 -0
  41. package/dist/backend/session.js.map +1 -1
  42. package/dist/backend/surface.d.ts +2 -0
  43. package/dist/backend/surface.d.ts.map +1 -1
  44. package/dist/backend/timing.d.ts +3 -0
  45. package/dist/backend/timing.d.ts.map +1 -0
  46. package/dist/backend/timing.js +8 -0
  47. package/dist/backend/timing.js.map +1 -0
  48. package/dist/cli/index.js +4 -4
  49. package/dist/cli/index.js.map +1 -1
  50. package/dist/cli/init/backends.d.ts +75 -0
  51. package/dist/cli/init/backends.d.ts.map +1 -0
  52. package/dist/cli/init/backends.js +98 -0
  53. package/dist/cli/init/backends.js.map +1 -0
  54. package/dist/cli/init/package.d.ts +43 -0
  55. package/dist/cli/init/package.d.ts.map +1 -0
  56. package/dist/cli/init/package.js +64 -0
  57. package/dist/cli/init/package.js.map +1 -0
  58. package/dist/cli/init/scaffold.d.ts +12 -0
  59. package/dist/cli/init/scaffold.d.ts.map +1 -0
  60. package/dist/cli/init/scaffold.js +36 -0
  61. package/dist/cli/init/scaffold.js.map +1 -0
  62. package/dist/cli/init.d.ts +8 -3
  63. package/dist/cli/init.d.ts.map +1 -1
  64. package/dist/cli/init.js +98 -94
  65. package/dist/cli/init.js.map +1 -1
  66. package/dist/config/app.d.ts +50 -0
  67. package/dist/config/app.d.ts.map +1 -0
  68. package/dist/config/app.js +168 -0
  69. package/dist/config/app.js.map +1 -0
  70. package/dist/config/esm.d.ts +4 -0
  71. package/dist/config/esm.d.ts.map +1 -0
  72. package/dist/config/esm.js +35 -0
  73. package/dist/config/esm.js.map +1 -0
  74. package/dist/config/load.d.ts.map +1 -1
  75. package/dist/config/load.js +4 -0
  76. package/dist/config/load.js.map +1 -1
  77. package/dist/config/resolve.d.ts +6 -15
  78. package/dist/config/resolve.d.ts.map +1 -1
  79. package/dist/config/resolve.js +18 -100
  80. package/dist/config/resolve.js.map +1 -1
  81. package/dist/config/validate.d.ts +3 -1
  82. package/dist/config/validate.d.ts.map +1 -1
  83. package/dist/config/validate.js +17 -1
  84. package/dist/config/validate.js.map +1 -1
  85. package/dist/internal/time.d.ts +6 -1
  86. package/dist/internal/time.d.ts.map +1 -1
  87. package/dist/internal/time.js +25 -2
  88. package/dist/internal/time.js.map +1 -1
  89. package/dist/report/build.js +2 -2
  90. package/dist/report/build.js.map +1 -1
  91. package/dist/report/junit.d.ts +11 -0
  92. package/dist/report/junit.d.ts.map +1 -0
  93. package/dist/report/junit.js +202 -0
  94. package/dist/report/junit.js.map +1 -0
  95. package/dist/report/list.d.ts.map +1 -1
  96. package/dist/report/list.js +3 -0
  97. package/dist/report/list.js.map +1 -1
  98. package/dist/report/write.d.ts +2 -0
  99. package/dist/report/write.d.ts.map +1 -1
  100. package/dist/report/write.js +7 -3
  101. package/dist/report/write.js.map +1 -1
  102. package/dist/run/events.d.ts +2 -0
  103. package/dist/run/events.d.ts.map +1 -1
  104. package/dist/run/events.js.map +1 -1
  105. package/dist/run/fixture-legacy.d.ts +36 -0
  106. package/dist/run/fixture-legacy.d.ts.map +1 -0
  107. package/dist/run/fixture-legacy.js +143 -0
  108. package/dist/run/fixture-legacy.js.map +1 -0
  109. package/dist/run/fixture-recording.d.ts +15 -0
  110. package/dist/run/fixture-recording.d.ts.map +1 -0
  111. package/dist/run/fixture-recording.js +75 -0
  112. package/dist/run/fixture-recording.js.map +1 -0
  113. package/dist/run/fixtures.d.ts.map +1 -1
  114. package/dist/run/fixtures.js +26 -162
  115. package/dist/run/fixtures.js.map +1 -1
  116. package/dist/run/managed-process.d.ts +49 -0
  117. package/dist/run/managed-process.d.ts.map +1 -0
  118. package/dist/run/managed-process.js +202 -0
  119. package/dist/run/managed-process.js.map +1 -0
  120. package/dist/run/runner.d.ts +3 -1
  121. package/dist/run/runner.d.ts.map +1 -1
  122. package/dist/run/runner.js +62 -12
  123. package/dist/run/runner.js.map +1 -1
  124. package/dist/run/steps.d.ts +1 -1
  125. package/dist/run/steps.d.ts.map +1 -1
  126. package/dist/run/steps.js +12 -9
  127. package/dist/run/steps.js.map +1 -1
  128. package/dist/types.d.ts +33 -1
  129. package/dist/types.d.ts.map +1 -1
  130. package/package.json +2 -2
  131. package/dist/run/app-process.d.ts +0 -18
  132. package/dist/run/app-process.d.ts.map +0 -1
  133. package/dist/run/app-process.js +0 -112
  134. package/dist/run/app-process.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAuD5D,iFAAiF;AACjF,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAqExF"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAW5D,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAYD;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsGlF"}
package/dist/cli/init.js CHANGED
@@ -1,124 +1,128 @@
1
1
  /** Non-destructive project scaffolding (spec 06-cli.md). */
2
+ import * as clack from '@clack/prompts';
3
+ import { spawnSync } from 'node:child_process';
2
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
5
  import path from 'node:path';
4
- import * as clack from '@clack/prompts';
5
- const CONFIG_TEMPLATE = `import { defineConfig } from '@e2edev/e2e';
6
- import { createAgent } from '@e2edev/e2e/agent';
7
- import { playwright } from '@e2edev/playwright';
8
-
9
- export default defineConfig({
10
- // A scheme is optional: localhost gets http://, any other host gets https://.
11
- app: { url: 'localhost:3000' },
12
- // The built-in agent; its model comes from E2E_MODEL. Shape it with system,
13
- // hand it tools, or pass any StepExecutor of your own instead.
14
- agent: createAgent({
15
- system: 'You are a thorough QA agent. Verify every outcome on screen.',
16
- }),
17
- // The runner knows no platform: every target names the backend that drives it.
18
- targets: [{ name: 'web', platform: 'web', backend: playwright() }],
19
- });
20
- `;
21
- /** The AI SDK is an optional peer; the scaffolded agent cannot run without it. */
22
- const AGENT_PEER = 'ai';
23
- const EXAMPLE_TEMPLATE = `import { test } from '@e2edev/playwright';
24
- import { expect } from '@e2edev/e2e';
25
-
26
- test('app opens', async ({ app, web }) => {
27
- await app.open();
28
- await expect(web).toHaveURL('/');
29
- });
30
-
31
- // Runs when E2E_MODEL and E2E_MODEL_API_KEY are set:
32
- // test('the agent drives a flow', async ({ app, agent }) => {
33
- // await app.open();
34
- // await agent.act('one goal in plain language');
35
- // await agent.assert('one question about the screen');
36
- // });
37
- `;
6
+ import { esmPackageHint } from '../config/esm.js';
7
+ import { getBackendPresets, DEFAULT_BACKEND_ID } from './init/backends.js';
8
+ import { addDependencies, detectPackageManager, readPackage, serializePackage } from './init/package.js';
9
+ import { createScaffold } from './init/scaffold.js';
38
10
  const GITIGNORE_ENTRIES = [
11
+ 'node_modules/',
39
12
  '.e2e/artifacts/',
40
13
  '.e2e/cache/',
41
14
  '.e2e/sessions/',
42
15
  '.e2e/report.json',
43
16
  '.e2e/ai-trace.json',
17
+ '.e2e/junit.xml',
44
18
  ];
45
- /** Runs `e2e init`. Creates only missing files and stops before any conflict. */
19
+ /**
20
+ * Runs `e2e init`. Every prompt happens before the first write, existing
21
+ * config and test files are never touched, and dependencies install only when
22
+ * the user asks.
23
+ */
46
24
  export async function init(cwd, options = {}) {
47
25
  clack.intro('e2e init');
48
- const planned = [
49
- { relative: 'e2e.config.ts', content: CONFIG_TEMPLATE },
50
- { relative: path.join('tests', 'example.e2e.ts'), content: EXAMPLE_TEMPLATE },
51
- ];
52
- const exists = (file) => existsSync(path.join(cwd, file.relative));
53
- const conflicts = planned.filter(exists);
54
- const remaining = planned.filter((file) => !exists(file));
55
- for (const conflict of conflicts) {
56
- clack.log.warn(`exists, not touching: ${conflict.relative}`);
26
+ let pkg;
27
+ try {
28
+ pkg = readPackage(cwd);
29
+ }
30
+ catch {
31
+ clack.log.error('invalid package.json; fix it before running e2e init');
32
+ return 2;
33
+ }
34
+ const existingConfig = ['e2e.config.ts', 'e2e.config.mts'].find((file) => existsSync(path.join(cwd, file)));
35
+ const examplePath = path.join('tests', 'example.e2e.ts');
36
+ const exampleExists = existsSync(path.join(cwd, examplePath));
37
+ if (existingConfig !== undefined)
38
+ clack.log.warn(`exists, not touching: ${existingConfig}`);
39
+ if (exampleExists)
40
+ clack.log.warn(`exists, not touching: ${examplePath}`);
41
+ if (pkg.original !== undefined) {
42
+ const hint = esmPackageHint(path.join(cwd, existingConfig ?? 'e2e.config.ts'));
43
+ if (hint !== undefined)
44
+ clack.log.warn(hint);
57
45
  }
58
- // The ignore list is reconciled on every run, not only the first: a project
59
- // initialized before an entry existed (`.e2e/ai-trace.json`, say) picks it
60
- // up by re-running init, without touching any scaffold file.
61
46
  const gitignorePath = path.join(cwd, '.gitignore');
62
- const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : '';
63
- // A CRLF .gitignore must not re-append every entry on each init.
64
- const lines = existing.split(/\r?\n/);
65
- const missing = GITIGNORE_ENTRIES.filter((entry) => !lines.includes(entry));
66
- if (remaining.length === 0 && missing.length === 0) {
47
+ const existingIgnore = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : '';
48
+ const ignoreLines = existingIgnore.split(/\r?\n/);
49
+ const missingIgnore = GITIGNORE_ENTRIES.filter((entry) => !ignoreLines.includes(entry));
50
+ // Backend and AI are choices for a new config only; an existing config keeps its own dependencies.
51
+ let backend = DEFAULT_BACKEND_ID;
52
+ let ai = existingConfig === undefined;
53
+ if (existingConfig === undefined && !options.yes) {
54
+ const selectedBackend = await clack.select({
55
+ message: 'Which backend?',
56
+ initialValue: DEFAULT_BACKEND_ID,
57
+ options: getBackendPresets().map(({ id, label, hint }) => ({ value: id, label, hint })),
58
+ });
59
+ if (clack.isCancel(selectedBackend))
60
+ return cancelled();
61
+ backend = selectedBackend;
62
+ const enableAi = await clack.confirm({ message: 'Enable AI testing? Adds AI SDK v7.', initialValue: true });
63
+ if (clack.isCancel(enableAi))
64
+ return cancelled();
65
+ ai = enableAi;
66
+ }
67
+ const scaffold = createScaffold(backend, ai);
68
+ const { manifest, additions } = addDependencies(pkg.manifest, scaffold.dependencies);
69
+ if (additions.length > 0) {
70
+ clack.log.info(`add dev dependencies: ${additions.map(([name, version]) => `${name}@${version}`).join(', ')}`);
71
+ }
72
+ const files = [
73
+ ...(pkg.original === undefined || additions.length > 0
74
+ ? [{ relative: 'package.json', content: serializePackage(manifest, pkg.original), existing: pkg.original !== undefined }]
75
+ : []),
76
+ ...(existingConfig === undefined ? [{ relative: 'e2e.config.ts', content: scaffold.config, existing: false }] : []),
77
+ ...(exampleExists ? [] : [{ relative: examplePath, content: scaffold.example, existing: false }]),
78
+ ];
79
+ if (files.length === 0 && missingIgnore.length === 0) {
67
80
  clack.outro('nothing to create; project already initialized');
68
81
  return 0;
69
82
  }
70
- if (options.yes !== true) {
83
+ if (!options.yes) {
71
84
  const actions = [
72
- ...(remaining.length === 0
73
- ? []
74
- : [`create ${remaining.map((file) => file.relative).join(', ')}`]),
75
- ...(missing.length === 0 ? [] : ['update .gitignore']),
85
+ ...files.map((file) => `${file.existing ? 'update' : 'create'} ${file.relative}`),
86
+ ...(missingIgnore.length > 0 ? ['update .gitignore'] : []),
76
87
  ];
77
- const proceed = await clack.confirm({ message: `${actions.join(' and ')}?` });
78
- if (clack.isCancel(proceed) || proceed !== true) {
79
- clack.cancel('cancelled; no changes were made');
80
- return 0;
81
- }
88
+ const proceed = await clack.confirm({ message: `${actions.join(', ')}?` });
89
+ if (clack.isCancel(proceed) || !proceed)
90
+ return cancelled();
91
+ }
92
+ const manager = detectPackageManager(cwd, manifest);
93
+ let install = false;
94
+ if (!options.yes) {
95
+ const selected = await clack.confirm({ message: `Install dependencies with ${manager}?`, initialValue: true });
96
+ if (clack.isCancel(selected))
97
+ return cancelled();
98
+ install = selected;
82
99
  }
83
- for (const file of remaining) {
100
+ for (const file of files) {
84
101
  const absolute = path.join(cwd, file.relative);
85
102
  mkdirSync(path.dirname(absolute), { recursive: true });
86
103
  writeFileSync(absolute, file.content, 'utf8');
87
- clack.log.success(`created ${file.relative}`);
88
- }
89
- if (remaining.some((file) => file.relative === 'e2e.config.ts') && !declaresDependency(cwd, AGENT_PEER)) {
90
- clack.log.warn(`e2e.config.ts constructs the built-in agent, which runs on the AI SDK: npm install --save-dev ${AGENT_PEER}`);
104
+ clack.log.success(`${file.existing ? 'updated' : 'created'} ${file.relative}`);
91
105
  }
92
- if (missing.length > 0) {
93
- const prefix = existing === '' || existing.endsWith('\n') ? '' : '\n';
94
- writeFileSync(gitignorePath, `${existing}${prefix}${missing.join('\n')}\n`, 'utf8');
95
- clack.log.success(`updated .gitignore (${missing.length} entries)`);
106
+ if (missingIgnore.length > 0) {
107
+ const prefix = existingIgnore === '' || existingIgnore.endsWith('\n') ? '' : '\n';
108
+ writeFileSync(gitignorePath, `${existingIgnore}${prefix}${missingIgnore.join('\n')}\n`, 'utf8');
109
+ clack.log.success(`updated .gitignore (${missingIgnore.length} entries)`);
96
110
  }
97
- if (remaining.length === 0) {
98
- clack.outro('project already initialized; .gitignore brought up to date');
99
- return 0;
111
+ if (install) {
112
+ const result = spawnSync(manager, ['install'], { cwd, stdio: 'inherit', shell: process.platform === 'win32' });
113
+ if (result.error !== undefined || result.status !== 0) {
114
+ const reason = result.error?.message ?? `exit ${result.status ?? result.signal}`;
115
+ clack.log.error(`installation failed (${reason}); retry with ${manager} install`);
116
+ clack.outro('scaffold saved');
117
+ return result.signal === 'SIGINT' ? 130 : 2;
118
+ }
100
119
  }
101
- clack.outro('next: point app.url in e2e.config.ts at your app, then npx --no-install e2e run');
120
+ clack.outro(`next: ${install ? '' : `${manager} install, then `}${scaffold.runCommand}`);
102
121
  return 0;
103
122
  }
104
- /** True when the project's package.json lists `name` as a dependency of any kind. */
105
- function declaresDependency(cwd, name) {
106
- const manifestPath = path.join(cwd, 'package.json');
107
- if (!existsSync(manifestPath))
108
- return false;
109
- let manifest;
110
- try {
111
- manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
112
- }
113
- catch {
114
- return false;
115
- }
116
- if (typeof manifest !== 'object' || manifest === null)
117
- return false;
118
- const record = manifest;
119
- return ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'].some((field) => {
120
- const block = record[field];
121
- return typeof block === 'object' && block !== null && name in block;
122
- });
123
+ /** Cancellation is only reachable before the first write, so nothing needs undoing. */
124
+ function cancelled() {
125
+ clack.cancel('cancelled; no changes were made');
126
+ return 0;
123
127
  }
124
128
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /** App, command, and service resolution (spec 05-config.md). */
2
+ import { type NormalizedBaseUrl } from '../internal/urls.ts';
3
+ import type { AppConfig, CommandConfig, E2EConfig } from '../types.ts';
4
+ /**
5
+ * How a spawned process counts as ready: a URL that answers, or the process
6
+ * itself exiting with code 0 (a migration, `docker compose up --wait`).
7
+ */
8
+ export type Readiness = {
9
+ readonly readyUrl: string;
10
+ } | {
11
+ readonly waitForExit: true;
12
+ };
13
+ /** A command the runner spawns, named for error messages. */
14
+ export interface ResolvedCommand {
15
+ readonly label: string;
16
+ readonly command: CommandConfig;
17
+ }
18
+ /** One `app.services` entry with its readiness contract already decided. */
19
+ export interface ResolvedService extends ResolvedCommand {
20
+ readonly readiness: Readiness;
21
+ readonly teardown: ResolvedCommand | undefined;
22
+ }
23
+ export interface ResolvedApp {
24
+ /** False when no app URL was configured and `base` is a synthetic loopback placeholder. */
25
+ readonly configured: boolean;
26
+ readonly base: NormalizedBaseUrl;
27
+ readonly readyUrl: string;
28
+ readonly allowedOrigins: readonly string[];
29
+ readonly environment: 'test' | 'staging' | 'production';
30
+ readonly command: CommandConfig | undefined;
31
+ /** Dependency processes started in order before `command` and torn down in reverse. */
32
+ readonly services: readonly ResolvedService[];
33
+ /** Stable logical app identity; overrides the origin for cache/session keying. */
34
+ readonly identity: string | undefined;
35
+ }
36
+ export declare function resolveApp(raw: E2EConfig, env: NodeJS.ProcessEnv): ResolvedApp;
37
+ /**
38
+ * Resolves `app.services`: every service is a command with exactly one
39
+ * readiness contract (`readyUrl` or `waitForExit`), and a `teardown` is a
40
+ * command of its own. The service fields that only steer the runner
41
+ * (`readyUrl`, `waitForExit`, `teardown`) are lifted out of the command.
42
+ */
43
+ export declare function resolveServices(raw: AppConfig['services']): readonly ResolvedService[];
44
+ /**
45
+ * The digest view of `app`: `app.command.env`, every service's env, and every
46
+ * service teardown's env become names, so no environment value contributes to
47
+ * the digest. Live values never appear under `app`, so nothing else changes.
48
+ */
49
+ export declare function digestApp(app: AppConfig): Record<string, unknown>;
50
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/config/app.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAGhE,OAAO,EAAwC,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnG,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAiB,MAAM,aAAa,CAAC;AAGtF;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAA;CAAE,CAAC;AAEvF,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;CACjC;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,WAAW,WAAW;IAC1B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAeD,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,WAAW,CAqF9E;AAuBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,GAAG,SAAS,eAAe,EAAE,CA6BtF;AAaD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAajE"}
@@ -0,0 +1,168 @@
1
+ /** App, command, and service resolution (spec 05-config.md). */
2
+ import { ConfigurationError } from '../internal/errors.js';
3
+ import { isImplicitTestHost, normalizeBaseUrl } from '../internal/urls.js';
4
+ import { httpUrl, positiveInt } from './validate.js';
5
+ const APP_KEYS = new Set([
6
+ 'url',
7
+ 'command',
8
+ 'readyUrl',
9
+ 'services',
10
+ 'allowedOrigins',
11
+ 'environment',
12
+ 'identity',
13
+ ]);
14
+ /** App keys that make sense without an app URL; every other key needs one. */
15
+ const URL_FREE_APP_KEYS = new Set(['url', 'command', 'services']);
16
+ export function resolveApp(raw, env) {
17
+ if (raw.app !== undefined) {
18
+ for (const key of Object.keys(raw.app)) {
19
+ if (!APP_KEYS.has(key)) {
20
+ throw new ConfigurationError('INVALID_CONFIG', `unknown app config key "${key}"`);
21
+ }
22
+ }
23
+ }
24
+ const services = resolveServices(raw.app?.services);
25
+ const rawUrl = raw.app?.url ?? env['APP_URL'];
26
+ if (rawUrl === undefined || rawUrl === '') {
27
+ // Not every surface has an app URL to point at (a device, a desktop
28
+ // shell): a synthetic loopback base keeps navigation resolution and
29
+ // identity digests defined, and `app.open()` fails loud with
30
+ // APP_URL_REQUIRED the moment a test actually needs one. A configured
31
+ // app command without a URL is still a mistake worth failing early on.
32
+ const orphaned = Object.keys(raw.app ?? {}).filter((key) => !URL_FREE_APP_KEYS.has(key));
33
+ if (orphaned.length > 0) {
34
+ throw new ConfigurationError('INVALID_CONFIG', `app.${orphaned[0]} requires app.url: set app.url in e2e.config.ts or the APP_URL environment variable`);
35
+ }
36
+ if (raw.app?.command === undefined) {
37
+ return {
38
+ configured: false,
39
+ base: normalizeBaseUrl('http://127.0.0.1:1'),
40
+ readyUrl: 'http://127.0.0.1:1/',
41
+ allowedOrigins: [],
42
+ environment: 'test',
43
+ command: undefined,
44
+ services,
45
+ identity: undefined,
46
+ };
47
+ }
48
+ throw new ConfigurationError('APP_URL_REQUIRED', 'an app URL is required alongside app.command: set app.url in e2e.config.ts or the APP_URL environment variable');
49
+ }
50
+ const base = normalizeBaseUrl(rawUrl);
51
+ const baseHost = new URL(base.href).hostname;
52
+ // The environment is a label for the report and the cache/session identity
53
+ // digest, not a gate: a loopback, `.localhost`, or `.test` host is `test`,
54
+ // any other host is `production` unless the config says otherwise.
55
+ const environment = raw.app?.environment ?? (isImplicitTestHost(baseHost) ? 'test' : 'production');
56
+ if (!['test', 'staging', 'production'].includes(environment)) {
57
+ throw new ConfigurationError('INVALID_CONFIG', `invalid app.environment "${environment}"`);
58
+ }
59
+ const allowedOrigins = raw.app?.allowedOrigins ?? [base.origin];
60
+ for (const origin of allowedOrigins) {
61
+ let parsed;
62
+ try {
63
+ parsed = new URL(origin);
64
+ }
65
+ catch {
66
+ throw new ConfigurationError('INVALID_CONFIG', `invalid allowed origin: ${origin}`);
67
+ }
68
+ if (parsed.origin !== origin) {
69
+ throw new ConfigurationError('INVALID_CONFIG', `allowed origin must be a serialized origin, got ${origin} (expected ${parsed.origin})`);
70
+ }
71
+ }
72
+ const command = raw.app?.command;
73
+ if (command !== undefined)
74
+ validateCommand(command, 'app.command');
75
+ const identity = raw.app?.identity;
76
+ if (identity !== undefined && (typeof identity !== 'string' || identity.trim() === '')) {
77
+ throw new ConfigurationError('INVALID_CONFIG', 'app.identity must be a non-empty string');
78
+ }
79
+ return {
80
+ configured: true,
81
+ base,
82
+ readyUrl: httpUrl(raw.app?.readyUrl, 'app.readyUrl') ?? base.href,
83
+ allowedOrigins,
84
+ environment,
85
+ command,
86
+ services,
87
+ identity,
88
+ };
89
+ }
90
+ /**
91
+ * The shape every spawned command shares: a non-empty executable and, when
92
+ * set, positive integer timeouts. A NaN or infinite budget would otherwise
93
+ * make the readiness loop spin without a deadline.
94
+ */
95
+ function validateCommand(command, label) {
96
+ if (typeof command !== 'object' || command === null) {
97
+ throw new ConfigurationError('INVALID_CONFIG', `${label} must be an object`);
98
+ }
99
+ if (typeof command.executable !== 'string' || command.executable.length === 0) {
100
+ throw new ConfigurationError('INVALID_CONFIG', `${label}.executable is required`);
101
+ }
102
+ positiveInt(command.startupTimeout, `${label}.startupTimeout`);
103
+ positiveInt(command.shutdownTimeout, `${label}.shutdownTimeout`);
104
+ }
105
+ /** Services carry no name, so messages name one by its position and command line. */
106
+ function commandLine(command) {
107
+ return [command.executable, ...(command.args ?? [])].join(' ');
108
+ }
109
+ /**
110
+ * Resolves `app.services`: every service is a command with exactly one
111
+ * readiness contract (`readyUrl` or `waitForExit`), and a `teardown` is a
112
+ * command of its own. The service fields that only steer the runner
113
+ * (`readyUrl`, `waitForExit`, `teardown`) are lifted out of the command.
114
+ */
115
+ export function resolveServices(raw) {
116
+ if (raw === undefined)
117
+ return [];
118
+ if (!Array.isArray(raw)) {
119
+ throw new ConfigurationError('INVALID_CONFIG', 'app.services must be an array');
120
+ }
121
+ return raw.map((service, index) => {
122
+ const position = `app.services[${index}]`;
123
+ validateCommand(service, position);
124
+ const { readyUrl: rawReadyUrl, waitForExit, teardown, ...command } = service;
125
+ const readyUrl = httpUrl(rawReadyUrl, `${position}.readyUrl`);
126
+ if ((readyUrl !== undefined) === (waitForExit === true)) {
127
+ throw new ConfigurationError('INVALID_CONFIG', `${position} needs exactly one readiness contract: set readyUrl or waitForExit: true`);
128
+ }
129
+ const readiness = readyUrl === undefined ? { waitForExit: true } : { readyUrl };
130
+ const label = `${position} (${commandLine(command)})`;
131
+ if (teardown !== undefined)
132
+ validateCommand(teardown, `${position}.teardown`);
133
+ return {
134
+ label,
135
+ command,
136
+ readiness,
137
+ teardown: teardown === undefined
138
+ ? undefined
139
+ : { label: `${label} teardown (${commandLine(teardown)})`, command: teardown },
140
+ };
141
+ });
142
+ }
143
+ function digestCommand(command) {
144
+ const { env, ...rest } = command;
145
+ if (env === undefined)
146
+ return rest;
147
+ return { ...rest, env: Object.fromEntries(Object.keys(env).map((key) => [key, { envName: key }])) };
148
+ }
149
+ /**
150
+ * The digest view of `app`: `app.command.env`, every service's env, and every
151
+ * service teardown's env become names, so no environment value contributes to
152
+ * the digest. Live values never appear under `app`, so nothing else changes.
153
+ */
154
+ export function digestApp(app) {
155
+ return {
156
+ ...app,
157
+ ...(app.command === undefined ? {} : { command: digestCommand(app.command) }),
158
+ ...(app.services === undefined
159
+ ? {}
160
+ : {
161
+ services: app.services.map(({ teardown, ...service }) => ({
162
+ ...digestCommand(service),
163
+ ...(teardown === undefined ? {} : { teardown: digestCommand(teardown) }),
164
+ })),
165
+ }),
166
+ };
167
+ }
168
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/config/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Package-scope diagnostics for TypeScript config and test entry points. */
2
+ /** Explains how to opt a `.ts` entry point's package into ESM when required. */
3
+ export declare function esmPackageHint(modulePath: string): string | undefined;
4
+ //# sourceMappingURL=esm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esm.d.ts","sourceRoot":"","sources":["../../src/config/esm.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAK7E,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA2BrE"}
@@ -0,0 +1,35 @@
1
+ /** Package-scope diagnostics for TypeScript config and test entry points. */
2
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ /** Explains how to opt a `.ts` entry point's package into ESM when required. */
5
+ export function esmPackageHint(modulePath) {
6
+ const filename = existsSync(modulePath) ? realpathSync(modulePath) : modulePath;
7
+ if (path.extname(filename) !== '.ts')
8
+ return undefined;
9
+ let dir = path.dirname(filename);
10
+ for (;;) {
11
+ const manifestPath = path.join(dir, 'package.json');
12
+ if (existsSync(manifestPath)) {
13
+ let manifest;
14
+ try {
15
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
16
+ }
17
+ catch {
18
+ // Leave malformed or unreadable manifests to the loader's own diagnostic.
19
+ return undefined;
20
+ }
21
+ if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) {
22
+ return undefined;
23
+ }
24
+ if ('type' in manifest && manifest.type === 'module')
25
+ return undefined;
26
+ return `e2e requires ES modules for .ts config and test files, but ${manifestPath} does not set "type": "module". To opt this package into ESM, run npm pkg set type=module from ${dir}. This also changes how existing .js files in the package are interpreted.`;
27
+ }
28
+ const parent = path.dirname(dir);
29
+ if (parent === dir || path.basename(parent) === 'node_modules')
30
+ break;
31
+ dir = parent;
32
+ }
33
+ return `e2e requires ES modules for .ts config and test files. Create a package.json with "type": "module" in ${path.dirname(filename)}, or run e2e init in the project directory.`;
34
+ }
35
+ //# sourceMappingURL=esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esm.js","sourceRoot":"","sources":["../../src/config/esm.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAChF,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IAEvD,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,SAAS,CAAC;QACR,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,IAAI,QAAiB,CAAC;YACtB,IAAI,CAAC;gBACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,0EAA0E;gBAC1E,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjF,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACvE,OAAO,8DAA8D,YAAY,kGAAkG,GAAG,4EAA4E,CAAC;QACrQ,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,cAAc;YAAE,MAAM;QACtE,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IAED,OAAO,yGAAyG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,6CAA6C,CAAC;AACtL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAOvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,gBAAgB,CA2BnF;AAWD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAK9F;AAED,mEAAmE;AACnE,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAmB7E"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAOvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,gBAAgB,CA2BnF;AAWD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9F;AAED,mEAAmE;AACnE,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAmB7E"}
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { pathToFileURL } from 'node:url';
5
5
  import { register } from 'tsx/esm/api';
6
6
  import { ConfigurationError } from '../internal/errors.js';
7
+ import { esmPackageHint } from './esm.js';
7
8
  const CONFIG_NAMES = ['e2e.config.ts', 'e2e.config.mts'];
8
9
  /**
9
10
  * Discovers the config file. With `--config` the explicit path wins. Otherwise
@@ -52,6 +53,9 @@ let imports = 0;
52
53
  * the config file as it is now.
53
54
  */
54
55
  export async function importModule(absolutePath, cacheKey = 'module') {
56
+ const hint = esmPackageHint(absolutePath);
57
+ if (hint !== undefined)
58
+ throw new Error(hint);
55
59
  imports += 1;
56
60
  const url = `${pathToFileURL(absolutePath).href}?e2e=${cacheKey}-${imports}`;
57
61
  loader ??= register({ namespace: 'e2e' });
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"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"}