feat(android): add androidDevice.options.omitDriverInstall (#13249)
This commit is contained in:
parent
bba36dcae4
commit
5d2e8918d8
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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[],
|
||||
|
|
|
|||
|
|
@ -2846,6 +2846,7 @@ Android:
|
|||
devices:
|
||||
parameters:
|
||||
port: number?
|
||||
omitDriverInstall: boolean?
|
||||
returns:
|
||||
devices:
|
||||
type: array
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -369,5 +369,6 @@ export type APIResponse = {
|
|||
};
|
||||
|
||||
export type AndroidDeviceOptions = {
|
||||
port?: number
|
||||
port?: number,
|
||||
omitDriverInstall?: boolean,
|
||||
};
|
||||
|
|
|
|||
5
packages/playwright-core/types/types.d.ts
vendored
5
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue