@e2edev/e2e 0.2.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 (242) hide show
  1. package/README.md +32 -3
  2. package/dist/agent/act.d.ts.map +1 -1
  3. package/dist/agent/act.js +124 -71
  4. package/dist/agent/act.js.map +1 -1
  5. package/dist/agent/actions.d.ts +15 -0
  6. package/dist/agent/actions.d.ts.map +1 -1
  7. package/dist/agent/actions.js +59 -1
  8. package/dist/agent/actions.js.map +1 -1
  9. package/dist/agent/default-agent.d.ts +34 -4
  10. package/dist/agent/default-agent.d.ts.map +1 -1
  11. package/dist/agent/default-agent.js +28 -150
  12. package/dist/agent/default-agent.js.map +1 -1
  13. package/dist/agent/derived.d.ts +17 -0
  14. package/dist/agent/derived.d.ts.map +1 -0
  15. package/dist/agent/derived.js +45 -0
  16. package/dist/agent/derived.js.map +1 -0
  17. package/dist/agent/executor.d.ts +122 -2
  18. package/dist/agent/executor.d.ts.map +1 -1
  19. package/dist/agent/executor.js.map +1 -1
  20. package/dist/agent/index.js +1 -1
  21. package/dist/agent/index.js.map +1 -1
  22. package/dist/agent/invocation.d.ts +4 -8
  23. package/dist/agent/invocation.d.ts.map +1 -1
  24. package/dist/agent/invocation.js +16 -42
  25. package/dist/agent/invocation.js.map +1 -1
  26. package/dist/agent/ledger.d.ts +14 -4
  27. package/dist/agent/ledger.d.ts.map +1 -1
  28. package/dist/agent/ledger.js +26 -5
  29. package/dist/agent/ledger.js.map +1 -1
  30. package/dist/agent/loop-guards.d.ts +14 -1
  31. package/dist/agent/loop-guards.d.ts.map +1 -1
  32. package/dist/agent/loop-guards.js +11 -8
  33. package/dist/agent/loop-guards.js.map +1 -1
  34. package/dist/agent/observation.d.ts +28 -7
  35. package/dist/agent/observation.d.ts.map +1 -1
  36. package/dist/agent/observation.js +52 -5
  37. package/dist/agent/observation.js.map +1 -1
  38. package/dist/agent/primitives.d.ts +86 -0
  39. package/dist/agent/primitives.d.ts.map +1 -0
  40. package/dist/agent/primitives.js +255 -0
  41. package/dist/agent/primitives.js.map +1 -0
  42. package/dist/agent/prompts.d.ts.map +1 -1
  43. package/dist/agent/prompts.js.map +1 -1
  44. package/dist/agent/public.d.ts +6 -3
  45. package/dist/agent/public.d.ts.map +1 -1
  46. package/dist/agent/public.js +4 -2
  47. package/dist/agent/public.js.map +1 -1
  48. package/dist/agent/replay.d.ts +1 -1
  49. package/dist/agent/replay.d.ts.map +1 -1
  50. package/dist/agent/replay.js +19 -2
  51. package/dist/agent/replay.js.map +1 -1
  52. package/dist/agent/step-cache.d.ts +5 -2
  53. package/dist/agent/step-cache.d.ts.map +1 -1
  54. package/dist/agent/step-cache.js +37 -5
  55. package/dist/agent/step-cache.js.map +1 -1
  56. package/dist/agent/tool-loop.d.ts +59 -5
  57. package/dist/agent/tool-loop.d.ts.map +1 -1
  58. package/dist/agent/tool-loop.js +77 -105
  59. package/dist/agent/tool-loop.js.map +1 -1
  60. package/dist/agent/tool.d.ts +11 -16
  61. package/dist/agent/tool.d.ts.map +1 -1
  62. package/dist/agent/tool.js +19 -13
  63. package/dist/agent/tool.js.map +1 -1
  64. package/dist/agent/usage.d.ts +27 -0
  65. package/dist/agent/usage.d.ts.map +1 -0
  66. package/dist/agent/usage.js +54 -0
  67. package/dist/agent/usage.js.map +1 -0
  68. package/dist/backend/index.d.ts +72 -6
  69. package/dist/backend/index.d.ts.map +1 -1
  70. package/dist/backend/index.js +4 -1
  71. package/dist/backend/index.js.map +1 -1
  72. package/dist/backend/session.d.ts.map +1 -1
  73. package/dist/backend/session.js +1 -0
  74. package/dist/backend/session.js.map +1 -1
  75. package/dist/backend/surface.d.ts +2 -0
  76. package/dist/backend/surface.d.ts.map +1 -1
  77. package/dist/backend/timing.d.ts +3 -0
  78. package/dist/backend/timing.d.ts.map +1 -0
  79. package/dist/backend/timing.js +8 -0
  80. package/dist/backend/timing.js.map +1 -0
  81. package/dist/cache/recorder.d.ts +2 -0
  82. package/dist/cache/recorder.d.ts.map +1 -1
  83. package/dist/cache/recorder.js +4 -1
  84. package/dist/cache/recorder.js.map +1 -1
  85. package/dist/cache/relocate.d.ts.map +1 -1
  86. package/dist/cache/relocate.js +11 -2
  87. package/dist/cache/relocate.js.map +1 -1
  88. package/dist/cache/trace.d.ts +11 -0
  89. package/dist/cache/trace.d.ts.map +1 -1
  90. package/dist/cache/trace.js +9 -0
  91. package/dist/cache/trace.js.map +1 -1
  92. package/dist/cli/index.d.ts.map +1 -1
  93. package/dist/cli/index.js +32 -22
  94. package/dist/cli/index.js.map +1 -1
  95. package/dist/cli/init/backends.d.ts +75 -0
  96. package/dist/cli/init/backends.d.ts.map +1 -0
  97. package/dist/cli/init/backends.js +98 -0
  98. package/dist/cli/init/backends.js.map +1 -0
  99. package/dist/cli/init/package.d.ts +43 -0
  100. package/dist/cli/init/package.d.ts.map +1 -0
  101. package/dist/cli/init/package.js +64 -0
  102. package/dist/cli/init/package.js.map +1 -0
  103. package/dist/cli/init/scaffold.d.ts +12 -0
  104. package/dist/cli/init/scaffold.d.ts.map +1 -0
  105. package/dist/cli/init/scaffold.js +36 -0
  106. package/dist/cli/init/scaffold.js.map +1 -0
  107. package/dist/cli/init.d.ts +8 -3
  108. package/dist/cli/init.d.ts.map +1 -1
  109. package/dist/cli/init.js +99 -72
  110. package/dist/cli/init.js.map +1 -1
  111. package/dist/cli/signals.d.ts +23 -0
  112. package/dist/cli/signals.d.ts.map +1 -0
  113. package/dist/cli/signals.js +42 -0
  114. package/dist/cli/signals.js.map +1 -0
  115. package/dist/collect/registry.d.ts +14 -4
  116. package/dist/collect/registry.d.ts.map +1 -1
  117. package/dist/collect/registry.js +10 -10
  118. package/dist/collect/registry.js.map +1 -1
  119. package/dist/config/app.d.ts +50 -0
  120. package/dist/config/app.d.ts.map +1 -0
  121. package/dist/config/app.js +168 -0
  122. package/dist/config/app.js.map +1 -0
  123. package/dist/config/esm.d.ts +4 -0
  124. package/dist/config/esm.d.ts.map +1 -0
  125. package/dist/config/esm.js +35 -0
  126. package/dist/config/esm.js.map +1 -0
  127. package/dist/config/load.d.ts.map +1 -1
  128. package/dist/config/load.js +4 -0
  129. package/dist/config/load.js.map +1 -1
  130. package/dist/config/resolve.d.ts +6 -16
  131. package/dist/config/resolve.d.ts.map +1 -1
  132. package/dist/config/resolve.js +18 -110
  133. package/dist/config/resolve.js.map +1 -1
  134. package/dist/config/validate.d.ts +3 -1
  135. package/dist/config/validate.d.ts.map +1 -1
  136. package/dist/config/validate.js +17 -1
  137. package/dist/config/validate.js.map +1 -1
  138. package/dist/index.d.ts +3 -2
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js +1 -1
  141. package/dist/index.js.map +1 -1
  142. package/dist/internal/errors.d.ts +9 -0
  143. package/dist/internal/errors.d.ts.map +1 -1
  144. package/dist/internal/errors.js +15 -0
  145. package/dist/internal/errors.js.map +1 -1
  146. package/dist/internal/time.d.ts +10 -0
  147. package/dist/internal/time.d.ts.map +1 -1
  148. package/dist/internal/time.js +45 -0
  149. package/dist/internal/time.js.map +1 -1
  150. package/dist/internal/urls.d.ts +2 -1
  151. package/dist/internal/urls.d.ts.map +1 -1
  152. package/dist/internal/urls.js +22 -2
  153. package/dist/internal/urls.js.map +1 -1
  154. package/dist/locator/engine.d.ts +5 -3
  155. package/dist/locator/engine.d.ts.map +1 -1
  156. package/dist/locator/engine.js +7 -6
  157. package/dist/locator/engine.js.map +1 -1
  158. package/dist/report/build.d.ts +0 -1
  159. package/dist/report/build.d.ts.map +1 -1
  160. package/dist/report/build.js +2 -3
  161. package/dist/report/build.js.map +1 -1
  162. package/dist/report/junit.d.ts +11 -0
  163. package/dist/report/junit.d.ts.map +1 -0
  164. package/dist/report/junit.js +202 -0
  165. package/dist/report/junit.js.map +1 -0
  166. package/dist/report/list.d.ts +2 -0
  167. package/dist/report/list.d.ts.map +1 -1
  168. package/dist/report/list.js +15 -0
  169. package/dist/report/list.js.map +1 -1
  170. package/dist/report/live-status.d.ts.map +1 -1
  171. package/dist/report/live-status.js +2 -1
  172. package/dist/report/live-status.js.map +1 -1
  173. package/dist/report/write.d.ts +2 -0
  174. package/dist/report/write.d.ts.map +1 -1
  175. package/dist/report/write.js +7 -3
  176. package/dist/report/write.js.map +1 -1
  177. package/dist/run/budget.d.ts +25 -0
  178. package/dist/run/budget.d.ts.map +1 -0
  179. package/dist/run/budget.js +38 -0
  180. package/dist/run/budget.js.map +1 -0
  181. package/dist/run/events.d.ts +15 -0
  182. package/dist/run/events.d.ts.map +1 -1
  183. package/dist/run/events.js.map +1 -1
  184. package/dist/run/execute.d.ts +8 -0
  185. package/dist/run/execute.d.ts.map +1 -1
  186. package/dist/run/execute.js +53 -8
  187. package/dist/run/execute.js.map +1 -1
  188. package/dist/run/fixture-legacy.d.ts +36 -0
  189. package/dist/run/fixture-legacy.d.ts.map +1 -0
  190. package/dist/run/fixture-legacy.js +143 -0
  191. package/dist/run/fixture-legacy.js.map +1 -0
  192. package/dist/run/fixture-recording.d.ts +15 -0
  193. package/dist/run/fixture-recording.d.ts.map +1 -0
  194. package/dist/run/fixture-recording.js +75 -0
  195. package/dist/run/fixture-recording.js.map +1 -0
  196. package/dist/run/fixtures.d.ts +6 -3
  197. package/dist/run/fixtures.d.ts.map +1 -1
  198. package/dist/run/fixtures.js +32 -166
  199. package/dist/run/fixtures.js.map +1 -1
  200. package/dist/run/in-process.d.ts.map +1 -1
  201. package/dist/run/in-process.js +11 -2
  202. package/dist/run/in-process.js.map +1 -1
  203. package/dist/run/managed-process.d.ts +49 -0
  204. package/dist/run/managed-process.d.ts.map +1 -0
  205. package/dist/run/managed-process.js +202 -0
  206. package/dist/run/managed-process.js.map +1 -0
  207. package/dist/run/realm.d.ts +43 -8
  208. package/dist/run/realm.d.ts.map +1 -1
  209. package/dist/run/realm.js +67 -24
  210. package/dist/run/realm.js.map +1 -1
  211. package/dist/run/runner.d.ts +11 -1
  212. package/dist/run/runner.d.ts.map +1 -1
  213. package/dist/run/runner.js +151 -33
  214. package/dist/run/runner.js.map +1 -1
  215. package/dist/run/scheduler.d.ts +8 -0
  216. package/dist/run/scheduler.d.ts.map +1 -1
  217. package/dist/run/scheduler.js +37 -3
  218. package/dist/run/scheduler.js.map +1 -1
  219. package/dist/run/serial.d.ts +2 -0
  220. package/dist/run/serial.d.ts.map +1 -1
  221. package/dist/run/serial.js +10 -0
  222. package/dist/run/serial.js.map +1 -1
  223. package/dist/run/steps.d.ts +1 -1
  224. package/dist/run/steps.d.ts.map +1 -1
  225. package/dist/run/steps.js +12 -9
  226. package/dist/run/steps.js.map +1 -1
  227. package/dist/run/worker/entry.js +17 -2
  228. package/dist/run/worker/entry.js.map +1 -1
  229. package/dist/run/worker/protocol.d.ts +9 -1
  230. package/dist/run/worker/protocol.d.ts.map +1 -1
  231. package/dist/run/worker/protocol.js.map +1 -1
  232. package/dist/run/worker/session.d.ts +12 -0
  233. package/dist/run/worker/session.d.ts.map +1 -1
  234. package/dist/run/worker/session.js +23 -1
  235. package/dist/run/worker/session.js.map +1 -1
  236. package/dist/types.d.ts +33 -2
  237. package/dist/types.d.ts.map +1 -1
  238. package/package.json +2 -2
  239. package/dist/run/app-process.d.ts +0 -18
  240. package/dist/run/app-process.d.ts.map +0 -1
  241. package/dist/run/app-process.js +0 -112
  242. package/dist/run/app-process.js.map +0 -1
