UNPKG

appium-flutter-driver

Version:
246 lines 10.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlutterDriver = void 0; // @ts-ignore: no 'errors' export module const lodash_1 = __importDefault(require("lodash")); const driver_1 = require("appium/driver"); const logger_1 = require("./logger"); const observatory_1 = require("./sessions/observatory"); const platform_1 = require("./platform"); const session_1 = require("./sessions/session"); const context_1 = require("./commands/context"); const element_1 = require("./commands/element"); const execute_1 = require("./commands/execute"); const gesture_1 = require("./commands/gesture"); const screen_1 = require("./commands/screen"); const clipboard_1 = require("./commands/clipboard"); const desired_caps_1 = require("./desired-caps"); const appium_xcuitest_driver_1 = require("appium-xcuitest-driver"); // Need to not proxy in WebView context const WEBVIEW_NO_PROXY = [ [`GET`, new RegExp(`^/session/[^/]+/appium`)], [`GET`, new RegExp(`^/session/[^/]+/context`)], [`GET`, new RegExp(`^/session/[^/]+/element/[^/]+/rect`)], [`GET`, new RegExp(`^/session/[^/]+/log/types$`)], [`GET`, new RegExp(`^/session/[^/]+/orientation`)], [`POST`, new RegExp(`^/session/[^/]+/appium`)], [`POST`, new RegExp(`^/session/[^/]+/context`)], [`POST`, new RegExp(`^/session/[^/]+/log$`)], [`POST`, new RegExp(`^/session/[^/]+/orientation`)], [`POST`, new RegExp(`^/session/[^/]+/touch/multi/perform`)], [`POST`, new RegExp(`^/session/[^/]+/touch/perform`)], ]; class FlutterDriver extends driver_1.BaseDriver { socket; locatorStrategies = [`key`, `css selector`]; proxydriver; device; portForwardLocalPort; localServer; _logmon; // Used to keep the capabilities internally internalCaps; receiveAsyncResponse; // to handle WebView context proxyWebViewActive = false; // session executeElementCommand = observatory_1.executeElementCommand; executeGetVMCommand = observatory_1.executeGetVMCommand; executeGetIsolateCommand = observatory_1.executeGetIsolateCommand; execute = execute_1.execute; executeAsync = execute_1.execute; // element getText = element_1.getText; setValue = element_1.setValue; clear = element_1.clear; getScreenshot = screen_1.getScreenshot; // gesture click = gesture_1.click; longTap = gesture_1.longTap; tapEl = gesture_1.tapEl; tap = gesture_1.tap; performTouch = gesture_1.performTouch; // context getContexts = context_1.getContexts; getCurrentContext = context_1.getCurrentContext; setContext = context_1.setContext; currentContext = context_1.FLUTTER_CONTEXT_NAME; driverShouldDoProxyCmd = context_1.driverShouldDoProxyCmd; // content getClipboard = clipboard_1.getClipboard; setClipboard = clipboard_1.setClipboard; constructor(opts, shouldValidateCaps) { super(opts, shouldValidateCaps); this.socket = null; this.device = null; this._logmon = null; this.desiredCapConstraints = desired_caps_1.desiredCapConstraints; // Used to keep the port for port forward to clear the pair. this.portForwardLocalPort = null; // Used for iOS to end the local server to proxy the request. this.localServer = null; } async createSession(...args) { const [sessionId, caps] = await super.createSession(...JSON.parse(JSON.stringify(args))); this.internalCaps = caps; return session_1.createSession.bind(this)(sessionId, caps, ...JSON.parse(JSON.stringify(args))); } async deleteSession() { this.log.info(`Deleting Flutter Driver session`); this._logmon?.stop(); this._logmon = null; this.proxydriver?.eventEmitter?.removeAllListeners('syslogStarted'); this.log.info('Cleanup the port forward'); switch (lodash_1.default.toLower(this.internalCaps.platformName)) { case platform_1.PLATFORM.IOS: this.localServer?.close(); this.localServer = null; break; case platform_1.PLATFORM.ANDROID: if (this.portForwardLocalPort) { if (this.proxydriver) { await this.proxydriver.adb?.removePortForward(this.portForwardLocalPort); } } break; } if (this.proxydriver) { this.log.info('Deleting the proxy driver session.'); try { await this.proxydriver.deleteSession(this.sessionId || undefined); } catch (e) { this.log.warn(e.message); } this.proxydriver = null; } await super.deleteSession(); } async installApp(appPath, opts = {}) { // @ts-expect-error this exist in xcuitestdriver or uia2 driver this.proxydriver?.installApp(appPath, opts); } async activateApp(appId) { // @ts-expect-error this exist in xcuitestdriver or uia2 driver this.proxydriver?.activateApp(appId); await session_1.reConnectFlutterDriver.bind(this)(this.internalCaps); } async terminateApp(appId) { // @ts-expect-error this exist in xcuitestdriver or uia2 driver return await this.proxydriver?.terminateApp(appId); } async back() { // @ts-expect-error this exist in xcuitestdriver or uia2 driver return await this.proxydriver?.back(); } async getOrientation() { if (!this.proxydriver) { return null; } switch (lodash_1.default.toLower(this.internalCaps.platformName)) { case platform_1.PLATFORM.IOS: return await this.proxydriver.proxyCommand('/orientation', 'GET'); default: return await this.proxydriver.getOrientation(); } } async setOrientation(orientation) { switch (lodash_1.default.toLower(this.internalCaps.platformName)) { case platform_1.PLATFORM.IOS: return await this.proxydriver.proxyCommand('/orientation', 'POST', { orientation, }); default: return await this.proxydriver.setOrientation(orientation); } } validateLocatorStrategy(strategy) { // @todo refactor DRY if (this.currentContext === `NATIVE_APP`) { return this.proxydriver?.validateLocatorStrategy(strategy); } super.validateLocatorStrategy(strategy, false); } validateDesiredCaps(caps) { // check with the base class, and return if it fails const res = super.validateDesiredCaps(caps); if (!res) { return res; } // finally, return true since the superclass check passed, as did this return true; } async proxyCommand(url, method, body = null) { // @ts-expect-error this exist in xcuitestdriver or uia2 driver const result = await this.proxydriver?.proxyCommand(url, method, body); return result; } async executeCommand(cmd, ...args) { if (new RegExp(/^[\s]*mobile:[\s]*activateApp$/).test(args[0])) { const { skipAttachObservatoryUrl = false } = args[1][0]; await this.proxydriver?.executeCommand(cmd, ...args); if (skipAttachObservatoryUrl) { return; } await session_1.reConnectFlutterDriver.bind(this)(this.internalCaps); return; } else if (new RegExp(/^[\s]*mobile:[\s]*terminateApp$/).test(args[0])) { // to make the behavior as same as this.terminateApp return await this.proxydriver?.executeCommand(cmd, ...args); } else if (cmd === `receiveAsyncResponse`) { logger_1.log.debug(`Executing FlutterDriver response '${cmd}'`); return await this.receiveAsyncResponse(...args); } else if ([`setOrientation`, `getOrientation`, `back`].includes(cmd)) { // The `setOrientation` and `getOrientation` commands are handled differently // for iOS and Android platforms. These commands are deferred to the base driver's // implementation (`super.executeCommand`) to ensure compatibility with both platforms // and to leverage the platform-specific logic already implemented in the base driver. logger_1.log.debug(`Executing FlutterDriver command '${cmd}'`); return await super.executeCommand(cmd, ...args); } else { if (this.driverShouldDoProxyCmd(cmd)) { logger_1.log.debug(`Executing proxied driver command '${cmd}'`); // There are 2 CommandTimeout (FlutterDriver and proxy) // Only FlutterDriver CommandTimeout is used; Proxy is disabled // All proxy commands needs to reset the FlutterDriver CommandTimeout // Here we manually reset the FlutterDriver CommandTimeout for commands that goes to proxy. this.clearNewCommandTimeout(); const result = await this.proxydriver?.executeCommand(cmd, ...args); this.startNewCommandTimeout(); return result; } else { logger_1.log.debug(`Executing Flutter driver command '${cmd}'`); return await super.executeCommand(cmd, ...args); } } } getProxyAvoidList() { if ([context_1.FLUTTER_CONTEXT_NAME, context_1.NATIVE_CONTEXT_NAME].includes(this.currentContext)) { return []; } return WEBVIEW_NO_PROXY; } proxyActive() { // In WebView context, all request should got to each driver // so that they can handle http request properly. // On iOS, WebView context is handled by XCUITest driver while Android is by chromedriver. // It means XCUITest driver should keep the XCUITest driver as a proxy, // while UIAutomator2 driver should proxy to chromedriver instead of UIA2 proxy. return this.proxyWebViewActive && this.proxydriver?.constructor.name !== appium_xcuitest_driver_1.XCUITestDriver.name; } canProxy() { // As same as proxyActive, all request should got to each driver // so that they can handle http request properly return this.proxyWebViewActive; } } exports.FlutterDriver = FlutterDriver; //# sourceMappingURL=driver.js.map