@delacour/warden-e2e 0.0.0-stage → 0.1.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/chunk-e6pn5ygy.mjs +5832 -0
  3. package/index.d.ts +1 -0
  4. package/index.mjs +1047 -0
  5. package/package.json +49 -4
  6. package/preload.d.ts +1 -0
  7. package/preload.mjs +4788 -0
  8. package/types/core/src/allocate.d.ts +23 -0
  9. package/types/core/src/builds/app-option.schema.d.ts +37 -0
  10. package/types/core/src/builds/install.d.ts +95 -0
  11. package/types/core/src/builds/resolve.d.ts +74 -0
  12. package/types/core/src/config.defaults.d.ts +25 -0
  13. package/types/core/src/exec.d.ts +18 -0
  14. package/types/core/src/liveness.d.ts +12 -0
  15. package/types/core/src/providers/android.d.ts +132 -0
  16. package/types/core/src/providers/health.d.ts +45 -0
  17. package/types/core/src/providers/provider.types.d.ts +56 -0
  18. package/types/core/src/store.d.ts +105 -0
  19. package/types/core/src/types.d.ts +126 -0
  20. package/types/e2e/src/alert-buttons.d.ts +41 -0
  21. package/types/e2e/src/alert-reader.d.ts +25 -0
  22. package/types/e2e/src/app.d.ts +62 -0
  23. package/types/e2e/src/device-devtools.d.ts +26 -0
  24. package/types/e2e/src/device-link.d.ts +43 -0
  25. package/types/e2e/src/device.d.ts +90 -0
  26. package/types/e2e/src/devtools/cdp.d.ts +65 -0
  27. package/types/e2e/src/devtools/console.d.ts +59 -0
  28. package/types/e2e/src/devtools/devtools.types.d.ts +169 -0
  29. package/types/e2e/src/devtools/facet.d.ts +28 -0
  30. package/types/e2e/src/devtools/inspector.d.ts +48 -0
  31. package/types/e2e/src/devtools/jsonl.d.ts +4 -0
  32. package/types/e2e/src/devtools/native-log.d.ts +50 -0
  33. package/types/e2e/src/devtools/network.d.ts +33 -0
  34. package/types/e2e/src/devtools/network.script.d.ts +24 -0
  35. package/types/e2e/src/devtools/session.d.ts +82 -0
  36. package/types/e2e/src/devtools/tree.d.ts +23 -0
  37. package/types/e2e/src/devtools/tree.script.d.ts +33 -0
  38. package/types/e2e/src/driver/alerts.d.ts +29 -0
  39. package/types/e2e/src/driver/android/adb-session.d.ts +52 -0
  40. package/types/e2e/src/driver/android/android-alert.d.ts +4 -0
  41. package/types/e2e/src/driver/android/android-animations.d.ts +29 -0
  42. package/types/e2e/src/driver/android/android-app.d.ts +32 -0
  43. package/types/e2e/src/driver/android/android-argv.d.ts +122 -0
  44. package/types/e2e/src/driver/android/android-device.d.ts +44 -0
  45. package/types/e2e/src/driver/android/android-driver.d.ts +60 -0
  46. package/types/e2e/src/driver/android/android-dump.d.ts +46 -0
  47. package/types/e2e/src/driver/android/android-state.d.ts +69 -0
  48. package/types/e2e/src/driver/android/uiad-backend.d.ts +63 -0
  49. package/types/e2e/src/driver/android/uiad-client.d.ts +60 -0
  50. package/types/e2e/src/driver/android/uiad-device.d.ts +70 -0
  51. package/types/e2e/src/driver/android/uiad-dex.generated.d.ts +8 -0
  52. package/types/e2e/src/driver/android/uiad-ops.d.ts +62 -0
  53. package/types/e2e/src/driver/android/uiad-protocol.d.ts +209 -0
  54. package/types/e2e/src/driver/android/uiautomator.d.ts +33 -0
  55. package/types/e2e/src/driver/driver.types.d.ts +231 -0
  56. package/types/e2e/src/driver/errors.d.ts +13 -0
  57. package/types/e2e/src/driver/gesture-geometry.d.ts +48 -0
  58. package/types/e2e/src/driver/ios/hid-recovery.d.ts +36 -0
  59. package/types/e2e/src/driver/ios/ios-driver.d.ts +63 -0
  60. package/types/e2e/src/driver/ios/ios-session.d.ts +30 -0
  61. package/types/e2e/src/driver/ios/locate-helper.d.ts +38 -0
  62. package/types/e2e/src/driver/ios/normalize.d.ts +11 -0
  63. package/types/e2e/src/driver/ios/simctl.d.ts +102 -0
  64. package/types/e2e/src/driver/ios/simd-client.d.ts +68 -0
  65. package/types/e2e/src/driver/ios/simd-protocol.d.ts +433 -0
  66. package/types/e2e/src/driver/ios/simd-transport.d.ts +43 -0
  67. package/types/e2e/src/driver/ios/type-budget.d.ts +6 -0
  68. package/types/e2e/src/driver/observation-cache.d.ts +66 -0
  69. package/types/e2e/src/driver/open.d.ts +29 -0
  70. package/types/e2e/src/driver/settle.d.ts +43 -0
  71. package/types/e2e/src/driver/span-detail.d.ts +12 -0
  72. package/types/e2e/src/driver/traced-driver.d.ts +14 -0
  73. package/types/e2e/src/driver/typing.d.ts +48 -0
  74. package/types/e2e/src/driver/unwrap.d.ts +13 -0
  75. package/types/e2e/src/env.d.ts +78 -0
  76. package/types/e2e/src/errors.d.ts +26 -0
  77. package/types/e2e/src/expect/expect.d.ts +27 -0
  78. package/types/e2e/src/expect/matchers.d.ts +72 -0
  79. package/types/e2e/src/fixture-session.d.ts +38 -0
  80. package/types/e2e/src/fixtures.d.ts +14 -0
  81. package/types/e2e/src/index.d.ts +11 -0
  82. package/types/e2e/src/perf/budgets.d.ts +33 -0
  83. package/types/e2e/src/perf/device-perf.d.ts +45 -0
  84. package/types/e2e/src/perf/perf.types.d.ts +59 -0
  85. package/types/e2e/src/preload.d.ts +29 -0
  86. package/types/e2e/src/runner/artifacts.d.ts +13 -0
  87. package/types/e2e/src/runner/attempt.d.ts +63 -0
  88. package/types/e2e/src/runner/callsite.d.ts +2 -0
  89. package/types/e2e/src/runner/failure.d.ts +40 -0
  90. package/types/e2e/src/runner/fixtures.types.d.ts +60 -0
  91. package/types/e2e/src/runner/results.d.ts +48 -0
  92. package/types/e2e/src/runner/scope.d.ts +64 -0
  93. package/types/e2e/src/runner/span.d.ts +40 -0
  94. package/types/e2e/src/runner/step.d.ts +7 -0
  95. package/types/e2e/src/runner/test.d.ts +59 -0
  96. package/types/e2e/src/runner/trace.d.ts +87 -0
  97. package/types/e2e/src/screen/actions.d.ts +93 -0
  98. package/types/e2e/src/screen/context.d.ts +134 -0
  99. package/types/e2e/src/screen/field.d.ts +121 -0
  100. package/types/e2e/src/screen/locator.d.ts +233 -0
  101. package/types/e2e/src/screen/nodes.d.ts +53 -0
  102. package/types/e2e/src/screen/poll.d.ts +57 -0
  103. package/types/e2e/src/screen/queries.d.ts +34 -0
  104. package/types/e2e/src/screen/query.d.ts +60 -0
  105. package/types/e2e/src/screen/react-locator.d.ts +30 -0
  106. package/types/e2e/src/screen/render.d.ts +42 -0
  107. package/types/e2e/src/screen/roles.d.ts +24 -0
  108. package/types/e2e/src/screen/screen.d.ts +61 -0
  109. package/types/e2e/src/screen/selector.d.ts +38 -0
  110. package/types/e2e/src/screen/text.d.ts +13 -0
  111. package/types/e2e/src/session.d.ts +124 -0
  112. package/types/e2e/src/traced-device.d.ts +9 -0
  113. package/types/e2e/src/version.d.ts +7 -0
  114. package/types/types/src/result.d.ts +12 -0
  115. package/README.md +0 -3
