mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
test(adb): fix the adb tests (#4691)
This commit is contained in:
parent
2ba60e92e3
commit
6cc695d92a
@ -31,7 +31,8 @@
|
|||||||
"roll-browser": "node utils/roll_browser.js",
|
"roll-browser": "node utils/roll_browser.js",
|
||||||
"coverage": "node test/checkCoverage.js",
|
"coverage": "node test/checkCoverage.js",
|
||||||
"check-deps": "node utils/check_deps.js",
|
"check-deps": "node utils/check_deps.js",
|
||||||
"build-android-driver": "./utils/build_android_driver.sh"
|
"build-android-driver": "./utils/build_android_driver.sh",
|
||||||
|
"test-android-driver": "PW_ANDROID_TESTS=1 npx folio test/android -p browserName=chromium --workers=1"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Dispatcher, DispatcherScope } from './dispatcher';
|
import { Dispatcher, DispatcherScope, existingDispatcher } from './dispatcher';
|
||||||
import { Android, AndroidDevice } from '../server/android/android';
|
import { Android, AndroidDevice } from '../server/android/android';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||||
@ -27,7 +27,7 @@ export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidIniti
|
|||||||
async devices(params: channels.AndroidDevicesParams): Promise<channels.AndroidDevicesResult> {
|
async devices(params: channels.AndroidDevicesParams): Promise<channels.AndroidDevicesResult> {
|
||||||
const devices = await this._object.devices();
|
const devices = await this._object.devices();
|
||||||
return {
|
return {
|
||||||
devices: devices.map(d => new AndroidDeviceDispatcher(this._scope, d))
|
devices: devices.map(d => AndroidDeviceDispatcher.from(this._scope, d))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +37,12 @@ export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidIniti
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.AndroidDeviceInitializer> implements channels.AndroidDeviceChannel {
|
export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.AndroidDeviceInitializer> implements channels.AndroidDeviceChannel {
|
||||||
|
|
||||||
|
static from(scope: DispatcherScope, device: AndroidDevice): AndroidDeviceDispatcher {
|
||||||
|
const result = existingDispatcher<AndroidDeviceDispatcher>(device);
|
||||||
|
return result || new AndroidDeviceDispatcher(scope, device);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(scope: DispatcherScope, device: AndroidDevice) {
|
constructor(scope: DispatcherScope, device: AndroidDevice) {
|
||||||
super(scope, device, 'AndroidDevice', {
|
super(scope, device, 'AndroidDevice', {
|
||||||
model: device.model,
|
model: device.model,
|
||||||
|
@ -82,6 +82,10 @@ export class Android {
|
|||||||
}
|
}
|
||||||
return [...this._devices.values()];
|
return [...this._devices.values()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_deviceClosed(device: AndroidDevice) {
|
||||||
|
this._devices.delete(device.serial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AndroidDevice extends EventEmitter {
|
export class AndroidDevice extends EventEmitter {
|
||||||
@ -98,12 +102,16 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
static Events = {
|
static Events = {
|
||||||
WebViewAdded: 'webViewAdded',
|
WebViewAdded: 'webViewAdded',
|
||||||
WebViewRemoved: 'webViewRemoved',
|
WebViewRemoved: 'webViewRemoved',
|
||||||
|
Closed: 'closed'
|
||||||
};
|
};
|
||||||
|
|
||||||
private _browserConnections = new Set<AndroidBrowser>();
|
private _browserConnections = new Set<AndroidBrowser>();
|
||||||
|
private _android: Android;
|
||||||
|
private _isClosed = false;
|
||||||
|
|
||||||
constructor(android: Android, backend: DeviceBackend, model: string) {
|
constructor(android: Android, backend: DeviceBackend, model: string) {
|
||||||
super();
|
super();
|
||||||
|
this._android = android;
|
||||||
this._backend = backend;
|
this._backend = backend;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.serial = backend.serial;
|
this.serial = backend.serial;
|
||||||
@ -202,6 +210,7 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
|
this._isClosed = true;
|
||||||
if (this._pollingWebViews)
|
if (this._pollingWebViews)
|
||||||
clearTimeout(this._pollingWebViews);
|
clearTimeout(this._pollingWebViews);
|
||||||
for (const connection of this._browserConnections)
|
for (const connection of this._browserConnections)
|
||||||
@ -211,6 +220,8 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
driver.close();
|
driver.close();
|
||||||
}
|
}
|
||||||
await this._backend.close();
|
await this._backend.close();
|
||||||
|
this._android._deviceClosed(this);
|
||||||
|
this.emit(AndroidDevice.Events.Closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
async launchBrowser(pkg: string = 'com.android.chrome', options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
async launchBrowser(pkg: string = 'com.android.chrome', options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
||||||
@ -234,11 +245,11 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
return await this._connectToBrowser(socketName, options);
|
return await this._connectToBrowser(socketName, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToWebView(pid: number): Promise<BrowserContext> {
|
async connectToWebView(pid: number): Promise<BrowserContext> {
|
||||||
const webView = this._webViews.get(pid);
|
const webView = this._webViews.get(pid);
|
||||||
if (!webView)
|
if (!webView)
|
||||||
throw new Error('WebView has been closed');
|
throw new Error('WebView has been closed');
|
||||||
return this._connectToBrowser(`webview_devtools_remote_${pid}`);
|
return await this._connectToBrowser(`webview_devtools_remote_${pid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _connectToBrowser(socketName: string, options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
private async _connectToBrowser(socketName: string, options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
||||||
@ -272,6 +283,8 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
|
|
||||||
private async _refreshWebViews() {
|
private async _refreshWebViews() {
|
||||||
const sockets = (await this._backend.runCommand(`shell:cat /proc/net/unix | grep webview_devtools_remote`)).split('\n');
|
const sockets = (await this._backend.runCommand(`shell:cat /proc/net/unix | grep webview_devtools_remote`)).split('\n');
|
||||||
|
if (this._isClosed)
|
||||||
|
return;
|
||||||
|
|
||||||
const newPids = new Set<number>();
|
const newPids = new Set<number>();
|
||||||
for (const line of sockets) {
|
for (const line of sockets) {
|
||||||
@ -286,6 +299,8 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const procs = (await this._backend.runCommand(`shell:ps -A | grep ${pid}`)).split('\n');
|
const procs = (await this._backend.runCommand(`shell:ps -A | grep ${pid}`)).split('\n');
|
||||||
|
if (this._isClosed)
|
||||||
|
return;
|
||||||
let pkg = '';
|
let pkg = '';
|
||||||
for (const proc of procs) {
|
for (const proc of procs) {
|
||||||
const match = proc.match(/[^\s]+\s+(\d+).*$/);
|
const match = proc.match(/[^\s]+\s+(\d+).*$/);
|
||||||
|
@ -23,6 +23,7 @@ if (process.env.PW_ANDROID_TESTS) {
|
|||||||
await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
|
await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
|
||||||
const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
|
const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
|
||||||
expect(webview.pkg()).toBe('org.chromium.webview_shell');
|
expect(webview.pkg()).toBe('org.chromium.webview_shell');
|
||||||
|
expect(device.webViews().length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should connect to page', async function({ device }) {
|
it('should connect to page', async function({ device }) {
|
||||||
@ -33,7 +34,7 @@ if (process.env.PW_ANDROID_TESTS) {
|
|||||||
expect(page.url()).toBe('about:blank');
|
expect(page.url()).toBe('about:blank');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate page externally', async function({ device, server }) {
|
it('should navigate page internally', async function({ device, server }) {
|
||||||
expect(device.webViews().length).toBe(0);
|
expect(device.webViews().length).toBe(0);
|
||||||
await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
|
await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
|
||||||
const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
|
const webview = await device.webView({ pkg: 'org.chromium.webview_shell' });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user