UNPKG

appium-flutter-driver

Version:
160 lines 7.51 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OBSERVATORY_URL_PATTERN = void 0; exports.connectSocket = connectSocket; exports.executeGetIsolateCommand = executeGetIsolateCommand; exports.executeGetVMCommand = executeGetVMCommand; exports.executeElementCommand = executeElementCommand; exports.extractObservatoryUrl = extractObservatoryUrl; const node_url_1 = require("node:url"); const lodash_1 = __importDefault(require("lodash")); const isolate_socket_1 = require("./isolate_socket"); const base64url_1 = require("./base64url"); const asyncbox_1 = require("asyncbox"); const truncateLength = 500; // https://github.com/flutter/flutter/blob/f90b019c68edf4541a4c8273865a2b40c2c01eb3/dev/devicelab/lib/framework/runner.dart#L183 // e.g. 'Observatory listening on http://127.0.0.1:52817/_w_SwaKs9-g=/' // https://github.com/flutter/flutter/blob/52ae102f182afaa0524d0d01d21b2d86d15a11dc/packages/flutter_tools/lib/src/resident_runner.dart#L1386-L1389 // e.g. 'An Observatory debugger and profiler on ${device.device.name} is available at: http://127.0.0.1:52817/_w_SwaKs9-g=/' exports.OBSERVATORY_URL_PATTERN = new RegExp(`(Observatory listening on |` + `An Observatory debugger and profiler on\\s.+\\sis available at: |` + `The Dart VM service is listening on )` + `((http|//)[a-zA-Z0-9:/=_\\-.\\[\\]]+)`); const moduleCheckIntervalCount = 30; const moduleCheckIntervalMs = 500; // SOCKETS async function connectSocket(dartObservatoryURL, caps) { const isolateId = caps.isolateId; this.log.debug(`Establishing a connection to the Dart Observatory`); const connectedPromise = new Promise((resolve) => { const socket = new isolate_socket_1.IsolateSocket(dartObservatoryURL); const removeListenerAndResolve = (r) => { socket.removeListener(`error`, onErrorListener); socket.removeListener(`timeout`, onTimeoutListener); socket.removeListener(`open`, onOpenListener); resolve(r); }; // Add an 'error' event handler for the client socket const onErrorListener = (ex) => { this.log.error(`Connection to ${dartObservatoryURL} got an error: ${ex.message}`); removeListenerAndResolve(null); }; socket.on(`error`, onErrorListener); // Add a 'close' event handler for the client socket socket.on(`close`, () => { this.log.info(`Connection to ${dartObservatoryURL} closed`); // @todo do we need to set this.socket = null? }); // Add a 'timeout' event handler for the client socket const onTimeoutListener = () => { this.log.error(`Connection to ${dartObservatoryURL} timed out`); removeListenerAndResolve(null); }; socket.on(`timeout`, onTimeoutListener); const onOpenListener = async () => { const originalSocketCall = socket.call; socket.call = async (...args) => { try { // `await` is needed so that rejected promise will be thrown and caught return await originalSocketCall.apply(socket, args); } catch (e) { this.log.errorWithException(new Error(JSON.stringify(e))); } }; this.log.info(`Connecting to Dart Observatory: ${dartObservatoryURL}`); if (isolateId) { this.log.info(`Listing the given isolate id: ${isolateId}`); socket.isolateId = isolateId; } else { const vm = (await socket.call(`getVM`)); this.log.info(`Listing all isolates: ${JSON.stringify(vm.isolates)}`); // To accept 'main.dart:main()' and 'main' const mainIsolateData = vm.isolates.find((e) => e.name.includes(`main`)); if (!mainIsolateData) { this.log.error(`Cannot get Dart main isolate info`); removeListenerAndResolve(null); socket.close(); return; } // e.g. 'isolates/2978358234363215', '2978358234363215' socket.isolateId = mainIsolateData.id; } // It could take time to load the expected module. try { await (0, asyncbox_1.retryInterval)(moduleCheckIntervalCount, moduleCheckIntervalMs, async () => { const isolate = (await socket.call(`getIsolate`, { isolateId: `${socket.isolateId}`, })); if (!isolate) { throw new Error(`Cannot get main Dart Isolate`); } if (!Array.isArray(isolate.extensionRPCs)) { throw new Error(`Cannot get Dart extensionRPCs from isolate ${JSON.stringify(isolate)}`); } if (isolate.extensionRPCs.indexOf(`ext.flutter.driver`) < 0) { throw new Error(`"ext.flutter.driver" is not found in "extensionRPCs" ${JSON.stringify(isolate.extensionRPCs)}`); } }); } catch (e) { this.log.error(e.message); removeListenerAndResolve(null); return; } removeListenerAndResolve(socket); }; socket.on(`open`, onOpenListener); }); const connectedSocket = await connectedPromise; if (connectedSocket) { return connectedSocket; } throw new Error(`Cannot connect to the Dart Observatory URL ${dartObservatoryURL}. ` + `Check the server log for more details`); } async function executeGetIsolateCommand(isolateId) { this.log.debug(`>>> getIsolate`); const isolate = await this.socket.call(`getIsolate`, { isolateId: `${isolateId}`, }); this.log.debug(`<<< ${lodash_1.default.truncate(JSON.stringify(isolate), { length: truncateLength })}`); return isolate; } async function executeGetVMCommand() { this.log.debug(`>>> getVM`); const vm = (await this.socket.call(`getVM`)); this.log.debug(`<<< ${lodash_1.default.truncate(JSON.stringify(vm), { length: truncateLength })}`); return vm; } async function executeElementCommand(command, elementBase64, extraArgs = {}) { const elementObject = elementBase64 ? JSON.parse((0, base64url_1.decode)(elementBase64)) : {}; const serializedCommand = { command, ...elementObject, ...extraArgs }; this.log.debug(`>>> ${JSON.stringify(serializedCommand)}`); const data = await this.socket.executeSocketCommand(serializedCommand); this.log.debug(`<<< ${JSON.stringify(data)} | previous command ${command}`); if (data.isError) { throw new Error(`Cannot execute command ${command}, server response ${JSON.stringify(data, null, 2)}`); } return data.response; } function extractObservatoryUrl(logEntry) { const match = logEntry.message.match(exports.OBSERVATORY_URL_PATTERN); if (!match) { return null; } try { const result = new node_url_1.URL(match[2]); result.protocol = `ws`; result.pathname += `ws`; return result; } catch { return null; } } //# sourceMappingURL=observatory.js.map