@@ -0,0 +1,202 @@
1
+ /** Spawned-process management for `app.command`, `app.services`, and their teardowns (spec 05-config.md). */
2
+ import { spawn } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { InfrastructureError } from '../internal/errors.js';
5
+ import { sleep } from '../internal/time.js';
6
+ const INHERITED_ENV = ['PATH', 'HOME', 'TMPDIR', 'TMP', 'TEMP', 'SystemRoot', 'COMSPEC'];
7
+ /** Readiness polling starts fast and backs off; a booting server answers late, not on a schedule. */
8
+ const READY_POLL_MIN_MS = 25;
9
+ const READY_POLL_MAX_MS = 250;
10
+ /** One readiness probe never outlives this, so a half-open server cannot stall the deadline check. */
11
+ const READY_PROBE_TIMEOUT_MS = 2_000;
12
+ function describeExit(exit) {
13
+ return exit.code === null ? `was terminated by ${exit.signal}` : `exited with code ${exit.code}`;
14
+ }
15
+ /**
16
+ * One command the runner owns: spawned as a process group, waited on until
17
+ * its readiness contract holds, and terminated signal-then-force. `label`
18
+ * names it in every error (`app.command`, `app.services[0] (docker ...)`).
19
+ */
20
+ export class ManagedProcess {
21
+ label;
22
+ command;
23
+ projectRoot;
24
+ readiness;
25
+ child = null;
26
+ constructor(label, command, projectRoot, readiness) {
27
+ this.label = label;
28
+ this.command = command;
29
+ this.projectRoot = projectRoot;
30
+ this.readiness = readiness;
31
+ }
32
+ /**
33
+ * Spawns the process group and waits for readiness. An already aborted
34
+ * `signal` spawns nothing; one that aborts during the wait ends it early and
35
+ * takes the process down with it. The caller reads the signal to learn the
36
+ * run was interrupted.
37
+ */
38
+ async start(signal) {
39
+ // A function, not a narrowed local: the signal flips while the loop awaits.
40
+ const aborted = () => signal?.aborted === true;
41
+ if (aborted())
42
+ return;
43
+ const env = {};
44
+ for (const key of INHERITED_ENV) {
45
+ const value = process.env[key];
46
+ if (value !== undefined)
47
+ env[key] = value;
48
+ }
49
+ Object.assign(env, this.command.env ?? {});
50
+ const child = spawn(this.command.executable, [...(this.command.args ?? [])], {
51
+ cwd: path.resolve(this.projectRoot, this.command.cwd ?? '.'),
52
+ env,
53
+ detached: process.platform !== 'win32',
54
+ stdio: 'ignore',
55
+ });
56
+ this.child = child;
57
+ let spawnError;
58
+ child.on('error', (error) => {
59
+ spawnError = error;
60
+ });
61
+ let exit;
62
+ const exited = new Promise((resolve) => {
63
+ child.once('exit', (code, exitSignal) => {
64
+ exit = { code, signal: exitSignal };
65
+ resolve();
66
+ });
67
+ });
68
+ // Without a URL to probe, the process exiting 0 is the readiness event.
69
+ const readyUrl = 'readyUrl' in this.readiness ? this.readiness.readyUrl : undefined;
70
+ const startupTimeout = this.command.startupTimeout ?? 60_000;
71
+ const deadline = Date.now() + startupTimeout;
72
+ let pollMs = READY_POLL_MIN_MS;
73
+ for (;;) {
74
+ if (aborted()) {
75
+ await this.stop();
76
+ return;
77
+ }
78
+ if (spawnError !== undefined) {
79
+ throw new InfrastructureError('APP_UNREACHABLE', `${this.label} failed to start: ${spawnError.message}`, { cause: spawnError });
80
+ }
81
+ if (exit !== undefined) {
82
+ if (readyUrl === undefined && exit.code === 0)
83
+ return;
84
+ throw new InfrastructureError('APP_UNREACHABLE', `${this.label} ${describeExit(exit)} ${readyUrl === undefined ? 'instead of 0' : 'before becoming ready'}`);
85
+ }
86
+ const remaining = deadline - Date.now();
87
+ if (remaining <= 0) {
88
+ await this.stop();
89
+ throw new InfrastructureError('APP_UNREACHABLE', readyUrl === undefined
90
+ ? `${this.label} did not exit within ${startupTimeout} ms`
91
+ : `${this.label} was not reachable at ${readyUrl} within ${startupTimeout} ms`);
92
+ }
93
+ if (readyUrl !== undefined) {
94
+ try {
95
+ const response = await fetch(readyUrl, {
96
+ redirect: 'manual',
97
+ signal: AbortSignal.timeout(Math.min(READY_PROBE_TIMEOUT_MS, remaining)),
98
+ });
99
+ if (response.status >= 200 && response.status <= 499)
100
+ return;
101
+ }
102
+ catch {
103
+ // not ready yet
104
+ }
105
+ }
106
+ // The exit event wakes the wait early so an exit is seen at once, not on the next poll.
107
+ await Promise.race([
108
+ sleep(Math.min(pollMs, Math.max(0, deadline - Date.now())), signal).catch(() => undefined),
109
+ exited,
110
+ ]);
111
+ pollMs = Math.min(pollMs * 2, READY_POLL_MAX_MS);
112
+ }
113
+ }
114
+ /** Gracefully terminates the whole process group, then force-kills. */
115
+ async stop() {
116
+ const child = this.child;
117
+ this.child = null;
118
+ if (child === null || child.exitCode !== null || child.signalCode !== null)
119
+ return;
120
+ const shutdownTimeout = this.command.shutdownTimeout ?? 10_000;
121
+ const pid = child.pid;
122
+ const signalGroup = (signal) => {
123
+ if (pid === undefined)
124
+ return;
125
+ try {
126
+ if (process.platform !== 'win32')
127
+ process.kill(-pid, signal);
128
+ else
129
+ child.kill(signal);
130
+ }
131
+ catch {
132
+ // process already gone
133
+ }
134
+ };
135
+ signalGroup('SIGTERM');
136
+ const exited = new Promise((resolve) => {
137
+ child.once('exit', () => resolve());
138
+ });
139
+ const timer = sleep(shutdownTimeout).then(() => 'timeout');
140
+ const winner = await Promise.race([exited.then(() => 'exited'), timer]);
141
+ if (winner === 'timeout') {
142
+ signalGroup('SIGKILL');
143
+ await exited.catch(() => undefined);
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * The dependency processes of `app.services`: started sequentially in
149
+ * declaration order, each ready before the next starts, and torn down in
150
+ * reverse.
151
+ */
152
+ export class ServiceStack {
153
+ services;
154
+ projectRoot;
155
+ started = [];
156
+ constructor(services, projectRoot) {
157
+ this.services = services;
158
+ this.projectRoot = projectRoot;
159
+ }
160
+ /**
161
+ * Starts every service in order. Stops early once `signal` aborts; the
162
+ * services already started still get their teardown from `stop`.
163
+ */
164
+ async start(signal) {
165
+ for (const { label, command, readiness, teardown } of this.services) {
166
+ if (signal?.aborted === true)
167
+ return;
168
+ const service = new ManagedProcess(label, command, this.projectRoot, readiness);
169
+ this.started.push({
170
+ service,
171
+ teardown: teardown === undefined
172
+ ? undefined
173
+ : new ManagedProcess(teardown.label, teardown.command, this.projectRoot, {
174
+ waitForExit: true,
175
+ }),
176
+ });
177
+ await service.start(signal);
178
+ }
179
+ }
180
+ /**
181
+ * Stops the started services in reverse order, then runs each of their
182
+ * teardown commands in reverse order and waits for it to exit. A failing
183
+ * teardown is reported through `onFailure` and never skips the rest, so one
184
+ * failing `docker compose down` cannot leave the others running.
185
+ */
186
+ async stop(onFailure) {
187
+ const started = this.started.splice(0).toReversed();
188
+ for (const { service } of started)
189
+ await service.stop();
190
+ for (const { teardown } of started) {
191
+ if (teardown === undefined)
192
+ continue;
193
+ try {
194
+ await teardown.start();
195
+ }
196
+ catch (cause) {
197
+ onFailure(cause);
198
+ }
199
+ }
200
+ }
201
+ }
202
+ //# sourceMappingURL=managed-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-process.js","sourceRoot":"","sources":["../../src/run/managed-process.ts"],"names":[],"mappings":"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"}
@@ -2,22 +2,36 @@
2
2
  import { type SerializedError } from '../internal/errors.ts';
3
3
  import { DebugTrace } from '../internal/debug.ts';
4
4
  import type { CollectedTest } from '../collect/collect.ts';
5
- import { type ModuleRegistration, type RegisteredHook, type RegisteredTest } from '../collect/registry.ts';
5
+ import { type GroupNode, type HookKind, type ModuleRegistration, type RegisteredTest, type TestHook } from '../collect/registry.ts';
6
+ import type { TestTargetPair } from '../collect/select.ts';
6
7
  import type { Platform } from '../types.ts';
7
8
  import type { RunError } from './records.ts';
9
+ /**
10
+ * A suite scope of one realm: a describe group, or `undefined` for the file
11
+ * scope. Scopes are the registration's own group nodes, so two sibling groups
12
+ * that happen to share a title stay two scopes with their own hooks.
13
+ */
14
+ type Scope = GroupNode | undefined;
8
15
  export interface Realm {
9
16
  registration: ModuleRegistration;
10
17
  /** Registered tests by title-path key, for per-attempt lookup. */
11
18
  testsByKey: ReadonlyMap<string, RegisteredTest>;
12
- /** Scope keys whose beforeAll already ran in this realm. */
13
- entered: Map<string, {
19
+ /**
20
+ * Scopes whose beforeAll ran in this realm, in entry order (outermost
21
+ * first), each with the failure that ended its beforeAll if one did. A scope
22
+ * leaves the map when its afterAll has run.
23
+ */
24
+ entered: Map<Scope, {
14
25
  failed: SerializedError | undefined;
15
26
  }>;
16
- /** Scopes pending afterAll, innermost last. */
17
- pendingAfterAll: string[];
18
27
  }
19
28
  /** Finds a registered test in a re-imported realm by its exact title path. */
20
29
  export declare function findRegistered(realm: Realm, test: CollectedTest): RegisteredTest | undefined;
30
+ /**
31
+ * Runs one hook within its budget. A hook that overruns fails with the
32
+ * runner's timeout error; `onTimeout` lets the caller cancel what it started.
33
+ */
34
+ export declare function runHook(kind: HookKind, run: () => void | Promise<void>, timeoutMs: number, onTimeout?: () => void): Promise<void>;
21
35
  export interface RealmManagerOptions {
22
36
  readonly targetName: string;
23
37
  readonly platform: Platform;
@@ -41,12 +55,33 @@ export declare class RealmManager {
41
55
  * adopting that import saves the second, identical one per unit.
42
56
  */
43
57
  adopt(registration: ModuleRegistration): Realm;
44
- /** Returns a test's hooks of one kind across its enclosing scope chain. */
45
- hooksFor(realm: Realm, test: RegisteredTest, kind: 'beforeEach' | 'afterEach'): RegisteredHook[];
58
+ /**
59
+ * A test's hooks of one kind in execution order (spec 11-lifecycle.md).
60
+ * `beforeEach` runs outer scope to inner, each scope's hooks in declaration
61
+ * order, wherever in the file a scope's hooks were declared relative to the
62
+ * test or to nested groups. `afterEach` mirrors it: inner scope to outer,
63
+ * each scope's hooks in reverse declaration order.
64
+ */
65
+ hooksFor(realm: Realm, test: RegisteredTest, kind: TestHook['kind']): TestHook[];
46
66
  /** Enters suite scopes for a test, running pending beforeAll hooks. */
47
67
  enterScopes(realm: Realm, test: RegisteredTest): Promise<SerializedError | undefined>;
48
- /** Runs pending afterAll hooks, innermost scope first. */
68
+ /**
69
+ * Closes every entered scope that none of `remaining` (the pairs still to
70
+ * run in this realm) belongs to, innermost first, running its afterAll
71
+ * hooks in reverse declaration order. A scope's afterAll therefore runs
72
+ * when its last runnable member leaves it (spec 11-lifecycle.md), not when
73
+ * the file ends: one describe's teardown never runs after a sibling's tests.
74
+ *
75
+ * Returns the first afterAll failure. Every failure is a run error, and the
76
+ * remaining hooks and scopes still run; the caller decides what the realm
77
+ * is still good for (spec: an afterAll failure discards the suite instance).
78
+ */
79
+ leaveFinished(realm: Realm, remaining: readonly TestTargetPair[]): Promise<SerializedError | undefined>;
80
+ /** Closes every entered scope: the realm ends here. */
49
81
  leave(realm: Realm): Promise<void>;
82
+ /** One scope's hooks of one kind, in declaration order. */
83
+ private scopeHooks;
50
84
  private suiteFixtures;
51
85
  }
86
+ export {};
52
87
  //# sourceMappingURL=realm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"realm.d.ts","sourceRoot":"","sources":["../../src/run/realm.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAGlF,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,KAAK;IACpB,YAAY,EAAE,kBAAkB,CAAC;IACjC,kEAAkE;IAClE,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAChD,4DAA4D;IAC5D,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAC9D,+CAA+C;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAE5F;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED,+EAA+E;AAC/E,qBAAa,YAAY;IAIX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IAEnC,YAA6B,OAAO,EAAE,mBAAmB,EAExD;IAED,mDAAmD;IAC7C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAQjD;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,EAAE,kBAAkB,GAAG,KAAK,CAI7C;IAED,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,cAAc,EAAE,CAK/F;IAED,uEAAuE;IACjE,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAkC1F;IAED,0DAA0D;IACpD,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBvC;IAED,OAAO,CAAC,aAAa;CAGtB"}
1
+ {"version":3,"file":"realm.d.ts","sourceRoot":"","sources":["../../src/run/realm.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAGlF,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,KAAK,cAAc,EAEnB,KAAK,QAAQ,EACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C;;;;GAIG;AACH,KAAK,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnC,MAAM,WAAW,KAAK;IACpB,YAAY,EAAE,kBAAkB,CAAC;IACjC,kEAAkE;IAClE,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAChD;;;;OAIG;IACH,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;CAC9D;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAE5F;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED,+EAA+E;AAC/E,qBAAa,YAAY;IAIX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IAEnC,YAA6B,OAAO,EAAE,mBAAmB,EAExD;IAED,mDAAmD;IAC7C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAQjD;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,EAAE,kBAAkB,GAAG,KAAK,CAI7C;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,EAAE,CAK/E;IAED,uEAAuE;IACjE,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAyB1F;IAED;;;;;;;;;;OAUG;IACG,aAAa,CACjB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,cAAc,EAAE,GACnC,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CA0BtC;IAED,uDAAuD;IACjD,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;IAED,2DAA2D;IAC3D,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,aAAa;CAGtB"}
package/dist/run/realm.js CHANGED
@@ -9,6 +9,16 @@ import { collectModule, groupChain, groupTitles, } from '../collect/registry.js'
9
9
  export function findRegistered(realm, test) {
10
10
  return realm.testsByKey.get(titlePathKey(test.titlePath));
11
11
  }
12
+ /**
13
+ * Runs one hook within its budget. A hook that overruns fails with the
14
+ * runner's timeout error; `onTimeout` lets the caller cancel what it started.
15
+ */
16
+ export function runHook(kind, run, timeoutMs, onTimeout) {
17
+ return withTimeout(Promise.resolve().then(run), timeoutMs, () => {
18
+ onTimeout?.();
19
+ return new TestTimeoutError(`${kind} hook timed out`);
20
+ });
21
+ }
12
22
  /** Creates realms and runs suite-scope hooks with per-realm entry tracking. */
13
23
  export class RealmManager {
14
24
  options;
@@ -33,67 +43,100 @@ export class RealmManager {
33
43
  const testsByKey = new Map();
34
44
  for (const test of registration.tests)
35
45
  testsByKey.set(titlePathKey(test.titlePath), test);
36
- return { registration, testsByKey, entered: new Map(), pendingAfterAll: [] };
46
+ return { registration, testsByKey, entered: new Map() };
37
47
  }
38
- /** Returns a test's hooks of one kind across its enclosing scope chain. */
48
+ /**
49
+ * A test's hooks of one kind in execution order (spec 11-lifecycle.md).
50
+ * `beforeEach` runs outer scope to inner, each scope's hooks in declaration
51
+ * order, wherever in the file a scope's hooks were declared relative to the
52
+ * test or to nested groups. `afterEach` mirrors it: inner scope to outer,
53
+ * each scope's hooks in reverse declaration order.
54
+ */
39
55
  hooksFor(realm, test, kind) {
40
- const chainKeys = new Set(scopeChainFor(test).map(scopeKey));
41
- return realm.registration.hooks.filter((hook) => hook.kind === kind && chainKeys.has(scopeKey(hook.group)));
56
+ const ordered = scopeChainFor(test).flatMap((scope) => this.scopeHooks(realm, scope, kind));
57
+ return kind === 'beforeEach' ? ordered : ordered.toReversed();
42
58
  }
43
59
  /** Enters suite scopes for a test, running pending beforeAll hooks. */
44
60
  async enterScopes(realm, test) {
45
61
  for (const scope of scopeChainFor(test)) {
46
- const key = scopeKey(scope);
47
- const entered = realm.entered.get(key);
62
+ const entered = realm.entered.get(scope);
48
63
  if (entered !== undefined) {
49
64
  if (entered.failed !== undefined)
50
65
  return entered.failed;
51
66
  continue;
52
67
  }
53
- const hooks = realm.registration.hooks.filter((hook) => hook.kind === 'beforeAll' && scopeKey(hook.group) === key);
54
68
  let failed;
55
- for (const hook of hooks) {
69
+ for (const hook of this.scopeHooks(realm, scope, 'beforeAll')) {
56
70
  try {
57
- await withTimeout(Promise.resolve(hook.fn(this.suiteFixtures())), this.options.timeout, () => new TestTimeoutError('beforeAll hook timed out'));
71
+ await runHook(hook.kind, () => hook.fn(this.suiteFixtures()), this.options.timeout);
58
72
  }
59
73
  catch (cause) {
60
74
  const error = classifyError(cause);
61
- failed = serializeError(new E2EError('test', 'HOOK_FAILED', `beforeAll failed: ${error.message}`, { cause }), { phase: 'beforeAll', scopeId: key === '' ? (test.titlePath[0] ?? 'file') : key });
75
+ failed = serializeError(new E2EError('test', 'HOOK_FAILED', `beforeAll failed: ${error.message}`, { cause }), { phase: 'beforeAll', scopeId: scopeId(scope) });
62
76
  this.options.runErrors.push({ error: failed });
63
77
  break;
64
78
  }
65
79
  }
66
- realm.entered.set(key, { failed });
67
- realm.pendingAfterAll.push(key);
80
+ realm.entered.set(scope, { failed });
68
81
  if (failed !== undefined)
69
82
  return failed;
70
83
  }
71
84
  return undefined;
72
85
  }
73
- /** Runs pending afterAll hooks, innermost scope first. */
74
- async leave(realm) {
75
- for (const key of [...realm.pendingAfterAll].toReversed()) {
76
- const hooks = realm.registration.hooks.filter((hook) => hook.kind === 'afterAll' && scopeKey(hook.group) === key);
77
- for (const hook of [...hooks].toReversed()) {
86
+ /**
87
+ * Closes every entered scope that none of `remaining` (the pairs still to
88
+ * run in this realm) belongs to, innermost first, running its afterAll
89
+ * hooks in reverse declaration order. A scope's afterAll therefore runs
90
+ * when its last runnable member leaves it (spec 11-lifecycle.md), not when
91
+ * the file ends: one describe's teardown never runs after a sibling's tests.
92
+ *
93
+ * Returns the first afterAll failure. Every failure is a run error, and the
94
+ * remaining hooks and scopes still run; the caller decides what the realm
95
+ * is still good for (spec: an afterAll failure discards the suite instance).
96
+ */
97
+ async leaveFinished(realm, remaining) {
98
+ let failure;
99
+ const needed = new Set();
100
+ for (const pair of remaining) {
101
+ // A pair the realm cannot find never runs here, so it holds nothing open.
102
+ const registered = findRegistered(realm, pair.test);
103
+ if (registered !== undefined)
104
+ for (const scope of scopeChainFor(registered))
105
+ needed.add(scope);
106
+ }
107
+ for (const scope of [...realm.entered.keys()].toReversed()) {
108
+ if (needed.has(scope))
109
+ continue;
110
+ realm.entered.delete(scope);
111
+ for (const hook of this.scopeHooks(realm, scope, 'afterAll').toReversed()) {
78
112
  try {
79
- await withTimeout(Promise.resolve(hook.fn(this.suiteFixtures())), this.options.cleanupTimeout, () => new TestTimeoutError('afterAll hook timed out'));
113
+ await runHook(hook.kind, () => hook.fn(this.suiteFixtures()), this.options.cleanupTimeout);
80
114
  }
81
115
  catch (cause) {
82
116
  const error = classifyError(cause);
83
- this.options.runErrors.push({
84
- error: serializeError(new E2EError('test', 'HOOK_FAILED', `afterAll failed: ${error.message}`, { cause }), { phase: 'afterAll', scopeId: key }),
85
- });
117
+ const failed = serializeError(new E2EError('test', 'HOOK_FAILED', `afterAll failed: ${error.message}`, { cause }), { phase: 'afterAll', scopeId: scopeId(scope) });
118
+ this.options.runErrors.push({ error: failed });
119
+ failure ??= failed;
86
120
  }
87
121
  }
88
122
  }
89
- realm.pendingAfterAll = [];
123
+ return failure;
124
+ }
125
+ /** Closes every entered scope: the realm ends here. */
126
+ async leave(realm) {
127
+ await this.leaveFinished(realm, []);
128
+ }
129
+ /** One scope's hooks of one kind, in declaration order. */
130
+ scopeHooks(realm, scope, kind) {
131
+ return realm.registration.hooks.filter((hook) => hook.kind === kind && hook.group === scope);
90
132
  }
91
133
  suiteFixtures() {
92
134
  return { platform: this.options.platform };
93
135
  }
94
136
  }
95
- function scopeKey(group) {
96
- return titlePathKey(groupTitles(group));
137
+ /** The scope's report identity: its title path, or `file` for the file scope. */
138
+ function scopeId(scope) {
139
+ return scope === undefined ? 'file' : groupTitles(scope).join(' \u203a ');
97
140
  }
98
141
  function scopeChainFor(test) {
99
142
  return [undefined, ...groupChain(test.group)];
@@ -1 +1 @@
1
- {"version":3,"file":"realm.js","sourceRoot":"","sources":["../../src/run/realm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"realm.js","sourceRoot":"","sources":["../../src/run/realm.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export interface RunOptions {
13
13
  headed?: boolean | undefined;
14
14
  retries?: number | undefined;
15
15
  workers?: number | undefined;
16
- reporters?: readonly ('list' | 'json')[] | undefined;
16
+ reporters?: readonly ('list' | 'json' | 'junit')[] | undefined;
17
17
  artifactsDir?: string | undefined;
18
18
  passWithNoTests?: boolean | undefined;
19
19
  /** Runs with the trace cache off (`--no-cache`), overriding the config. */
@@ -31,7 +31,15 @@ export interface RunOptions {
31
31
  rawConfig?: E2EConfig | undefined;
32
32
  env?: NodeJS.ProcessEnv | undefined;
33
33
  quiet?: boolean | undefined;
34
+ /** Cancellation: the running test ends, its teardown runs, the run finishes as `interrupted`. */
34
35
  interruptSignal?: AbortSignal | undefined;
36
+ /**
37
+ * Forced cancellation: every worker disposes its backend at once instead
38
+ * of finishing its test, and is killed after the cleanup budget. Counts as
39
+ * an interrupt on its own. The runner never handles process signals itself;
40
+ * the CLI's Ctrl-C ladder (`cli/signals.ts`) feeds these two.
41
+ */
42
+ forceSignal?: AbortSignal | undefined;
35
43
  /** Structured, JSON-serializable run events for embedding hosts. */
36
44
  onEvent?: RunEventSink | undefined;
37
45
  }
@@ -40,6 +48,8 @@ export interface RunOutcome {
40
48
  status: 'passed' | 'failed' | 'error' | 'interrupted';
41
49
  report: Report1Document;
42
50
  reportPath: string | undefined;
51
+ /** Where the JUnit XML was written; undefined unless the `junit` reporter was selected. */
52
+ junitPath: string | undefined;
43
53
  /** Where the AI trace was written; undefined unless `aiTrace` was requested. */
44
54
  aiTracePath: string | undefined;
45
55
  results: readonly ResultRecord[];
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/run/runner.ts"],"names":[],"mappings":"AAAA,8EAA8E;AA2B9E,OAAO,EAA+B,KAAK,eAAe,EAAyB,MAAM,oBAAoB,CAAC;AAK9G,OAAO,EAAwC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAExG,OAAO,KAAK,EAAE,YAAY,EAA+B,MAAM,cAAc,CAAC;AAK9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACrC,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC;IACrD,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,eAAe,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,oEAAoE;IACpE,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;IACtD,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,gFAAgF;IAChF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,wBAAsB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CA0UvE"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/run/runner.ts"],"names":[],"mappings":"AAAA,8EAA8E;AA4B9E,OAAO,EAA+B,KAAK,eAAe,EAAyB,MAAM,oBAAoB,CAAC;AAM9G,OAAO,EAAwC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAExG,OAAO,KAAK,EAAE,YAAY,EAA+B,MAAM,cAAc,CAAC;AAK9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACrC,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC;IAC/D,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,iGAAiG;IACjG,eAAe,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACtC,oEAAoE;IACpE,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;IACtD,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,2FAA2F;IAC3F,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,gFAAgF;IAChF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;CAClC;AASD,yEAAyE;AACzE,wBAAsB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAyavE"}