feat(android): add androidDevice.options.omitDriverInstall (#13249)

This commit is contained in:
kaivean 2022-04-03 07:00:38 +08:00 committed by GitHub
parent bba36dcae4
commit 5d2e8918d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 11 deletions

View file

@ -87,6 +87,11 @@ Returns the list of detected Android devices.
Optional port to establish ADB server connection.
### option: Android.devices.omitDriverInstall
- `omitDriverInstall` <[boolean]>
Prevents automatic playwright driver installation on attach. Assumes that the drivers have been installed already.
## method: Android.setDefaultTimeout
This setting will change the default maximum time for all the methods accepting [`param: timeout`] option.

View file

@ -3682,9 +3682,11 @@ export interface AndroidChannel extends AndroidEventTarget, Channel {
}
export type AndroidDevicesParams = {
port?: number,
omitDriverInstall?: boolean,
};
export type AndroidDevicesOptions = {
port?: number,
omitDriverInstall?: boolean,
};
export type AndroidDevicesResult = {
devices: AndroidDeviceChannel[],

View file

@ -2846,6 +2846,7 @@ Android:
devices:
parameters:
port: number?
omitDriverInstall: boolean?
returns:
devices:
type: array

View file

@ -1304,6 +1304,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
scheme.ElectronApplicationCloseParams = tOptional(tObject({}));
scheme.AndroidDevicesParams = tObject({
port: tOptional(tNumber),
omitDriverInstall: tOptional(tBoolean),
});
scheme.AndroidSetDefaultTimeoutNoReplyParams = tObject({
timeout: tNumber,

View file

@ -80,7 +80,7 @@ export class Android extends SdkObject {
newSerials.add(d.serial);
if (this._devices.has(d.serial))
continue;
const device = await AndroidDevice.create(this, d);
const device = await AndroidDevice.create(this, d, options);
this._devices.set(d.serial, device);
}
for (const d of this._devices.keys()) {
@ -99,6 +99,7 @@ export class AndroidDevice extends SdkObject {
readonly _backend: DeviceBackend;
readonly model: string;
readonly serial: string;
private _options: types.AndroidDeviceOptions;
private _driverPromise: Promise<PipeTransport> | undefined;
private _lastId = 0;
private _callbacks = new Map<number, { fulfill: (result: any) => void, reject: (error: Error) => void }>();
@ -116,19 +117,20 @@ export class AndroidDevice extends SdkObject {
private _android: Android;
private _isClosed = false;
constructor(android: Android, backend: DeviceBackend, model: string) {
constructor(android: Android, backend: DeviceBackend, model: string, options: types.AndroidDeviceOptions) {
super(android, 'android-device');
this._android = android;
this._backend = backend;
this.model = model;
this.serial = backend.serial;
this._options = options;
this._timeoutSettings = new TimeoutSettings(android._timeoutSettings);
}
static async create(android: Android, backend: DeviceBackend): Promise<AndroidDevice> {
static async create(android: Android, backend: DeviceBackend, options: types.AndroidDeviceOptions): Promise<AndroidDevice> {
await backend.init();
const model = await backend.runCommand('shell:getprop ro.product.model');
const device = new AndroidDevice(android, backend, model.toString().trim());
const device = new AndroidDevice(android, backend, model.toString().trim(), options);
await device._init();
return device;
}
@ -169,13 +171,18 @@ export class AndroidDevice extends SdkObject {
debug('pw:android')('Stopping the old driver');
await this.shell(`am force-stop com.microsoft.playwright.androiddriver`);
debug('pw:android')('Uninstalling the old driver');
await this.shell(`cmd package uninstall com.microsoft.playwright.androiddriver`);
await this.shell(`cmd package uninstall com.microsoft.playwright.androiddriver.test`);
// uninstall and install driver on every excution
if (!this._options.omitDriverInstall) {
debug('pw:android')('Uninstalling the old driver');
await this.shell(`cmd package uninstall com.microsoft.playwright.androiddriver`);
await this.shell(`cmd package uninstall com.microsoft.playwright.androiddriver.test`);
debug('pw:android')('Installing the new driver');
for (const file of ['android-driver.apk', 'android-driver-target.apk'])
await this.installApk(await fs.promises.readFile(require.resolve(`../../../bin/${file}`)));
debug('pw:android')('Installing the new driver');
for (const file of ['android-driver.apk', 'android-driver-target.apk'])
await this.installApk(await fs.promises.readFile(require.resolve(`../../../bin/${file}`)));
} else {
debug('pw:android')('Skipping the driver installation');
}
debug('pw:android')('Starting the new driver');
this.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => debug('pw:android')(e));

View file

@ -369,5 +369,6 @@ export type APIResponse = {
};
export type AndroidDeviceOptions = {
port?: number
port?: number,
omitDriverInstall?: boolean,
};

View file

@ -11117,6 +11117,11 @@ export interface Android {
* @param options
*/
devices(options?: {
/**
* Prevents automatic playwright driver installation on attach. Assumes that the drivers have been installed already.
*/
omitDriverInstall?: boolean;
/**
* Optional port to establish ADB server connection.
*/

View file

@ -15,6 +15,7 @@
*/
import fs from 'fs';
import { join } from 'path';
import { PNG } from 'pngjs';
import { androidTest as test, expect } from './androidTest';
@ -57,3 +58,33 @@ test('androidDevice.fill', async function({ androidDevice }) {
await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello');
expect((await androidDevice.info({ res: 'org.chromium.webview_shell:id/url_field' })).text).toBe('Hello');
});
test('androidDevice.options.omitDriverInstall', async function({ playwright }) {
const devices = await playwright._android.devices({ omitDriverInstall: true });
const androidDevice = devices[0];
await androidDevice.shell(`cmd package uninstall com.microsoft.playwright.androiddriver`);
await androidDevice.shell(`cmd package uninstall com.microsoft.playwright.androiddriver.test`);
await androidDevice.shell('am start -n com.android.chrome/com.google.android.apps.chrome.Main about:blank');
let fillStatus = '';
androidDevice.fill({ res: 'com.android.chrome:id/url_bar' }, 'Hello').then(() => {
fillStatus = 'success';
}).catch(() => {
fillStatus = 'error';
});
// install and start driver
for (const file of ['android-driver.apk', 'android-driver-target.apk']) {
const filePath = join(require.resolve('playwright-core'), '..', 'bin', file);
await androidDevice.installApk(await fs.promises.readFile(filePath));
}
androidDevice.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => console.error);
// wait for finishing fill operation
while (!fillStatus)
await new Promise(f => setTimeout(f, 200));
expect(fillStatus).toBe('success');
});