@@ -0,0 +1,433 @@
1
+ import { z } from "zod";
2
+ import type { DriverError, Rect, Role, ScreenInfo } from "../driver.types";
3
+ /**
4
+ * Wire format of `warden-simd` (plan WDN-E2E, "warden-simd protocol (v1)"): newline-delimited JSON,
5
+ * one object per line. Requests `{id, op, …params, timeoutMs?}`; responses `{id, ok:true, data}` /
6
+ * `{id, ok:false, error}` (possibly out of order); events `{event:"ready"|"log"|"fatal", …}`.
7
+ */
8
+ export declare const protocolVersion = 1;
9
+ export declare const screenInfoSchema: z.ZodType<ScreenInfo>;
10
+ /**
11
+ * One AX node as the helper sends it. `id`, `normFrame`, `depth`, `traits`, `enabled` and `children`
12
+ * may be omitted (the TS driver fills them in `normalize.ts`) and any optional field may arrive as
13
+ * `null` (unknown); everything else is the `Element` shape.
14
+ */
15
+ export type WireElement = {
16
+ id?: string | null;
17
+ role: Role;
18
+ rawType: string;
19
+ label?: string | null;
20
+ identifier?: string | null;
21
+ value?: string | null;
22
+ text?: string | null;
23
+ placeholder?: string | null;
24
+ frame: Rect;
25
+ normFrame?: Rect | null;
26
+ traits?: string[] | null;
27
+ enabled?: boolean | null;
28
+ focused?: boolean | null;
29
+ hidden?: boolean | null;
30
+ selected?: boolean | null;
31
+ checked?: boolean | null;
32
+ hittable?: boolean | null;
33
+ tapPoint?: {
34
+ x: number;
35
+ y: number;
36
+ } | null;
37
+ pid?: number | null;
38
+ depth?: number | null;
39
+ children?: WireElement[] | null;
40
+ };
41
+ export declare const wireElementSchema: z.ZodType<WireElement>;
42
+ /**
43
+ * Structural check of one wire node and its subtree, equivalent to {@link wireElementSchema} (a test compares
44
+ * them) but cheaper: about 0.05 ms warm for a 35-node tree against 0.25 ms, and about 0.7 ms on the first call of
45
+ * a process against 2 ms (measured after the ready event had warmed zod). Unknown keys are accepted (a newer
46
+ * helper may add fields); `normalize.ts` reads only the known ones.
47
+ */
48
+ export declare function isWireElement(value: unknown): value is WireElement;
49
+ export declare const wireErrorSchema: z.ZodObject<{
50
+ code: z.ZodString;
51
+ message: z.ZodString;
52
+ retryable: z.ZodOptional<z.ZodBoolean>;
53
+ detail: z.ZodOptional<z.ZodUnknown>;
54
+ }, z.core.$strip>;
55
+ export type WireError = z.infer<typeof wireErrorSchema>;
56
+ export declare const readyEventSchema: z.ZodObject<{
57
+ event: z.ZodLiteral<"ready">;
58
+ protocol: z.ZodNumber;
59
+ version: z.ZodString;
60
+ udid: z.ZodString;
61
+ hid: z.ZodObject<{
62
+ transport: z.ZodString;
63
+ }, z.core.$strip>;
64
+ ax: z.ZodObject<{
65
+ default: z.ZodString;
66
+ bridge: z.ZodString;
67
+ }, z.core.$strip>;
68
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
69
+ }, z.core.$strip>;
70
+ export type ReadyEvent = z.infer<typeof readyEventSchema>;
71
+ export declare const logEventSchema: z.ZodObject<{
72
+ event: z.ZodLiteral<"log">;
73
+ level: z.ZodEnum<{
74
+ error: "error";
75
+ info: "info";
76
+ warn: "warn";
77
+ debug: "debug";
78
+ }>;
79
+ message: z.ZodString;
80
+ op: z.ZodOptional<z.ZodString>;
81
+ id: z.ZodOptional<z.ZodString>;
82
+ }, z.core.$strip>;
83
+ export type LogEvent = z.infer<typeof logEventSchema>;
84
+ export declare const fatalEventSchema: z.ZodObject<{
85
+ event: z.ZodLiteral<"fatal">;
86
+ error: z.ZodObject<{
87
+ code: z.ZodString;
88
+ message: z.ZodString;
89
+ retryable: z.ZodOptional<z.ZodBoolean>;
90
+ detail: z.ZodOptional<z.ZodUnknown>;
91
+ }, z.core.$strip>;
92
+ }, z.core.$strip>;
93
+ export type FatalEvent = z.infer<typeof fatalEventSchema>;
94
+ export declare const eventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
95
+ event: z.ZodLiteral<"ready">;
96
+ protocol: z.ZodNumber;
97
+ version: z.ZodString;
98
+ udid: z.ZodString;
99
+ hid: z.ZodObject<{
100
+ transport: z.ZodString;
101
+ }, z.core.$strip>;
102
+ ax: z.ZodObject<{
103
+ default: z.ZodString;
104
+ bridge: z.ZodString;
105
+ }, z.core.$strip>;
106
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
107
+ }, z.core.$strip>, z.ZodObject<{
108
+ event: z.ZodLiteral<"log">;
109
+ level: z.ZodEnum<{
110
+ error: "error";
111
+ info: "info";
112
+ warn: "warn";
113
+ debug: "debug";
114
+ }>;
115
+ message: z.ZodString;
116
+ op: z.ZodOptional<z.ZodString>;
117
+ id: z.ZodOptional<z.ZodString>;
118
+ }, z.core.$strip>, z.ZodObject<{
119
+ event: z.ZodLiteral<"fatal">;
120
+ error: z.ZodObject<{
121
+ code: z.ZodString;
122
+ message: z.ZodString;
123
+ retryable: z.ZodOptional<z.ZodBoolean>;
124
+ detail: z.ZodOptional<z.ZodUnknown>;
125
+ }, z.core.$strip>;
126
+ }, z.core.$strip>], "event">;
127
+ export type SimdEvent = z.infer<typeof eventSchema>;
128
+ export declare const responseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
129
+ id: z.ZodString;
130
+ ok: z.ZodLiteral<true>;
131
+ data: z.ZodOptional<z.ZodUnknown>;
132
+ }, z.core.$strip>, z.ZodObject<{
133
+ id: z.ZodString;
134
+ ok: z.ZodLiteral<false>;
135
+ error: z.ZodObject<{
136
+ code: z.ZodString;
137
+ message: z.ZodString;
138
+ retryable: z.ZodOptional<z.ZodBoolean>;
139
+ detail: z.ZodOptional<z.ZodUnknown>;
140
+ }, z.core.$strip>;
141
+ }, z.core.$strip>], "ok">;
142
+ export type SimdResponse = z.infer<typeof responseSchema>;
143
+ /** Any line the helper may send. Events carry `event`, responses carry `ok`. */
144
+ export type SimdMessage = {
145
+ kind: "event";
146
+ event: SimdEvent;
147
+ } | {
148
+ kind: "response";
149
+ response: SimdResponse;
150
+ };
151
+ export type ParsedLine = {
152
+ success: true;
153
+ message: SimdMessage;
154
+ } | {
155
+ success: false;
156
+ reason: string;
157
+ };
158
+ export declare function parseLine(line: string): ParsedLine;
159
+ export declare const healthDataSchema: z.ZodObject<{
160
+ version: z.ZodString;
161
+ udid: z.ZodString;
162
+ hid: z.ZodObject<{
163
+ transport: z.ZodString;
164
+ }, z.core.$strip>;
165
+ ax: z.ZodObject<{
166
+ default: z.ZodString;
167
+ bridge: z.ZodEnum<{
168
+ available: "available";
169
+ missing: "missing";
170
+ failed: "failed";
171
+ degraded: "degraded";
172
+ }>;
173
+ error: z.ZodOptional<z.ZodString>;
174
+ lastError: z.ZodOptional<z.ZodObject<{
175
+ message: z.ZodString;
176
+ agoMs: z.ZodNumber;
177
+ }, z.core.$strip>>;
178
+ }, z.core.$strip>;
179
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
180
+ socket: z.ZodOptional<z.ZodObject<{
181
+ path: z.ZodString;
182
+ clients: z.ZodNumber;
183
+ }, z.core.$strip>>;
184
+ idb: z.ZodOptional<z.ZodString>;
185
+ xcode: z.ZodOptional<z.ZodString>;
186
+ state: z.ZodOptional<z.ZodString>;
187
+ uptimeMs: z.ZodOptional<z.ZodNumber>;
188
+ }, z.core.$loose>;
189
+ export type HealthData = z.infer<typeof healthDataSchema>;
190
+ export declare const snapshotDataSchema: z.ZodObject<{
191
+ backend: z.ZodEnum<{
192
+ axbridge: "axbridge";
193
+ ax: "ax";
194
+ uiautomator: "uiautomator";
195
+ }>;
196
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
197
+ modal: z.ZodOptional<z.ZodNullable<z.ZodObject<{
198
+ pid: z.ZodOptional<z.ZodNumber>;
199
+ description: z.ZodOptional<z.ZodString>;
200
+ }, z.core.$strip>>>;
201
+ truncated: z.ZodBoolean;
202
+ elements: z.ZodArray<z.ZodCustom<WireElement, WireElement>>;
203
+ ms: z.ZodNumber;
204
+ fallback: z.ZodOptional<z.ZodObject<{
205
+ from: z.ZodString;
206
+ to: z.ZodString;
207
+ reason: z.ZodString;
208
+ }, z.core.$strip>>;
209
+ readMs: z.ZodOptional<z.ZodNumber>;
210
+ nodes: z.ZodOptional<z.ZodNumber>;
211
+ }, z.core.$loose>;
212
+ export type SnapshotData = z.infer<typeof snapshotDataSchema>;
213
+ export declare const elementAtPointDataSchema: z.ZodNullable<z.ZodType<WireElement, unknown, z.core.$ZodTypeInternals<WireElement, unknown>>>;
214
+ /** `path` when the helper wrote the PNG itself, else `png` as base64. */
215
+ export declare const screenshotDataSchema: z.ZodObject<{
216
+ path: z.ZodOptional<z.ZodString>;
217
+ png: z.ZodOptional<z.ZodString>;
218
+ width: z.ZodOptional<z.ZodNumber>;
219
+ height: z.ZodOptional<z.ZodNumber>;
220
+ }, z.core.$loose>;
221
+ export type ScreenshotData = z.infer<typeof screenshotDataSchema>;
222
+ /**
223
+ * `via`: `stream` (the guest reported run-loop idle) or `snapshot` (the stream was stuck: two identical reads); a
224
+ * value this client does not know reads as absent. `reason: "frontmost_mismatch"`: `bundleId` was asked for and never
225
+ * became the frontmost app before the deadline, and `frontmostPid` is what was frontmost instead.
226
+ */
227
+ export declare const settleDataSchema: z.ZodObject<{
228
+ quiet: z.ZodBoolean;
229
+ waitedMs: z.ZodNumber;
230
+ via: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
231
+ snapshot: "snapshot";
232
+ stream: "stream";
233
+ }>>>;
234
+ reason: z.ZodOptional<z.ZodString>;
235
+ frontmostPid: z.ZodOptional<z.ZodNumber>;
236
+ }, z.core.$loose>;
237
+ export type SettleData = z.infer<typeof settleDataSchema>;
238
+ /**
239
+ * `rebind` params: the helper (not the launch) waits until the quiescence stream reports on `bundleId`'s own process.
240
+ * `bound: false` is an answer, not an error: `reason` is `no_process` (the app never appeared), `timeout` (the stream
241
+ * stayed on another process) or `cancelled`. `restarts` is how many times the helper had to restart the stream.
242
+ */
243
+ export declare const rebindDataSchema: z.ZodObject<{
244
+ bound: z.ZodBoolean;
245
+ waitedMs: z.ZodNumber;
246
+ pid: z.ZodOptional<z.ZodNumber>;
247
+ restarts: z.ZodOptional<z.ZodNumber>;
248
+ recycled: z.ZodOptional<z.ZodBoolean>;
249
+ reason: z.ZodOptional<z.ZodString>;
250
+ }, z.core.$loose>;
251
+ export type RebindData = z.infer<typeof rebindDataSchema>;
252
+ /**
253
+ * `alertButtons` params. No `backend` reads both readers (`ax` first, then `axbridge`); `ax` or `axbridge` reads only
254
+ * that one: one tree read instead of two, errors propagate (nothing else answered), and an `axbridge` read that sees a
255
+ * modal without readable buttons answers `{ buttons: [] }` instead of `null`.
256
+ */
257
+ export type AlertButtonsParams = {
258
+ backend?: "ax" | "axbridge";
259
+ };
260
+ /** `alertButtons`: the system alert / sheet on top, `null` when there is none. */
261
+ export declare const alertButtonsDataSchema: z.ZodNullable<z.ZodObject<{
262
+ title: z.ZodOptional<z.ZodString>;
263
+ message: z.ZodOptional<z.ZodString>;
264
+ buttons: z.ZodArray<z.ZodType<WireElement, unknown, z.core.$ZodTypeInternals<WireElement, unknown>>>;
265
+ }, z.core.$strip>>;
266
+ export type AlertButtonsData = z.infer<typeof alertButtonsDataSchema>;
267
+ /**
268
+ * `frontmost{bundleId}`: whether that app's process is the one the quiescence stream reports as frontmost. A read of the
269
+ * helper's state (one launchd lookup), no tree read and no waiting. `pid` is the bundle's process (absent when it is not
270
+ * running), `frontmostPid` the stream's (absent while no stream has reported).
271
+ */
272
+ export declare const frontmostDataSchema: z.ZodObject<{
273
+ frontmost: z.ZodBoolean;
274
+ pid: z.ZodOptional<z.ZodNumber>;
275
+ frontmostPid: z.ZodOptional<z.ZodNumber>;
276
+ }, z.core.$loose>;
277
+ export type FrontmostData = z.infer<typeof frontmostDataSchema>;
278
+ /**
279
+ * `orientation`: a real read may also say `faceUp` / `faceDown` / `unknown` (flat device); `source` tells
280
+ * whether the value was read from the device, is the last one this helper wrote, or is an assumed portrait.
281
+ */
282
+ export declare const orientationDataSchema: z.ZodObject<{
283
+ orientation: z.ZodEnum<{
284
+ portrait: "portrait";
285
+ portraitUpsideDown: "portraitUpsideDown";
286
+ landscapeLeft: "landscapeLeft";
287
+ landscapeRight: "landscapeRight";
288
+ unknown: "unknown";
289
+ faceUp: "faceUp";
290
+ faceDown: "faceDown";
291
+ }>;
292
+ source: z.ZodOptional<z.ZodEnum<{
293
+ device: "device";
294
+ written: "written";
295
+ assumed: "assumed";
296
+ }>>;
297
+ }, z.core.$strip>;
298
+ export type OrientationData = z.infer<typeof orientationDataSchema>;
299
+ /** Ops whose `data` the client validates and types; every other op's data stays `unknown`. */
300
+ export declare const opSchemas: {
301
+ readonly health: z.ZodObject<{
302
+ version: z.ZodString;
303
+ udid: z.ZodString;
304
+ hid: z.ZodObject<{
305
+ transport: z.ZodString;
306
+ }, z.core.$strip>;
307
+ ax: z.ZodObject<{
308
+ default: z.ZodString;
309
+ bridge: z.ZodEnum<{
310
+ available: "available";
311
+ missing: "missing";
312
+ failed: "failed";
313
+ degraded: "degraded";
314
+ }>;
315
+ error: z.ZodOptional<z.ZodString>;
316
+ lastError: z.ZodOptional<z.ZodObject<{
317
+ message: z.ZodString;
318
+ agoMs: z.ZodNumber;
319
+ }, z.core.$strip>>;
320
+ }, z.core.$strip>;
321
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
322
+ socket: z.ZodOptional<z.ZodObject<{
323
+ path: z.ZodString;
324
+ clients: z.ZodNumber;
325
+ }, z.core.$strip>>;
326
+ idb: z.ZodOptional<z.ZodString>;
327
+ xcode: z.ZodOptional<z.ZodString>;
328
+ state: z.ZodOptional<z.ZodString>;
329
+ uptimeMs: z.ZodOptional<z.ZodNumber>;
330
+ }, z.core.$loose>;
331
+ readonly snapshot: z.ZodObject<{
332
+ backend: z.ZodEnum<{
333
+ axbridge: "axbridge";
334
+ ax: "ax";
335
+ uiautomator: "uiautomator";
336
+ }>;
337
+ screen: z.ZodType<ScreenInfo, unknown, z.core.$ZodTypeInternals<ScreenInfo, unknown>>;
338
+ modal: z.ZodOptional<z.ZodNullable<z.ZodObject<{
339
+ pid: z.ZodOptional<z.ZodNumber>;
340
+ description: z.ZodOptional<z.ZodString>;
341
+ }, z.core.$strip>>>;
342
+ truncated: z.ZodBoolean;
343
+ elements: z.ZodArray<z.ZodCustom<WireElement, WireElement>>;
344
+ ms: z.ZodNumber;
345
+ fallback: z.ZodOptional<z.ZodObject<{
346
+ from: z.ZodString;
347
+ to: z.ZodString;
348
+ reason: z.ZodString;
349
+ }, z.core.$strip>>;
350
+ readMs: z.ZodOptional<z.ZodNumber>;
351
+ nodes: z.ZodOptional<z.ZodNumber>;
352
+ }, z.core.$loose>;
353
+ readonly elementAtPoint: z.ZodNullable<z.ZodType<WireElement, unknown, z.core.$ZodTypeInternals<WireElement, unknown>>>;
354
+ readonly screenshot: z.ZodObject<{
355
+ path: z.ZodOptional<z.ZodString>;
356
+ png: z.ZodOptional<z.ZodString>;
357
+ width: z.ZodOptional<z.ZodNumber>;
358
+ height: z.ZodOptional<z.ZodNumber>;
359
+ }, z.core.$loose>;
360
+ readonly settle: z.ZodObject<{
361
+ quiet: z.ZodBoolean;
362
+ waitedMs: z.ZodNumber;
363
+ via: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
364
+ snapshot: "snapshot";
365
+ stream: "stream";
366
+ }>>>;
367
+ reason: z.ZodOptional<z.ZodString>;
368
+ frontmostPid: z.ZodOptional<z.ZodNumber>;
369
+ }, z.core.$loose>;
370
+ readonly rebind: z.ZodObject<{
371
+ bound: z.ZodBoolean;
372
+ waitedMs: z.ZodNumber;
373
+ pid: z.ZodOptional<z.ZodNumber>;
374
+ restarts: z.ZodOptional<z.ZodNumber>;
375
+ recycled: z.ZodOptional<z.ZodBoolean>;
376
+ reason: z.ZodOptional<z.ZodString>;
377
+ }, z.core.$loose>;
378
+ readonly alertButtons: z.ZodNullable<z.ZodObject<{
379
+ title: z.ZodOptional<z.ZodString>;
380
+ message: z.ZodOptional<z.ZodString>;
381
+ buttons: z.ZodArray<z.ZodType<WireElement, unknown, z.core.$ZodTypeInternals<WireElement, unknown>>>;
382
+ }, z.core.$strip>>;
383
+ readonly frontmost: z.ZodObject<{
384
+ frontmost: z.ZodBoolean;
385
+ pid: z.ZodOptional<z.ZodNumber>;
386
+ frontmostPid: z.ZodOptional<z.ZodNumber>;
387
+ }, z.core.$loose>;
388
+ readonly orientation: z.ZodObject<{
389
+ orientation: z.ZodEnum<{
390
+ portrait: "portrait";
391
+ portraitUpsideDown: "portraitUpsideDown";
392
+ landscapeLeft: "landscapeLeft";
393
+ landscapeRight: "landscapeRight";
394
+ unknown: "unknown";
395
+ faceUp: "faceUp";
396
+ faceDown: "faceDown";
397
+ }>;
398
+ source: z.ZodOptional<z.ZodEnum<{
399
+ device: "device";
400
+ written: "written";
401
+ assumed: "assumed";
402
+ }>>;
403
+ }, z.core.$strip>;
404
+ };
405
+ export type OpDataMap = {
406
+ health: HealthData;
407
+ snapshot: SnapshotData;
408
+ elementAtPoint: WireElement | null;
409
+ screenshot: ScreenshotData;
410
+ settle: SettleData;
411
+ rebind: RebindData;
412
+ alertButtons: AlertButtonsData;
413
+ frontmost: FrontmostData;
414
+ orientation: OrientationData;
415
+ };
416
+ export type OpData<Op extends string> = Op extends keyof OpDataMap ? OpDataMap[Op] : unknown;
417
+ export declare function hasOpSchema(op: string): op is keyof typeof opSchemas;
418
+ /** Wire code → `DriverErrorCode`: `E_UNKNOWN_UDID` is `E_UNKNOWN_DEVICE`, unknown codes are `E_INTERNAL` (code kept in `detail`). */
419
+ export declare function mapWireError(wire: WireError): DriverError;
420
+ export type LineSplitter = {
421
+ /** feed raw bytes; returns the complete lines (without `\n` / `\r\n`, blanks dropped) */
422
+ push(chunk: Uint8Array): string[];
423
+ /** the unterminated tail (a crashed helper may leave one) */
424
+ rest(): string;
425
+ };
426
+ /** Newline framing that is safe against chunk boundaries inside a line or a UTF-8 sequence. */
427
+ export declare function createLineSplitter(): LineSplitter;
428
+ export type SimdRequest = {
429
+ id: string;
430
+ op: string;
431
+ timeoutMs?: number;
432
+ } & Record<string, unknown>;
433
+ export declare function encodeRequest(request: SimdRequest): string;
@@ -0,0 +1,43 @@
1
+ import type { Result } from "../../../../types/src/result";
2
+ import type { DriverError } from "../driver.types";
3
+ /**
4
+ * The byte pipe under `simd-client`: a spawned helper's stdio or a unix socket. A transport only
5
+ * frames lines and reports closure; ids, timeouts and respawn live in the client.
6
+ */
7
+ export type TransportClose = {
8
+ exitCode: number | null;
9
+ stderrTail: string[];
10
+ };
11
+ export type TransportHandlers = {
12
+ onLine(line: string): void;
13
+ /** helper stderr (stdio mode) */
14
+ onDiagnostic(line: string): void;
15
+ onClose(info: TransportClose): void;
16
+ };
17
+ export type Transport = {
18
+ send(data: string): void;
19
+ /** graceful: stop input, wait for exit up to the grace period, then kill */
20
+ close(): Promise<void>;
21
+ };
22
+ export type TransportFactory = (handlers: TransportHandlers) => Promise<Result<Transport, DriverError>>;
23
+ /** The slice of a child process the stdio transport needs; tests and `bunSpawn` provide it. */
24
+ export type SimdProcess = {
25
+ write(data: string): void;
26
+ /** close stdin */
27
+ end(): void;
28
+ kill(): void;
29
+ stdout: ReadableStream<Uint8Array>;
30
+ stderr?: ReadableStream<Uint8Array>;
31
+ exited: Promise<number>;
32
+ };
33
+ export type SimdSpawn = (cmd: readonly string[]) => SimdProcess;
34
+ export declare const bunSpawn: SimdSpawn;
35
+ export declare function stdioTransport(opts: {
36
+ cmd: readonly string[];
37
+ spawn?: SimdSpawn;
38
+ /** how long `close()` waits for the helper to exit after closing stdin before killing it */
39
+ graceMs?: number;
40
+ }): TransportFactory;
41
+ export declare function socketTransport(opts: {
42
+ socketPath: string;
43
+ }): TransportFactory;
@@ -0,0 +1,6 @@
1
+ /** Per-request budget for the helper's `typeText`: it holds, paces and (for a repeated key) waits per character. */
2
+ export declare const TYPE_BASE_MS = 10000;
3
+ export declare const TYPE_PER_CHAR_MS = 70;
4
+ export declare const TYPE_PER_REPEAT_MS = 300;
5
+ /** Base + ~70 ms per character + 300 ms per character equal to the one before it. */
6
+ export declare function typeTextBudgetMs(text: string): number;
@@ -0,0 +1,66 @@
1
+ import type { AlertInfo, Driver, DriverResult, Platform, Snapshot } from "./driver.types";
2
+ /**
3
+ * A short-lived memory of the last whole-screen snapshot, so a read that follows another with no input in between
4
+ * does not walk the screen again (`isVisible()` then `text()` was two snapshots; on Android each one is a ~1.9 s
5
+ * `uiautomator dump`).
6
+ *
7
+ * It is a `Driver` wrapper, because every layer that can change the screen (`screen`, `app`, `device`, specs) shares
8
+ * the one driver: whatever calls it, an input moves the *generation* on and the kept snapshot dies with the old one.
9
+ * A snapshot is also dropped once it is older than the platform's max age, input or not (the app can change by itself).
10
+ * Which reads may reuse one is the caller's call (`observe({ reuse })`): only the first look of a wait does, so a
11
+ * poll never spins on a tree that stopped being true.
12
+ */
13
+ /** How old a kept snapshot may be and still answer a read. iOS reads cost ~100-300 ms; an Android dump takes ~1.9 s. */
14
+ export declare const OBSERVATION_MAX_AGE_MS: Record<Platform, number>;
15
+ /** Optional capability of the cached driver, next to the frozen `Driver` (pattern: `SelectsAll` in `typing.ts`). */
16
+ export type Observes = {
17
+ /** the whole screen: the kept snapshot when `reuse` and it is still good, else a new one (which is then kept) */
18
+ observe(options: {
19
+ reuse: boolean;
20
+ }): DriverResult<Snapshot>;
21
+ /** forgets the kept snapshot: the next `observe` reads the device */
22
+ invalidateObservations(): void;
23
+ /**
24
+ * The look before the next one, for an action's stability rule (a frame that held still across two looks). Never
25
+ * used to answer a read: the kept snapshot is returned whatever its age.
26
+ */
27
+ previous?(): PreviousLook;
28
+ /**
29
+ * The kept snapshot and its age, when no input came since it was taken (whatever its age; the caller judges). Never
30
+ * reads the device. For a tap that checks a young kept snapshot with a hit-test instead of taking a new one.
31
+ */
32
+ peek?(): KeptLook | undefined;
33
+ };
34
+ export type KeptLook = {
35
+ snapshot: Snapshot;
36
+ ageMs: number;
37
+ };
38
+ export type PreviousLook = {
39
+ /** the kept snapshot, when no input came since it was taken (whatever its age) */
40
+ snapshot: Snapshot | undefined;
41
+ /** the input generation now: two answers with the same number had no input between them */
42
+ generation: number;
43
+ /** ms since the last input ended; undefined before any input */
44
+ sinceInputMs: number | undefined;
45
+ };
46
+ export declare function canObserve(driver: Driver): driver is Driver & Observes;
47
+ /**
48
+ * Optional capability: the system alert, worked out from a snapshot already taken (Android: alerts are windows in the
49
+ * dump). With it the cache answers `alert()` from the kept snapshot instead of dumping the screen again.
50
+ */
51
+ export type DetectsAlerts = {
52
+ alertIn(snapshot: Snapshot): AlertInfo | null;
53
+ };
54
+ export declare function canDetectAlerts(driver: Driver): driver is Driver & DetectsAlerts;
55
+ export type ObservationCacheOptions = {
56
+ /** time source (ms); default `Date.now` */
57
+ now?: () => number;
58
+ /** default `OBSERVATION_MAX_AGE_MS` for the driver's platform */
59
+ maxAgeMs?: number;
60
+ };
61
+ /**
62
+ * Wraps `driver` (a `Proxy`: every member, optional capabilities included, reads through unchanged) with the
63
+ * observation cache and the {@link Observes} capability. Put it outside the tracing wrapper, so a snapshot that was
64
+ * served from memory leaves no `driver.snapshot` span.
65
+ */
66
+ export declare function cacheObservations<D extends Driver>(driver: D, options?: ObservationCacheOptions): D & Observes;
@@ -0,0 +1,29 @@
1
+ import { type Exec } from "../../../core/src/exec";
2
+ import type { E2eEnv } from "../env";
3
+ import type { DriverFactory } from "../session";
4
+ import { type AndroidDriverOptions } from "./android/android-driver";
5
+ import type { Driver, DriverResult } from "./driver.types";
6
+ import { type OpenIosDriverOptions } from "./ios/ios-driver";
7
+ /**
8
+ * Test seams for {@link openDriver}: everything the platform openers inject except what the env supplies.
9
+ * `android` carries the Android-only seams (`adb` path, resident-shell spawn, binary runner, clock).
10
+ */
11
+ export type OpenDriverDeps = Omit<OpenIosDriverOptions, "udid" | "env" | "exec"> & {
12
+ exec?: Exec;
13
+ android?: Omit<AndroidDriverOptions, "serial" | "exec" | "log" | "adb"> & {
14
+ adb?: string;
15
+ };
16
+ };
17
+ /** `WARDEN_E2E_DEBUG=1` logs every helper op and simctl call with its duration to stderr. */
18
+ export declare const DEBUG_ENV = "WARDEN_E2E_DEBUG";
19
+ /**
20
+ * The Android opener's options: the env's serial and app package, the `state` store under `<wardenHome>/android`
21
+ * (a caller's own `android.state` wins) that remembers the dump route that worked and the animation scales to put
22
+ * back, the resident `warden-uiad` server (unless `WARDEN_ANDROID_UIAD=0`, a caller's own `android.uiad`, or an injected
23
+ * shell `spawn`, which is a test that must never reach a real `adb`), and the injected seams.
24
+ */
25
+ export declare function androidOptions(env: E2eEnv, deps: OpenDriverDeps, debug: boolean): AndroidDriverOptions;
26
+ /** Open the `Driver` for the device in `env`, by platform. Android deep links go to `env.bundleId` only. */
27
+ export declare function openDriver(env: E2eEnv, deps?: OpenDriverDeps): DriverResult<Driver>;
28
+ /** What the session uses when no factory is passed; `preload.ts` registers it with `setDefaultDriverFactory`. */
29
+ export declare const defaultDriverFactory: DriverFactory;
@@ -0,0 +1,43 @@
1
+ import type { Snapshot } from "./driver.types";
2
+ export type SettleDeps = {
3
+ quietMs: number;
4
+ timeoutMs: number;
5
+ /** monotonic-ish clock in ms */
6
+ now: () => number;
7
+ sleep: (ms: number) => Promise<void>;
8
+ /** gap between polls, default 50 */
9
+ pollMs?: number;
10
+ };
11
+ export type SettleOutcome = {
12
+ quiet: boolean;
13
+ waitedMs: number;
14
+ };
15
+ /** How a settle decided: the helper's quiescence `stream` (iOS `warden-simd`, Android `warden-uiad`: the accessibility events stopped), the `snapshot` stability fallback, or client-side snapshot `hash` polling. */
16
+ export type SettleVia = "stream" | "snapshot" | "hash";
17
+ /**
18
+ * What a driver's `settle` may report beyond the frozen `{ quiet, waitedMs }` of `Driver["settle"]` (a driver
19
+ * returns this wider object; the contract in `driver.types.ts` is unchanged). iOS passes the helper's reply through:
20
+ * `via`, `reason` (`frontmost_mismatch` when the launched app never came to the front, `helper_timeout` when the
21
+ * helper answered after the client's padded timer) and `frontmostPid`. Android says `stream` when `warden-uiad` waited
22
+ * for the events to stop, else `snapshot` when one `uiautomator dump` covered the whole quiet window and `hash` when it
23
+ * compared successive snapshots; the iOS hash fallback says `hash`.
24
+ */
25
+ export type SettleDetail = SettleOutcome & {
26
+ via?: SettleVia;
27
+ reason?: string;
28
+ frontmostPid?: number;
29
+ };
30
+ /** The extra fields of a settle reply, kept when they have the right type. `Driver["settle"]` is typed narrower than it answers. */
31
+ export declare function settleDetailOf(outcome: SettleOutcome): SettleDetail;
32
+ /** A screen counts as settled once its hash stayed equal this long (`device.settle`, `warden ui --settle`). */
33
+ export declare const DEFAULT_SETTLE_QUIET_MS = 250;
34
+ /** How long a settle waits for quiet before it gives up. */
35
+ export declare const DEFAULT_SETTLE_TIMEOUT_MS = 3000;
36
+ /**
37
+ * Snapshot-hash settle: poll a UI fingerprint until it stays unchanged for `quietMs`
38
+ * (two consecutive equal hashes and ≥ quietMs since the last change), or give up at `timeoutMs`.
39
+ * Side effects are injected so tests drive a fake clock.
40
+ */
41
+ export declare function settleByHash(poll: () => Promise<string>, deps: SettleDeps): Promise<SettleOutcome>;
42
+ /** Stable fingerprint over `(role, identifier, label, value, frame)` of every node in preorder. */
43
+ export declare function snapshotHash(snapshot: Pick<Snapshot, "flat">): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Where code deep inside a driver call (an adb command, the dump route, a settle verdict) leaves a note for the
3
+ * `span` that is timing that call, without the driver knowing about tracing: a note outside a span goes nowhere.
4
+ * Values are scalars so a span stays one short JSON line.
5
+ */
6
+ export type SpanDetail = Record<string, string | number | boolean>;
7
+ /** Runs `fn` with `notes` as the sink for every {@link noteSpanDetail} / {@link addSpanDetail} made inside it, awaits included. */
8
+ export declare function collectSpanDetail<T>(notes: SpanDetail, fn: () => T): T;
9
+ /** Sets `key` on the innermost span being timed. */
10
+ export declare function noteSpanDetail(key: string, value: string | number | boolean): void;
11
+ /** Adds `amount` to a numeric `key` of the innermost span (a counter or a sum of durations). */
12
+ export declare function addSpanDetail(key: string, amount: number): void;
@@ -0,0 +1,14 @@
1
+ import { type SpanSink } from "../runner/span";
2
+ import type { Driver } from "./driver.types";
3
+ export type TracedDriverOptions = {
4
+ /** where spans go right now: the running attempt's trace, `undefined` between attempts. Read per call. */
5
+ trace: () => SpanSink | undefined;
6
+ now?: () => number;
7
+ };
8
+ /**
9
+ * Wraps `driver` so every call it answers with a promise (`snapshot`, `tap`, `settle`, `app.launch`, and whatever
10
+ * optional capability it offers, such as `pressKeyRepeat`) writes a `driver.<call>` span to the running attempt's
11
+ * trace. It is a `Proxy`, so every other member (`platform`, `capabilities`, a synchronous method) reads through
12
+ * unchanged, and nothing is recorded outside an attempt. Arguments are never recorded: `typeText` carries passwords.
13
+ */
14
+ export declare function traceDriver<D extends Driver>(driver: D, options: TracedDriverOptions): D;