@nouhouari/conductor-e2e 0.0.0-stage → 0.1.8

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 (101) hide show
  1. package/CHANGELOG.md +228 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -2
  4. package/config/environments/default.ts +41 -0
  5. package/config/environments/dev.ts +16 -0
  6. package/config/environments/staging.ts +15 -0
  7. package/config/index.ts +70 -0
  8. package/config/types.ts +94 -0
  9. package/dist/config/environments/default.d.ts +3 -0
  10. package/dist/config/environments/default.d.ts.map +1 -0
  11. package/dist/config/environments/default.js +40 -0
  12. package/dist/config/environments/default.js.map +1 -0
  13. package/dist/config/environments/dev.d.ts +3 -0
  14. package/dist/config/environments/dev.d.ts.map +1 -0
  15. package/dist/config/environments/dev.js +18 -0
  16. package/dist/config/environments/dev.js.map +1 -0
  17. package/dist/config/environments/staging.d.ts +3 -0
  18. package/dist/config/environments/staging.d.ts.map +1 -0
  19. package/dist/config/environments/staging.js +17 -0
  20. package/dist/config/environments/staging.js.map +1 -0
  21. package/dist/config/index.d.ts +7 -0
  22. package/dist/config/index.d.ts.map +1 -0
  23. package/dist/config/index.js +81 -0
  24. package/dist/config/index.js.map +1 -0
  25. package/dist/config/types.d.ts +93 -0
  26. package/dist/config/types.d.ts.map +1 -0
  27. package/dist/config/types.js +3 -0
  28. package/dist/config/types.js.map +1 -0
  29. package/dist/src/drivers/ApiDriver.d.ts +16 -0
  30. package/dist/src/drivers/ApiDriver.d.ts.map +1 -0
  31. package/dist/src/drivers/ApiDriver.js +48 -0
  32. package/dist/src/drivers/ApiDriver.js.map +1 -0
  33. package/dist/src/drivers/DatabaseDriver.d.ts +12 -0
  34. package/dist/src/drivers/DatabaseDriver.d.ts.map +1 -0
  35. package/dist/src/drivers/DatabaseDriver.js +15 -0
  36. package/dist/src/drivers/DatabaseDriver.js.map +1 -0
  37. package/dist/src/drivers/FlutterDesktopDriver.d.ts +139 -0
  38. package/dist/src/drivers/FlutterDesktopDriver.d.ts.map +1 -0
  39. package/dist/src/drivers/FlutterDesktopDriver.js +445 -0
  40. package/dist/src/drivers/FlutterDesktopDriver.js.map +1 -0
  41. package/dist/src/drivers/MaestroDriver.d.ts +19 -0
  42. package/dist/src/drivers/MaestroDriver.d.ts.map +1 -0
  43. package/dist/src/drivers/MaestroDriver.js +144 -0
  44. package/dist/src/drivers/MaestroDriver.js.map +1 -0
  45. package/dist/src/drivers/WebDriver.d.ts +21 -0
  46. package/dist/src/drivers/WebDriver.d.ts.map +1 -0
  47. package/dist/src/drivers/WebDriver.js +57 -0
  48. package/dist/src/drivers/WebDriver.js.map +1 -0
  49. package/dist/src/hooks/browser.hooks.d.ts +2 -0
  50. package/dist/src/hooks/browser.hooks.d.ts.map +1 -0
  51. package/dist/src/hooks/browser.hooks.js +15 -0
  52. package/dist/src/hooks/browser.hooks.js.map +1 -0
  53. package/dist/src/hooks/database.hooks.d.ts +2 -0
  54. package/dist/src/hooks/database.hooks.d.ts.map +1 -0
  55. package/dist/src/hooks/database.hooks.js +11 -0
  56. package/dist/src/hooks/database.hooks.js.map +1 -0
  57. package/dist/src/hooks/desktop.hooks.d.ts +2 -0
  58. package/dist/src/hooks/desktop.hooks.d.ts.map +1 -0
  59. package/dist/src/hooks/desktop.hooks.js +15 -0
  60. package/dist/src/hooks/desktop.hooks.js.map +1 -0
  61. package/dist/src/hooks/flutterDesktop.hooks.d.ts +2 -0
  62. package/dist/src/hooks/flutterDesktop.hooks.d.ts.map +1 -0
  63. package/dist/src/hooks/flutterDesktop.hooks.js +26 -0
  64. package/dist/src/hooks/flutterDesktop.hooks.js.map +1 -0
  65. package/dist/src/hooks/index.d.ts +6 -0
  66. package/dist/src/hooks/index.d.ts.map +1 -0
  67. package/dist/src/hooks/index.js +25 -0
  68. package/dist/src/hooks/index.js.map +1 -0
  69. package/dist/src/hooks/maestro.hooks.d.ts +2 -0
  70. package/dist/src/hooks/maestro.hooks.d.ts.map +1 -0
  71. package/dist/src/hooks/maestro.hooks.js +8 -0
  72. package/dist/src/hooks/maestro.hooks.js.map +1 -0
  73. package/dist/src/index.d.ts +21 -0
  74. package/dist/src/index.d.ts.map +1 -0
  75. package/dist/src/index.js +30 -0
  76. package/dist/src/index.js.map +1 -0
  77. package/dist/src/pages/BasePage.d.ts +11 -0
  78. package/dist/src/pages/BasePage.d.ts.map +1 -0
  79. package/dist/src/pages/BasePage.js +22 -0
  80. package/dist/src/pages/BasePage.js.map +1 -0
  81. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts +51 -0
  82. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts.map +1 -0
  83. package/dist/src/scenarios/RemoteScenarioFetcher.js +162 -0
  84. package/dist/src/scenarios/RemoteScenarioFetcher.js.map +1 -0
  85. package/dist/src/scenarios/cli.d.ts +3 -0
  86. package/dist/src/scenarios/cli.d.ts.map +1 -0
  87. package/dist/src/scenarios/cli.js +26 -0
  88. package/dist/src/scenarios/cli.js.map +1 -0
  89. package/dist/src/support/logger.d.ts +3 -0
  90. package/dist/src/support/logger.d.ts.map +1 -0
  91. package/dist/src/support/logger.js +16 -0
  92. package/dist/src/support/logger.js.map +1 -0
  93. package/dist/src/support/retry.d.ts +7 -0
  94. package/dist/src/support/retry.d.ts.map +1 -0
  95. package/dist/src/support/retry.js +21 -0
  96. package/dist/src/support/retry.js.map +1 -0
  97. package/dist/src/world/ConductorWorld.d.ts +39 -0
  98. package/dist/src/world/ConductorWorld.d.ts.map +1 -0
  99. package/dist/src/world/ConductorWorld.js +112 -0
  100. package/dist/src/world/ConductorWorld.js.map +1 -0
  101. package/package.json +81 -4
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FlutterDesktopDriver = void 0;
40
+ const child_process_1 = require("child_process");
41
+ const path = __importStar(require("path"));
42
+ const fs = __importStar(require("fs"));
43
+ const ws_1 = __importDefault(require("ws"));
44
+ const VM_URL_REGEX = /(?:Dart VM service|Observatory) is listening on (https?:\/\/[^\s]+)/i;
45
+ const STREAM = process.env.DEBUG_FLUTTER_DESKTOP !== '0' && process.env.DEBUG_FLUTTER_DESKTOP !== 'false';
46
+ class FlutterDesktopDriver {
47
+ cfg;
48
+ proc = null;
49
+ ws = null;
50
+ isolateId = null;
51
+ nextRpcId = 1;
52
+ pending = new Map();
53
+ textEntryEmulationEnabled = false;
54
+ constructor(env) {
55
+ if (!env.flutterDesktop) {
56
+ throw new Error('No flutterDesktop config. Set config.flutterDesktop with FlutterDesktopConfig.');
57
+ }
58
+ this.cfg = env.flutterDesktop;
59
+ }
60
+ get isLaunched() {
61
+ return this.ws !== null && this.isolateId !== null;
62
+ }
63
+ // ─── lifecycle ──────────────────────────────────────────────────────────────
64
+ async launch() {
65
+ if (this.isLaunched)
66
+ return;
67
+ const exe = this.cfg.appPath;
68
+ if (!fs.existsSync(exe)) {
69
+ throw new Error(`Flutter desktop executable not found: ${exe}\nBuild it first, e.g. \`flutter build macos --profile -t lib/main_test.dart\`.`);
70
+ }
71
+ const args = [...(this.cfg.extraArgs ?? [])];
72
+ if (this.cfg.vmServicePort)
73
+ args.push(`--vm-service-port=${this.cfg.vmServicePort}`);
74
+ const launchTimeoutMs = this.cfg.launchTimeoutMs ?? 30_000;
75
+ if (STREAM)
76
+ process.stderr.write(`\n[flutter-desktop] ▶ launching ${exe}\n`);
77
+ const proc = (0, child_process_1.spawn)(exe, args, {
78
+ env: { ...process.env, ...(this.cfg.env ?? {}) },
79
+ stdio: ['ignore', 'pipe', 'pipe']
80
+ });
81
+ this.proc = proc;
82
+ proc.on('error', (err) => {
83
+ if (STREAM)
84
+ process.stderr.write(`[flutter-desktop] spawn error: ${err.message}\n`);
85
+ });
86
+ const vmUrl = await this.waitForVmServiceUrl(proc, launchTimeoutMs);
87
+ if (STREAM)
88
+ process.stderr.write(`[flutter-desktop] VM service: ${vmUrl}\n`);
89
+ await this.connectWebSocket(vmUrl);
90
+ await this.resolveIsolateAndDriverExtension(launchTimeoutMs);
91
+ if (STREAM)
92
+ process.stderr.write(`[flutter-desktop] ✔ ready (isolate=${this.isolateId})\n`);
93
+ }
94
+ /**
95
+ * Connect to an already-running Flutter app via its Dart VM service URL.
96
+ * Use instead of `launch()` when the app is already running — e.g.:
97
+ * - **Android**: `adb forward tcp:PORT tcp:PORT`, then connect to `ws://localhost:PORT/TOKEN/ws`
98
+ * - **iOS**: `iproxy PORT PORT DEVICE_UDID`, then connect
99
+ * - **Windows / Linux desktop**: manage the process yourself and pass the URL
100
+ *
101
+ * Accepts either the HTTP form printed by the app (`http://localhost:PORT/TOKEN/`)
102
+ * or the WebSocket form directly (`ws://localhost:PORT/TOKEN/ws`).
103
+ */
104
+ async connect(vmServiceUrl, timeoutMs) {
105
+ if (this.isLaunched)
106
+ return;
107
+ const t = timeoutMs ?? this.cfg.launchTimeoutMs ?? 30_000;
108
+ if (STREAM)
109
+ process.stderr.write(`\n[flutter-desktop] ⚡ connecting to ${vmServiceUrl}\n`);
110
+ await this.connectWebSocket(vmServiceUrl);
111
+ await this.resolveIsolateAndDriverExtension(t);
112
+ if (STREAM)
113
+ process.stderr.write(`[flutter-desktop] ✔ ready (isolate=${this.isolateId})\n`);
114
+ }
115
+ async close() {
116
+ // Reject any pending RPCs
117
+ for (const [, p] of this.pending) {
118
+ clearTimeout(p.timer);
119
+ p.reject(new Error('FlutterDesktopDriver closed'));
120
+ }
121
+ this.pending.clear();
122
+ if (this.ws) {
123
+ try {
124
+ this.ws.close();
125
+ }
126
+ catch { }
127
+ this.ws = null;
128
+ }
129
+ if (this.proc && !this.proc.killed) {
130
+ this.proc.kill('SIGTERM');
131
+ // Force-kill after 2s
132
+ const proc = this.proc;
133
+ await new Promise((resolve) => {
134
+ const t = setTimeout(() => { try {
135
+ proc.kill('SIGKILL');
136
+ }
137
+ catch { } resolve(); }, 2000);
138
+ proc.once('exit', () => { clearTimeout(t); resolve(); });
139
+ });
140
+ }
141
+ this.proc = null;
142
+ this.isolateId = null;
143
+ this.textEntryEmulationEnabled = false;
144
+ }
145
+ // ─── public actions ─────────────────────────────────────────────────────────
146
+ /** Tap a widget identified by `finder`. */
147
+ async tap(finder, timeoutMs) {
148
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
149
+ await this.driverCommand({ command: 'tap', ...this.serializeFinder(finder), timeout: String(t) }, t + 2000);
150
+ }
151
+ /** Type `text` into the currently focused text field.
152
+ * Emulation must be enabled BEFORE tapping so that `TextInput.setClient`
153
+ * is captured by the mock — otherwise the mock's _client stays null and
154
+ * enter_text is silently ignored. */
155
+ async enterText(finder, text, timeoutMs) {
156
+ if (!this.textEntryEmulationEnabled) {
157
+ await this.driverCommand({ command: 'set_text_entry_emulation', enabled: 'true' }, timeoutMs);
158
+ this.textEntryEmulationEnabled = true;
159
+ }
160
+ await this.tap(finder, timeoutMs);
161
+ await this.driverCommand({ command: 'enter_text', text }, timeoutMs);
162
+ }
163
+ /**
164
+ * Send a message to the app's `enableFlutterDriverExtension` data handler
165
+ * and return the response string. Use this to invoke app-side actions that
166
+ * cannot be driven through the gesture system (e.g. tapping widgets inside
167
+ * a scrollable that blocks flutter_driver's hitTestable() check).
168
+ */
169
+ async requestData(message, timeoutMs) {
170
+ const result = await this.driverCommand({ command: 'request_data', message }, timeoutMs);
171
+ return result.message ?? '';
172
+ }
173
+ /** Read the text of a Text widget at `finder`. */
174
+ async getText(finder, timeoutMs) {
175
+ const result = await this.driverCommand({ command: 'get_text', ...this.serializeFinder(finder) }, timeoutMs);
176
+ return result.text ?? '';
177
+ }
178
+ /** Wait for `finder` to resolve to an existing widget. */
179
+ async waitFor(finder, timeoutMs) {
180
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
181
+ await this.driverCommand({ command: 'waitFor', ...this.serializeFinder(finder), timeout: String(t) }, t + 2000 // give the wire timeout some headroom over the driver timeout
182
+ );
183
+ }
184
+ /** Wait until `finder` no longer resolves to any widget. */
185
+ async waitForAbsent(finder, timeoutMs) {
186
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
187
+ await this.driverCommand({ command: 'waitForAbsent', ...this.serializeFinder(finder), timeout: String(t) }, t + 2000);
188
+ }
189
+ /**
190
+ * Take a screenshot of the Flutter app's render surface via the
191
+ * `ext.flutter.driver` `screenshot` command. Returns a PNG path.
192
+ *
193
+ * This goes over the same WebSocket as the rest of the driver — no OS-level
194
+ * screen-recording permissions are required, and only the app surface is
195
+ * captured (not the whole desktop).
196
+ */
197
+ async takeScreenshot(name) {
198
+ const outDir = this.cfg.screenshotDir ?? 'reports/screenshots';
199
+ fs.mkdirSync(outDir, { recursive: true });
200
+ const outPath = path.resolve(outDir, `${name}.png`);
201
+ const result = await this.driverCommand({ command: 'screenshot' });
202
+ if (!result?.screenshot) {
203
+ throw new Error('flutter_driver screenshot returned no payload');
204
+ }
205
+ fs.writeFileSync(outPath, Buffer.from(result.screenshot, 'base64'));
206
+ return outPath;
207
+ }
208
+ /** Double-tap a widget identified by `finder`. */
209
+ async doubleTap(finder, timeoutMs) {
210
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
211
+ await this.driverCommand({ command: 'double_tap', ...this.serializeFinder(finder), timeout: String(t) }, t + 2000);
212
+ }
213
+ /** Long-press a widget identified by `finder`. */
214
+ async longPress(finder, timeoutMs) {
215
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
216
+ await this.driverCommand({ command: 'long_press', ...this.serializeFinder(finder), timeout: String(t) }, t + 2000);
217
+ }
218
+ /**
219
+ * Scroll a Scrollable widget identified by `finder` by (`dx`, `dy`) pixels
220
+ * over `durationMs` milliseconds at `frequency` Hz.
221
+ */
222
+ async scroll(finder, dx, dy, durationMs, frequency, timeoutMs) {
223
+ const duration = durationMs ?? 300;
224
+ const freq = frequency ?? 60;
225
+ const wireTimeout = timeoutMs ?? (duration + 5_000);
226
+ await this.driverCommand({ command: 'scroll', ...this.serializeFinder(finder), dx, dy, duration, frequency: freq }, wireTimeout);
227
+ }
228
+ /**
229
+ * Scroll until `finder` is visible.
230
+ * `alignment` controls where the widget lands: 0.0 = top edge, 0.5 = center, 1.0 = bottom edge.
231
+ */
232
+ async scrollIntoView(finder, alignment, timeoutMs) {
233
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
234
+ await this.driverCommand({ command: 'scrollIntoView', ...this.serializeFinder(finder), alignment: alignment ?? 0.0 }, t + 2000);
235
+ }
236
+ /**
237
+ * Clear the text field at `finder` by enabling text-entry emulation,
238
+ * tapping to focus, then setting its value to an empty string.
239
+ */
240
+ async clearText(finder, timeoutMs) {
241
+ if (!this.textEntryEmulationEnabled) {
242
+ await this.driverCommand({ command: 'set_text_entry_emulation', enabled: 'true' }, timeoutMs);
243
+ this.textEntryEmulationEnabled = true;
244
+ }
245
+ await this.tap(finder, timeoutMs);
246
+ await this.driverCommand({ command: 'enter_text', text: '' }, timeoutMs);
247
+ }
248
+ /**
249
+ * Non-throwing visibility probe: returns `true` if `finder` resolves within
250
+ * `timeoutMs` (default 500 ms), `false` otherwise. Use for conditional
251
+ * assertions instead of `waitFor` when absence is acceptable.
252
+ */
253
+ async isVisible(finder, timeoutMs) {
254
+ try {
255
+ await this.waitFor(finder, timeoutMs ?? 500);
256
+ return true;
257
+ }
258
+ catch {
259
+ return false;
260
+ }
261
+ }
262
+ /**
263
+ * Return the screen coordinates of a point on the widget at `finder`.
264
+ * `offsetType` defaults to `'center'`.
265
+ */
266
+ async getOffset(finder, offsetType, timeoutMs) {
267
+ const result = await this.driverCommand({ command: 'get_offset', ...this.serializeFinder(finder), offsetType: offsetType ?? 'center' }, timeoutMs);
268
+ return { dx: result.dx ?? 0, dy: result.dy ?? 0 };
269
+ }
270
+ /**
271
+ * Wait until a predefined Flutter condition is satisfied — the app-level
272
+ * equivalent of Playwright's `page.waitForLoadState()`.
273
+ *
274
+ * `'NoPendingFrames'` — no animation frames scheduled (app is idle)
275
+ * `'NoTransientCallbacks'` — no pending transient callbacks
276
+ * `'FirstFrameRasterized'` — first frame has been rendered
277
+ */
278
+ async waitForCondition(condition, timeoutMs) {
279
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
280
+ await this.driverCommand({ command: 'waitForCondition', conditionJson: JSON.stringify({ conditionName: condition }), timeout: String(t) }, t + 2000);
281
+ }
282
+ /**
283
+ * Enable or disable Flutter's frame-sync during driver commands. Set to
284
+ * `false` before triggering heavy animations so the driver does not stall
285
+ * waiting for each frame to settle; restore with `setFrameSync(true)` when
286
+ * done. Mirrors disabling CSS transitions in web tests.
287
+ */
288
+ async setFrameSync(enabled, timeoutMs) {
289
+ await this.driverCommand({ command: 'set_frame_sync', enabled: String(enabled) }, timeoutMs);
290
+ }
291
+ /**
292
+ * NOTE: `isEnabled` (checking whether a widget is interactive) is not part
293
+ * of the `ext.flutter.driver` protocol. Use `requestData()` with an app-side
294
+ * handler that inspects widget state and returns the result as a string.
295
+ */
296
+ // ─── internals ──────────────────────────────────────────────────────────────
297
+ serializeFinder(finder) {
298
+ switch (finder.type) {
299
+ case 'ByValueKey':
300
+ // flutter_driver expects keyValueString + keyValueType ('String' | 'int')
301
+ return {
302
+ finderType: 'ByValueKey',
303
+ keyValueString: finder.value,
304
+ keyValueType: 'String'
305
+ };
306
+ case 'ByText':
307
+ return { finderType: 'ByText', text: finder.value };
308
+ case 'ByType':
309
+ return { finderType: 'ByType', type: finder.value };
310
+ case 'ByTooltipMessage':
311
+ return { finderType: 'ByTooltipMessage', text: finder.value };
312
+ }
313
+ }
314
+ /** Read stdout/stderr until we see a VM service URL or hit the timeout. */
315
+ waitForVmServiceUrl(proc, timeoutMs) {
316
+ return new Promise((resolve, reject) => {
317
+ let buffer = '';
318
+ let settled = false;
319
+ const timer = setTimeout(() => {
320
+ if (settled)
321
+ return;
322
+ settled = true;
323
+ proc.kill('SIGTERM');
324
+ reject(new Error(`Timed out (${timeoutMs}ms) waiting for VM service URL on stdout. Captured:\n${buffer}`));
325
+ }, timeoutMs);
326
+ const onData = (chunk) => {
327
+ const text = chunk.toString();
328
+ buffer += text;
329
+ if (STREAM) {
330
+ for (const line of text.split('\n')) {
331
+ if (line.trim())
332
+ process.stderr.write(`[flutter-desktop] ${line}\n`);
333
+ }
334
+ }
335
+ const m = buffer.match(VM_URL_REGEX);
336
+ if (m && !settled) {
337
+ settled = true;
338
+ clearTimeout(timer);
339
+ resolve(m[1]);
340
+ }
341
+ };
342
+ proc.stdout?.on('data', onData);
343
+ proc.stderr?.on('data', onData);
344
+ proc.once('exit', (code) => {
345
+ if (settled)
346
+ return;
347
+ settled = true;
348
+ clearTimeout(timer);
349
+ reject(new Error(`Process exited (code=${code}) before VM service URL appeared. Captured:\n${buffer}`));
350
+ });
351
+ });
352
+ }
353
+ connectWebSocket(vmUrl) {
354
+ // http(s)://host:port/TOKEN/ → ws(s)://host:port/TOKEN/ws
355
+ const url = new URL(vmUrl);
356
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
357
+ if (!url.pathname.endsWith('/'))
358
+ url.pathname += '/';
359
+ url.pathname += 'ws';
360
+ const wsUrl = url.toString();
361
+ return new Promise((resolve, reject) => {
362
+ const ws = new ws_1.default(wsUrl);
363
+ this.ws = ws;
364
+ ws.once('open', () => resolve());
365
+ ws.once('error', (err) => reject(new Error(`Failed to connect to VM service: ${err.message}`)));
366
+ ws.on('message', (data) => this.onMessage(data));
367
+ ws.on('close', () => {
368
+ // Fail any pending RPCs
369
+ for (const [, p] of this.pending) {
370
+ clearTimeout(p.timer);
371
+ p.reject(new Error('VM service WebSocket closed'));
372
+ }
373
+ this.pending.clear();
374
+ });
375
+ });
376
+ }
377
+ onMessage(data) {
378
+ let msg;
379
+ try {
380
+ msg = JSON.parse(data.toString());
381
+ }
382
+ catch {
383
+ return;
384
+ }
385
+ if (typeof msg.id !== 'number')
386
+ return; // ignore events
387
+ const pending = this.pending.get(msg.id);
388
+ if (!pending)
389
+ return;
390
+ this.pending.delete(msg.id);
391
+ clearTimeout(pending.timer);
392
+ if (msg.error) {
393
+ pending.reject(new Error(`VM service error (${msg.error.code}): ${msg.error.message}`));
394
+ }
395
+ else {
396
+ pending.resolve(msg.result);
397
+ }
398
+ }
399
+ /** Send a JSON-RPC method to the VM service and await the response. */
400
+ rpc(method, params, timeoutMs) {
401
+ const ws = this.ws;
402
+ if (!ws || ws.readyState !== ws_1.default.OPEN) {
403
+ return Promise.reject(new Error('VM service WebSocket is not open'));
404
+ }
405
+ const id = this.nextRpcId++;
406
+ const t = timeoutMs ?? this.cfg.defaultTimeoutMs ?? 10_000;
407
+ return new Promise((resolve, reject) => {
408
+ const timer = setTimeout(() => {
409
+ this.pending.delete(id);
410
+ reject(new Error(`RPC ${method} timed out after ${t}ms`));
411
+ }, t);
412
+ this.pending.set(id, { resolve, reject, timer });
413
+ ws.send(JSON.stringify({ jsonrpc: '2.0', id, method, params }));
414
+ });
415
+ }
416
+ /** Send an `ext.flutter.driver` command on the resolved isolate. */
417
+ async driverCommand(command, timeoutMs) {
418
+ if (!this.isolateId)
419
+ throw new Error('FlutterDesktopDriver not initialized');
420
+ const result = await this.rpc('ext.flutter.driver', { isolateId: this.isolateId, ...command }, timeoutMs);
421
+ if (result?.isError) {
422
+ throw new Error(`flutter_driver command failed: ${JSON.stringify(result.response ?? result)}`);
423
+ }
424
+ // The ext.flutter.driver result wraps the actual payload in `response`
425
+ return result?.response ?? result;
426
+ }
427
+ async resolveIsolateAndDriverExtension(timeoutMs) {
428
+ const deadline = Date.now() + timeoutMs;
429
+ while (Date.now() < deadline) {
430
+ const vm = await this.rpc('getVM', {});
431
+ const first = vm.isolates?.[0];
432
+ if (first) {
433
+ const isolate = await this.rpc('getIsolate', { isolateId: first.id });
434
+ if (isolate.extensionRPCs?.includes('ext.flutter.driver')) {
435
+ this.isolateId = first.id;
436
+ return;
437
+ }
438
+ }
439
+ await new Promise((r) => setTimeout(r, 200));
440
+ }
441
+ throw new Error(`Timed out waiting for ext.flutter.driver extension. Did the app call enableFlutterDriverExtension()?`);
442
+ }
443
+ }
444
+ exports.FlutterDesktopDriver = FlutterDesktopDriver;
445
+ //# sourceMappingURL=FlutterDesktopDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlutterDesktopDriver.js","sourceRoot":"","sources":["../../../src/drivers/FlutterDesktopDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { EnvironmentConfig } from '../../config/types';
2
+ export interface MaestroRunOptions {
3
+ env?: Record<string, string>;
4
+ timeoutMs?: number;
5
+ reinstallDriver?: boolean;
6
+ }
7
+ export interface MaestroResult {
8
+ success: boolean;
9
+ output: string;
10
+ exitCode: number;
11
+ }
12
+ export declare class MaestroDriver {
13
+ private config;
14
+ constructor(config: EnvironmentConfig);
15
+ run(flowName: string, opts?: MaestroRunOptions): Promise<MaestroResult>;
16
+ runOrThrow(flowName: string, opts?: MaestroRunOptions): Promise<MaestroResult>;
17
+ takeScreenshot(name: string): Promise<string>;
18
+ }
19
+ //# sourceMappingURL=MaestroDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaestroDriver.d.ts","sourceRoot":"","sources":["../../../src/drivers/MaestroDriver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,iBAAiB;IAEvC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAuDvE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe9E,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBpD"}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MaestroDriver = void 0;
37
+ const child_process_1 = require("child_process");
38
+ const path = __importStar(require("path"));
39
+ class MaestroDriver {
40
+ config;
41
+ constructor(config) {
42
+ this.config = config;
43
+ }
44
+ async run(flowName, opts) {
45
+ const flowPath = path.resolve(this.config.mobile.flowsDir, `${flowName}.yaml`);
46
+ const timeoutMs = opts?.timeoutMs ?? this.config.mobile.timeoutMs;
47
+ const maestroBin = this.config.mobile.maestroBin ?? 'maestro';
48
+ const stream = process.env.DEBUG_MAESTRO !== '0' && process.env.DEBUG_MAESTRO !== 'false';
49
+ const args = ['test', flowPath];
50
+ if (opts?.reinstallDriver)
51
+ args.push('--reinstall-driver');
52
+ if (this.config.mobile.deviceId)
53
+ args.unshift('--device', this.config.mobile.deviceId);
54
+ if (opts?.env) {
55
+ for (const [k, v] of Object.entries(opts.env))
56
+ args.push('--env', `${k}=${v}`);
57
+ }
58
+ if (stream) {
59
+ const envSummary = opts?.env ? ' ' + Object.entries(opts.env).map(([k, v]) => `${k}=${v}`).join(' ') : '';
60
+ process.stderr.write(`\n[maestro] ▶ ${flowName}${envSummary}\n`);
61
+ }
62
+ return new Promise((resolve) => {
63
+ let output = '';
64
+ let buffer = '';
65
+ const proc = (0, child_process_1.spawn)(maestroBin, args, { env: process.env });
66
+ const onData = (chunk) => {
67
+ const text = chunk.toString();
68
+ output += text;
69
+ if (!stream)
70
+ return;
71
+ buffer += text;
72
+ const lines = buffer.split('\n');
73
+ buffer = lines.pop() ?? '';
74
+ for (const line of lines) {
75
+ if (line.trim())
76
+ process.stderr.write(`[maestro] ${line}\n`);
77
+ }
78
+ };
79
+ proc.stdout.on('data', onData);
80
+ proc.stderr.on('data', onData);
81
+ const timer = setTimeout(() => {
82
+ proc.kill('SIGTERM');
83
+ setTimeout(() => { try {
84
+ proc.kill('SIGKILL');
85
+ }
86
+ catch { } }, 2000);
87
+ if (stream)
88
+ process.stderr.write(`[maestro] ✖ ${flowName} — timeout after ${timeoutMs}ms\n`);
89
+ resolve({ success: false, output: output + '\nTimeout exceeded', exitCode: -1 });
90
+ }, timeoutMs);
91
+ proc.on('close', (code) => {
92
+ clearTimeout(timer);
93
+ if (stream && buffer.trim())
94
+ process.stderr.write(`[maestro] ${buffer}\n`);
95
+ const exitCode = code ?? -1;
96
+ const failed = exitCode !== 0 || output.includes('Flow Failed');
97
+ if (stream)
98
+ process.stderr.write(`[maestro] ${failed ? '✖' : '✔'} ${flowName} (exit=${exitCode})\n`);
99
+ resolve({ success: !failed, output, exitCode });
100
+ });
101
+ });
102
+ }
103
+ async runOrThrow(flowName, opts) {
104
+ const result = await this.run(flowName, opts);
105
+ if (!result.success) {
106
+ // Only retry with --reinstall-driver on real on-device gRPC crashes, NOT on our own timeout
107
+ const driverCrashed = /io\.grpc\.StatusRuntimeException: UNAVAILABLE|Command failed \(tcp:\d+\): closed/.test(result.output);
108
+ if (driverCrashed && !opts?.reinstallDriver) {
109
+ process.stderr.write(`[maestro] ⚠ device driver crashed — retrying with --reinstall-driver\n`);
110
+ const retry = await this.run(flowName, { ...opts, reinstallDriver: true });
111
+ if (retry.success)
112
+ return retry;
113
+ }
114
+ throw new Error(`Maestro flow "${flowName}" failed:\n${result.output}`);
115
+ }
116
+ return result;
117
+ }
118
+ async takeScreenshot(name) {
119
+ const outputDir = 'reports/screenshots';
120
+ const screenshotPath = path.resolve(outputDir, `${name}.png`);
121
+ const deviceArgs = this.config.mobile.deviceId ? ['-s', this.config.mobile.deviceId] : [];
122
+ const adb = process.env.ANDROID_HOME
123
+ ? path.join(process.env.ANDROID_HOME, 'platform-tools', 'adb')
124
+ : 'adb';
125
+ return new Promise((resolve, reject) => {
126
+ const proc = (0, child_process_1.spawn)(adb, [...deviceArgs, 'exec-out', 'screencap', '-p'], { env: process.env });
127
+ const chunks = [];
128
+ proc.stdout.on('data', (chunk) => chunks.push(chunk));
129
+ proc.on('close', (code) => {
130
+ if (code === 0 && chunks.length > 0) {
131
+ const fs = require('fs');
132
+ fs.mkdirSync(outputDir, { recursive: true });
133
+ fs.writeFileSync(screenshotPath, Buffer.concat(chunks));
134
+ resolve(screenshotPath);
135
+ }
136
+ else {
137
+ reject(new Error(`adb screencap failed with code ${code}`));
138
+ }
139
+ });
140
+ });
141
+ }
142
+ }
143
+ exports.MaestroDriver = MaestroDriver;
144
+ //# sourceMappingURL=MaestroDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaestroDriver.js","sourceRoot":"","sources":["../../../src/drivers/MaestroDriver.ts"],"names":[],"mappings":"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"}