appium-flutter-driver
Version:
198 lines (174 loc) • 6.97 kB
text/typescript
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { FlutterDriver } from '../driver';
import { reConnectFlutterDriver } from '../sessions/session';
import { longTap, scroll, scrollIntoView, scrollUntilVisible, scrollUntilTapable } from './execute/scroll';
import { waitFor, waitForAbsent, waitForTappable } from './execute/wait';
import { launchApp } from './../ios/app';
import B from 'bluebird';
const flutterCommandRegex = /^[\s]*flutter[\s]*:(.+)/;
export const execute = async function(
this: FlutterDriver,
rawCommand: string,
args: any[],
) {
// flutter
const matching = rawCommand.match(flutterCommandRegex);
if (!matching) {
throw new Error(`Command not support: "${rawCommand}"`);
}
const command = matching[1].trim();
switch (command) {
case `launchApp`:
return await flutterLaunchApp(this, args[0], args[1]);
case `connectObservatoryWsUrl`:
return await connectObservatoryWsUrl(this);
case `getVMInfo`:
return await getVMInfo(this);
case `setIsolateId`:
return await setIsolateId(this, args[0]);
case `getIsolate`:
return await getIsolate(this, args[0]);
case `checkHealth`:
return await checkHealth(this);
case `clearTimeline`:
return await clearTimeline(this);
case `forceGC`:
return await forceGC(this);
case `getRenderTree`:
return await getRenderTree(this);
case `getBottomLeft`:
return await getOffset(this, args[0], { offsetType: `bottomLeft` });
case `getBottomRight`:
return await getOffset(this, args[0], { offsetType: `bottomRight` });
case `getCenter`:
return await getOffset(this, args[0], { offsetType: `center` });
case `getTopLeft`:
return await getOffset(this, args[0], { offsetType: `topLeft` });
case `getTopRight`:
return await getOffset(this, args[0], { offsetType: `topRight` });
case `getRenderObjectDiagnostics`:
return await getRenderObjectDiagnostics(this, args[0], args[1]);
case `getSemanticsId`:
return await getSemanticsId(this, args[0]);
case `waitForAbsent`:
return await waitForAbsent(this, args[0], args[1]);
case `waitFor`:
return await waitFor(this, args[0], args[1]);
case `waitForTappable`:
return await waitForTappable(this, args[0], args[1]);
case `scroll`:
return await scroll(this, args[0], args[1]);
case `scrollUntilVisible`:
return await scrollUntilVisible(this, args[0], args[1]);
case `scrollUntilTapable`:
return await scrollUntilTapable(this, args[0], args[1]);
case `scrollIntoView`:
return await scrollIntoView(this, args[0], args[1]);
case `setTextEntryEmulation`:
return await setTextEntryEmulation(this, args[0]);
case `enterText`:
return await enterText(this, args[0]);
case `requestData`:
return await requestData(this, args[0]);
case `longTap`:
return await longTap(this, args[0], args[1]);
case `waitForFirstFrame`:
return await waitForCondition(this, { conditionName: `FirstFrameRasterizedCondition`});
case `setFrameSync`:
return await setFrameSync(this, args[0], args[1]);
case `clickElement`:
return await clickElement(this, args[0], args[1]);
default:
throw new Error(`Command not support: "${rawCommand}"`);
}
};
const flutterLaunchApp = async (
self: FlutterDriver, appId: string, opts
) => {
const { arguments: args = [], environment: env = {}} = opts;
await launchApp(self.internalCaps.udid!, appId, args, env);
await reConnectFlutterDriver.bind(self)(self.internalCaps);
};
const connectObservatoryWsUrl = async (self: FlutterDriver) => {
await reConnectFlutterDriver.bind(self)(self.internalCaps);
};
const checkHealth = async (self: FlutterDriver) =>
(await self.executeElementCommand(`get_health`)).status;
const getVMInfo = async (self: FlutterDriver) =>
(await self.executeGetVMCommand());
const getRenderTree = async (self: FlutterDriver) =>
(await self.executeElementCommand(`get_render_tree`)).tree;
const getOffset = async (
self: FlutterDriver,
elementBase64: string,
offsetType: {offsetType: string},
) => await self.executeElementCommand(`get_offset`, elementBase64, offsetType);
const waitForCondition = async (
self: FlutterDriver,
conditionName: {conditionName: string},
) => await self.executeElementCommand(`waitForCondition`, ``, conditionName);
const forceGC = async (self: FlutterDriver) => {
const response = await self.socket!.call(`_collectAllGarbage`, {
isolateId: self.socket!.isolateId,
}) as { type: string };
if (response.type !== `Success`) {
throw new Error(`Could not forceGC, response was ${response}`);
}
};
const setIsolateId = async (self: FlutterDriver, isolateId: string) => {
self.socket!.isolateId = isolateId;
return await self.socket!.call(`getIsolate`, {
isolateId: `${isolateId}`,
});
};
const getIsolate = async (
self: FlutterDriver, isolateId: string|undefined
) => await self.executeGetIsolateCommand(isolateId || self.socket!.isolateId);
const clearTimeline = async (self: FlutterDriver) => {
// @todo backward compatible, need to cleanup later
const call1: Promise<any> = self.socket!.call(`_clearVMTimeline`);
const call2: Promise<any> = self.socket!.call(`clearVMTimeline`);
const response = await B.any([call1, call2]);
if (response.type !== `Success`) {
throw new Error(`Could not forceGC, response was ${response}`);
}
};
const getRenderObjectDiagnostics = async (
self: FlutterDriver,
elementBase64: string,
opts: {
subtreeDepth: number;
includeProperties: boolean;
},
) => {
const { subtreeDepth = 0, includeProperties = true } = opts;
return await self.executeElementCommand(
`get_diagnostics_tree`,
elementBase64,
{
diagnosticsType: `renderObject`,
includeProperties,
subtreeDepth,
},
);
};
const getSemanticsId = async (self: FlutterDriver, elementBase64: string) =>
(await self.executeElementCommand(`get_semantics_id`, elementBase64)).id;
const enterText = async (self: FlutterDriver, text: string) =>
await self.socket!.executeSocketCommand({ command: `enter_text`, text });
const requestData = async (self: FlutterDriver, message: string) =>
await self.socket!.executeSocketCommand({ command: `request_data`, message });
const setFrameSync = async (self, bool: boolean, durationMilliseconds: number) =>
await self.socket!.executeSocketCommand({
command: `set_frame_sync`,
enabled: bool,
timeout: durationMilliseconds,
});
const setTextEntryEmulation = async (self: FlutterDriver, enabled: boolean) =>
await self.socket!.executeSocketCommand({ command: `set_text_entry_emulation`, enabled });
const clickElement = async (self:FlutterDriver, elementBase64: string, opts) => {
const {timeout = 1000} = opts;
return await self.executeElementCommand(`tap`, elementBase64, {
timeout
});
};