@nouhouari/conductor-e2e 0.0.0-stage → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +237 -0
- package/LICENSE +21 -0
- package/README.md +196 -2
- package/config/environments/default.ts +41 -0
- package/config/environments/dev.ts +16 -0
- package/config/environments/staging.ts +15 -0
- package/config/index.ts +70 -0
- package/config/types.ts +94 -0
- package/dist/config/environments/default.d.ts +3 -0
- package/dist/config/environments/default.d.ts.map +1 -0
- package/dist/config/environments/default.js +40 -0
- package/dist/config/environments/default.js.map +1 -0
- package/dist/config/environments/dev.d.ts +3 -0
- package/dist/config/environments/dev.d.ts.map +1 -0
- package/dist/config/environments/dev.js +18 -0
- package/dist/config/environments/dev.js.map +1 -0
- package/dist/config/environments/staging.d.ts +3 -0
- package/dist/config/environments/staging.d.ts.map +1 -0
- package/dist/config/environments/staging.js +17 -0
- package/dist/config/environments/staging.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +81 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +93 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +3 -0
- package/dist/config/types.js.map +1 -0
- package/dist/src/drivers/ApiDriver.d.ts +16 -0
- package/dist/src/drivers/ApiDriver.d.ts.map +1 -0
- package/dist/src/drivers/ApiDriver.js +48 -0
- package/dist/src/drivers/ApiDriver.js.map +1 -0
- package/dist/src/drivers/DatabaseDriver.d.ts +12 -0
- package/dist/src/drivers/DatabaseDriver.d.ts.map +1 -0
- package/dist/src/drivers/DatabaseDriver.js +15 -0
- package/dist/src/drivers/DatabaseDriver.js.map +1 -0
- package/dist/src/drivers/FlutterDesktopDriver.d.ts +139 -0
- package/dist/src/drivers/FlutterDesktopDriver.d.ts.map +1 -0
- package/dist/src/drivers/FlutterDesktopDriver.js +445 -0
- package/dist/src/drivers/FlutterDesktopDriver.js.map +1 -0
- package/dist/src/drivers/MaestroDriver.d.ts +19 -0
- package/dist/src/drivers/MaestroDriver.d.ts.map +1 -0
- package/dist/src/drivers/MaestroDriver.js +144 -0
- package/dist/src/drivers/MaestroDriver.js.map +1 -0
- package/dist/src/drivers/WebDriver.d.ts +21 -0
- package/dist/src/drivers/WebDriver.d.ts.map +1 -0
- package/dist/src/drivers/WebDriver.js +57 -0
- package/dist/src/drivers/WebDriver.js.map +1 -0
- package/dist/src/hooks/browser.hooks.d.ts +2 -0
- package/dist/src/hooks/browser.hooks.d.ts.map +1 -0
- package/dist/src/hooks/browser.hooks.js +15 -0
- package/dist/src/hooks/browser.hooks.js.map +1 -0
- package/dist/src/hooks/database.hooks.d.ts +2 -0
- package/dist/src/hooks/database.hooks.d.ts.map +1 -0
- package/dist/src/hooks/database.hooks.js +11 -0
- package/dist/src/hooks/database.hooks.js.map +1 -0
- package/dist/src/hooks/desktop.hooks.d.ts +2 -0
- package/dist/src/hooks/desktop.hooks.d.ts.map +1 -0
- package/dist/src/hooks/desktop.hooks.js +15 -0
- package/dist/src/hooks/desktop.hooks.js.map +1 -0
- package/dist/src/hooks/flutterDesktop.hooks.d.ts +2 -0
- package/dist/src/hooks/flutterDesktop.hooks.d.ts.map +1 -0
- package/dist/src/hooks/flutterDesktop.hooks.js +26 -0
- package/dist/src/hooks/flutterDesktop.hooks.js.map +1 -0
- package/dist/src/hooks/index.d.ts +6 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +25 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/maestro.hooks.d.ts +2 -0
- package/dist/src/hooks/maestro.hooks.d.ts.map +1 -0
- package/dist/src/hooks/maestro.hooks.js +8 -0
- package/dist/src/hooks/maestro.hooks.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +30 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/pages/BasePage.d.ts +11 -0
- package/dist/src/pages/BasePage.d.ts.map +1 -0
- package/dist/src/pages/BasePage.js +22 -0
- package/dist/src/pages/BasePage.js.map +1 -0
- package/dist/src/scenarios/RemoteScenarioFetcher.d.ts +51 -0
- package/dist/src/scenarios/RemoteScenarioFetcher.d.ts.map +1 -0
- package/dist/src/scenarios/RemoteScenarioFetcher.js +162 -0
- package/dist/src/scenarios/RemoteScenarioFetcher.js.map +1 -0
- package/dist/src/scenarios/cli.d.ts +3 -0
- package/dist/src/scenarios/cli.d.ts.map +1 -0
- package/dist/src/scenarios/cli.js +26 -0
- package/dist/src/scenarios/cli.js.map +1 -0
- package/dist/src/support/logger.d.ts +3 -0
- package/dist/src/support/logger.d.ts.map +1 -0
- package/dist/src/support/logger.js +16 -0
- package/dist/src/support/logger.js.map +1 -0
- package/dist/src/support/retry.d.ts +7 -0
- package/dist/src/support/retry.d.ts.map +1 -0
- package/dist/src/support/retry.js +21 -0
- package/dist/src/support/retry.js.map +1 -0
- package/dist/src/world/ConductorWorld.d.ts +39 -0
- package/dist/src/world/ConductorWorld.d.ts.map +1 -0
- package/dist/src/world/ConductorWorld.js +112 -0
- package/dist/src/world/ConductorWorld.js.map +1 -0
- package/package.json +81 -4
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { EnvironmentConfig } from '../../config/types';
|
|
2
|
+
/**
|
|
3
|
+
* FlutterDesktopDriver
|
|
4
|
+
*
|
|
5
|
+
* Drives a Flutter desktop app (built with `lib/main_test.dart` calling
|
|
6
|
+
* `enableFlutterDriverExtension()`) by:
|
|
7
|
+
* 1. Spawning the executable.
|
|
8
|
+
* 2. Reading the Dart VM service URL printed on stdout.
|
|
9
|
+
* 3. Opening a WebSocket to the VM service.
|
|
10
|
+
* 4. Calling the `ext.flutter.driver` service extension via JSON-RPC.
|
|
11
|
+
*
|
|
12
|
+
* No Dart side process is involved — this is a pure TypeScript client.
|
|
13
|
+
*/
|
|
14
|
+
export type FinderType = 'ByValueKey' | 'ByText' | 'ByType' | 'ByTooltipMessage';
|
|
15
|
+
export interface Finder {
|
|
16
|
+
type: FinderType;
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
export type OffsetType = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'center';
|
|
20
|
+
export interface Offset {
|
|
21
|
+
dx: number;
|
|
22
|
+
dy: number;
|
|
23
|
+
}
|
|
24
|
+
export type WaitCondition = 'NoPendingFrames' | 'NoTransientCallbacks' | 'FirstFrameRasterized';
|
|
25
|
+
export declare class FlutterDesktopDriver {
|
|
26
|
+
private readonly cfg;
|
|
27
|
+
private proc;
|
|
28
|
+
private ws;
|
|
29
|
+
private isolateId;
|
|
30
|
+
private nextRpcId;
|
|
31
|
+
private pending;
|
|
32
|
+
private textEntryEmulationEnabled;
|
|
33
|
+
constructor(env: EnvironmentConfig);
|
|
34
|
+
get isLaunched(): boolean;
|
|
35
|
+
launch(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Connect to an already-running Flutter app via its Dart VM service URL.
|
|
38
|
+
* Use instead of `launch()` when the app is already running — e.g.:
|
|
39
|
+
* - **Android**: `adb forward tcp:PORT tcp:PORT`, then connect to `ws://localhost:PORT/TOKEN/ws`
|
|
40
|
+
* - **iOS**: `iproxy PORT PORT DEVICE_UDID`, then connect
|
|
41
|
+
* - **Windows / Linux desktop**: manage the process yourself and pass the URL
|
|
42
|
+
*
|
|
43
|
+
* Accepts either the HTTP form printed by the app (`http://localhost:PORT/TOKEN/`)
|
|
44
|
+
* or the WebSocket form directly (`ws://localhost:PORT/TOKEN/ws`).
|
|
45
|
+
*/
|
|
46
|
+
connect(vmServiceUrl: string, timeoutMs?: number): Promise<void>;
|
|
47
|
+
close(): Promise<void>;
|
|
48
|
+
/** Tap a widget identified by `finder`. */
|
|
49
|
+
tap(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
50
|
+
/** Type `text` into the currently focused text field.
|
|
51
|
+
* Emulation must be enabled BEFORE tapping so that `TextInput.setClient`
|
|
52
|
+
* is captured by the mock — otherwise the mock's _client stays null and
|
|
53
|
+
* enter_text is silently ignored. */
|
|
54
|
+
enterText(finder: Finder, text: string, timeoutMs?: number): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Send a message to the app's `enableFlutterDriverExtension` data handler
|
|
57
|
+
* and return the response string. Use this to invoke app-side actions that
|
|
58
|
+
* cannot be driven through the gesture system (e.g. tapping widgets inside
|
|
59
|
+
* a scrollable that blocks flutter_driver's hitTestable() check).
|
|
60
|
+
*/
|
|
61
|
+
requestData(message: string, timeoutMs?: number): Promise<string>;
|
|
62
|
+
/** Read the text of a Text widget at `finder`. */
|
|
63
|
+
getText(finder: Finder, timeoutMs?: number): Promise<string>;
|
|
64
|
+
/** Wait for `finder` to resolve to an existing widget. */
|
|
65
|
+
waitFor(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
66
|
+
/** Wait until `finder` no longer resolves to any widget. */
|
|
67
|
+
waitForAbsent(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Take a screenshot of the Flutter app's render surface via the
|
|
70
|
+
* `ext.flutter.driver` `screenshot` command. Returns a PNG path.
|
|
71
|
+
*
|
|
72
|
+
* This goes over the same WebSocket as the rest of the driver — no OS-level
|
|
73
|
+
* screen-recording permissions are required, and only the app surface is
|
|
74
|
+
* captured (not the whole desktop).
|
|
75
|
+
*/
|
|
76
|
+
takeScreenshot(name: string): Promise<string>;
|
|
77
|
+
/** Double-tap a widget identified by `finder`. */
|
|
78
|
+
doubleTap(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
79
|
+
/** Long-press a widget identified by `finder`. */
|
|
80
|
+
longPress(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Scroll a Scrollable widget identified by `finder` by (`dx`, `dy`) pixels
|
|
83
|
+
* over `durationMs` milliseconds at `frequency` Hz.
|
|
84
|
+
*/
|
|
85
|
+
scroll(finder: Finder, dx: number, dy: number, durationMs?: number, frequency?: number, timeoutMs?: number): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Scroll until `finder` is visible.
|
|
88
|
+
* `alignment` controls where the widget lands: 0.0 = top edge, 0.5 = center, 1.0 = bottom edge.
|
|
89
|
+
*/
|
|
90
|
+
scrollIntoView(finder: Finder, alignment?: number, timeoutMs?: number): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Clear the text field at `finder` by enabling text-entry emulation,
|
|
93
|
+
* tapping to focus, then setting its value to an empty string.
|
|
94
|
+
*/
|
|
95
|
+
clearText(finder: Finder, timeoutMs?: number): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Non-throwing visibility probe: returns `true` if `finder` resolves within
|
|
98
|
+
* `timeoutMs` (default 500 ms), `false` otherwise. Use for conditional
|
|
99
|
+
* assertions instead of `waitFor` when absence is acceptable.
|
|
100
|
+
*/
|
|
101
|
+
isVisible(finder: Finder, timeoutMs?: number): Promise<boolean>;
|
|
102
|
+
/**
|
|
103
|
+
* Return the screen coordinates of a point on the widget at `finder`.
|
|
104
|
+
* `offsetType` defaults to `'center'`.
|
|
105
|
+
*/
|
|
106
|
+
getOffset(finder: Finder, offsetType?: OffsetType, timeoutMs?: number): Promise<Offset>;
|
|
107
|
+
/**
|
|
108
|
+
* Wait until a predefined Flutter condition is satisfied — the app-level
|
|
109
|
+
* equivalent of Playwright's `page.waitForLoadState()`.
|
|
110
|
+
*
|
|
111
|
+
* `'NoPendingFrames'` — no animation frames scheduled (app is idle)
|
|
112
|
+
* `'NoTransientCallbacks'` — no pending transient callbacks
|
|
113
|
+
* `'FirstFrameRasterized'` — first frame has been rendered
|
|
114
|
+
*/
|
|
115
|
+
waitForCondition(condition: WaitCondition, timeoutMs?: number): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Enable or disable Flutter's frame-sync during driver commands. Set to
|
|
118
|
+
* `false` before triggering heavy animations so the driver does not stall
|
|
119
|
+
* waiting for each frame to settle; restore with `setFrameSync(true)` when
|
|
120
|
+
* done. Mirrors disabling CSS transitions in web tests.
|
|
121
|
+
*/
|
|
122
|
+
setFrameSync(enabled: boolean, timeoutMs?: number): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* NOTE: `isEnabled` (checking whether a widget is interactive) is not part
|
|
125
|
+
* of the `ext.flutter.driver` protocol. Use `requestData()` with an app-side
|
|
126
|
+
* handler that inspects widget state and returns the result as a string.
|
|
127
|
+
*/
|
|
128
|
+
private serializeFinder;
|
|
129
|
+
/** Read stdout/stderr until we see a VM service URL or hit the timeout. */
|
|
130
|
+
private waitForVmServiceUrl;
|
|
131
|
+
private connectWebSocket;
|
|
132
|
+
private onMessage;
|
|
133
|
+
/** Send a JSON-RPC method to the VM service and await the response. */
|
|
134
|
+
private rpc;
|
|
135
|
+
/** Send an `ext.flutter.driver` command on the resolved isolate. */
|
|
136
|
+
private driverCommand;
|
|
137
|
+
private resolveIsolateAndDriverExtension;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=FlutterDesktopDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlutterDesktopDriver.d.ts","sourceRoot":"","sources":["../../../src/drivers/FlutterDesktopDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|