feat(android): add AndroidDevice.close event (#18306)
This commit is contained in:
parent
63c41f88cd
commit
e25537f941
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
[AndroidDevice] represents a connected device, either real hardware or emulated. Devices can be obtained using [`method: Android.devices`].
|
[AndroidDevice] represents a connected device, either real hardware or emulated. Devices can be obtained using [`method: Android.devices`].
|
||||||
|
|
||||||
|
## event: AndroidDevice.close
|
||||||
|
* since: v1.28
|
||||||
|
- argument: <[AndroidDevice]>
|
||||||
|
|
||||||
|
Emitted when the device connection gets closed.
|
||||||
|
|
||||||
## event: AndroidDevice.webView
|
## event: AndroidDevice.webView
|
||||||
* since: v1.9
|
* since: v1.9
|
||||||
- argument: <[AndroidWebView]>
|
- argument: <[AndroidWebView]>
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,10 @@ export class AndroidServerLauncherImpl {
|
||||||
browserServer.wsEndpoint = () => wsEndpoint;
|
browserServer.wsEndpoint = () => wsEndpoint;
|
||||||
browserServer.close = () => device.close();
|
browserServer.close = () => device.close();
|
||||||
browserServer.kill = () => device.close();
|
browserServer.kill = () => device.close();
|
||||||
|
device.on('close', () => {
|
||||||
|
server.close();
|
||||||
|
browserServer.emit('close');
|
||||||
|
});
|
||||||
return browserServer;
|
return browserServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
|
||||||
this._timeoutSettings = new TimeoutSettings((parent as Android)._timeoutSettings);
|
this._timeoutSettings = new TimeoutSettings((parent as Android)._timeoutSettings);
|
||||||
this._channel.on('webViewAdded', ({ webView }) => this._onWebViewAdded(webView));
|
this._channel.on('webViewAdded', ({ webView }) => this._onWebViewAdded(webView));
|
||||||
this._channel.on('webViewRemoved', ({ socketName }) => this._onWebViewRemoved(socketName));
|
this._channel.on('webViewRemoved', ({ socketName }) => this._onWebViewRemoved(socketName));
|
||||||
|
this._channel.on('close', () => this._didClose());
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onWebViewAdded(webView: channels.AndroidWebView) {
|
private _onWebViewAdded(webView: channels.AndroidWebView) {
|
||||||
|
|
@ -239,7 +240,6 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
try {
|
try {
|
||||||
this._didClose();
|
|
||||||
if (this._shouldCloseConnectionOnClose)
|
if (this._shouldCloseConnectionOnClose)
|
||||||
this._connection.close(kBrowserClosedError);
|
this._connection.close(kBrowserClosedError);
|
||||||
else
|
else
|
||||||
|
|
@ -252,7 +252,7 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
|
||||||
}
|
}
|
||||||
|
|
||||||
_didClose() {
|
_didClose() {
|
||||||
this.emit(Events.AndroidDevice.Close);
|
this.emit(Events.AndroidDevice.Close, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async shell(command: string): Promise<Buffer> {
|
async shell(command: string): Promise<Buffer> {
|
||||||
|
|
|
||||||
|
|
@ -2209,6 +2209,7 @@ scheme.AndroidDeviceInitializer = tObject({
|
||||||
model: tString,
|
model: tString,
|
||||||
serial: tString,
|
serial: tString,
|
||||||
});
|
});
|
||||||
|
scheme.AndroidDeviceCloseEvent = tOptional(tObject({}));
|
||||||
scheme.AndroidDeviceWebViewAddedEvent = tObject({
|
scheme.AndroidDeviceWebViewAddedEvent = tObject({
|
||||||
webView: tType('AndroidWebView'),
|
webView: tType('AndroidWebView'),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ export class PlaywrightConnection {
|
||||||
this._debugLog(`engaged pre-launched (Android) mode`);
|
this._debugLog(`engaged pre-launched (Android) mode`);
|
||||||
const playwright = this._preLaunched.playwright!;
|
const playwright = this._preLaunched.playwright!;
|
||||||
const androidDevice = this._preLaunched.androidDevice!;
|
const androidDevice = this._preLaunched.androidDevice!;
|
||||||
androidDevice.on(AndroidDevice.Events.Closed, () => {
|
androidDevice.on(AndroidDevice.Events.Close, () => {
|
||||||
// Underlying browser did close for some reason - force disconnect the client.
|
// Underlying browser did close for some reason - force disconnect the client.
|
||||||
this.close({ code: 1001, reason: 'Android device disconnected' });
|
this.close({ code: 1001, reason: 'Android device disconnected' });
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ export class AndroidDevice extends SdkObject {
|
||||||
static Events = {
|
static Events = {
|
||||||
WebViewAdded: 'webViewAdded',
|
WebViewAdded: 'webViewAdded',
|
||||||
WebViewRemoved: 'webViewRemoved',
|
WebViewRemoved: 'webViewRemoved',
|
||||||
Closed: 'closed'
|
Close: 'close',
|
||||||
};
|
};
|
||||||
|
|
||||||
private _browserConnections = new Set<AndroidBrowser>();
|
private _browserConnections = new Set<AndroidBrowser>();
|
||||||
|
|
@ -140,7 +140,11 @@ export class AndroidDevice extends SdkObject {
|
||||||
async _init() {
|
async _init() {
|
||||||
await this._refreshWebViews();
|
await this._refreshWebViews();
|
||||||
const poll = () => {
|
const poll = () => {
|
||||||
this._pollingWebViews = setTimeout(() => this._refreshWebViews().then(poll).catch(() => {}), 500);
|
this._pollingWebViews = setTimeout(() => this._refreshWebViews()
|
||||||
|
.then(poll)
|
||||||
|
.catch(() => {
|
||||||
|
this.close().catch(() => {});
|
||||||
|
}), 500);
|
||||||
};
|
};
|
||||||
poll();
|
poll();
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +167,9 @@ export class AndroidDevice extends SdkObject {
|
||||||
return await this._backend.runCommand(`shell:screencap -p`);
|
return await this._backend.runCommand(`shell:screencap -p`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _driver(): Promise<PipeTransport> {
|
private async _driver(): Promise<PipeTransport | undefined> {
|
||||||
|
if (this._isClosed)
|
||||||
|
return;
|
||||||
if (!this._driverPromise)
|
if (!this._driverPromise)
|
||||||
this._driverPromise = this._installDriver();
|
this._driverPromise = this._installDriver();
|
||||||
return this._driverPromise;
|
return this._driverPromise;
|
||||||
|
|
@ -223,6 +229,8 @@ export class AndroidDevice extends SdkObject {
|
||||||
// Patch the timeout in!
|
// Patch the timeout in!
|
||||||
params.timeout = this._timeoutSettings.timeout(params);
|
params.timeout = this._timeoutSettings.timeout(params);
|
||||||
const driver = await this._driver();
|
const driver = await this._driver();
|
||||||
|
if (!driver)
|
||||||
|
throw new Error('Device is closed');
|
||||||
const id = ++this._lastId;
|
const id = ++this._lastId;
|
||||||
const result = new Promise((fulfill, reject) => this._callbacks.set(id, { fulfill, reject }));
|
const result = new Promise((fulfill, reject) => this._callbacks.set(id, { fulfill, reject }));
|
||||||
driver.send(JSON.stringify({ id, method, params }));
|
driver.send(JSON.stringify({ id, method, params }));
|
||||||
|
|
@ -230,6 +238,8 @@ export class AndroidDevice extends SdkObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
|
if (this._isClosed)
|
||||||
|
return;
|
||||||
this._isClosed = true;
|
this._isClosed = true;
|
||||||
if (this._pollingWebViews)
|
if (this._pollingWebViews)
|
||||||
clearTimeout(this._pollingWebViews);
|
clearTimeout(this._pollingWebViews);
|
||||||
|
|
@ -237,11 +247,11 @@ export class AndroidDevice extends SdkObject {
|
||||||
await connection.close();
|
await connection.close();
|
||||||
if (this._driverPromise) {
|
if (this._driverPromise) {
|
||||||
const driver = await this._driver();
|
const driver = await this._driver();
|
||||||
driver.close();
|
driver?.close();
|
||||||
}
|
}
|
||||||
await this._backend.close();
|
await this._backend.close();
|
||||||
this._android._deviceClosed(this);
|
this._android._deviceClosed(this);
|
||||||
this.emit(AndroidDevice.Events.Closed);
|
this.emit(AndroidDevice.Events.Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
async launchBrowser(pkg: string = 'com.android.chrome', options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
async launchBrowser(pkg: string = 'com.android.chrome', options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
||||||
|
|
|
||||||
|
|
@ -71,23 +71,26 @@ class AdbDevice implements DeviceBackend {
|
||||||
async function runCommand(command: string, host: string = '127.0.0.1', port: number = 5037, serial?: string): Promise<Buffer> {
|
async function runCommand(command: string, host: string = '127.0.0.1', port: number = 5037, serial?: string): Promise<Buffer> {
|
||||||
debug('pw:adb:runCommand')(command, serial);
|
debug('pw:adb:runCommand')(command, serial);
|
||||||
const socket = new BufferedSocketWrapper(command, net.createConnection({ host, port }));
|
const socket = new BufferedSocketWrapper(command, net.createConnection({ host, port }));
|
||||||
if (serial) {
|
try {
|
||||||
await socket.write(encodeMessage(`host:transport:${serial}`));
|
if (serial) {
|
||||||
|
await socket.write(encodeMessage(`host:transport:${serial}`));
|
||||||
|
const status = await socket.read(4);
|
||||||
|
assert(status.toString() === 'OKAY', status.toString());
|
||||||
|
}
|
||||||
|
await socket.write(encodeMessage(command));
|
||||||
const status = await socket.read(4);
|
const status = await socket.read(4);
|
||||||
assert(status.toString() === 'OKAY', status.toString());
|
assert(status.toString() === 'OKAY', status.toString());
|
||||||
|
let commandOutput: Buffer;
|
||||||
|
if (!command.startsWith('shell:')) {
|
||||||
|
const remainingLength = parseInt((await socket.read(4)).toString(), 16);
|
||||||
|
commandOutput = await socket.read(remainingLength);
|
||||||
|
} else {
|
||||||
|
commandOutput = await socket.readAll();
|
||||||
|
}
|
||||||
|
return commandOutput;
|
||||||
|
} finally {
|
||||||
|
socket.close();
|
||||||
}
|
}
|
||||||
await socket.write(encodeMessage(command));
|
|
||||||
const status = await socket.read(4);
|
|
||||||
assert(status.toString() === 'OKAY', status.toString());
|
|
||||||
let commandOutput: Buffer;
|
|
||||||
if (!command.startsWith('shell:')) {
|
|
||||||
const remainingLength = parseInt((await socket.read(4)).toString(), 16);
|
|
||||||
commandOutput = await socket.read(remainingLength);
|
|
||||||
} else {
|
|
||||||
commandOutput = await socket.readAll();
|
|
||||||
}
|
|
||||||
socket.close();
|
|
||||||
return commandOutput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function open(command: string, host: string = '127.0.0.1', port: number = 5037, serial?: string): Promise<BufferedSocketWrapper> {
|
async function open(command: string, host: string = '127.0.0.1', port: number = 5037, serial?: string): Promise<BufferedSocketWrapper> {
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.
|
||||||
this._dispatchEvent('webViewAdded', { webView });
|
this._dispatchEvent('webViewAdded', { webView });
|
||||||
this.addObjectListener(AndroidDevice.Events.WebViewAdded, webView => this._dispatchEvent('webViewAdded', { webView }));
|
this.addObjectListener(AndroidDevice.Events.WebViewAdded, webView => this._dispatchEvent('webViewAdded', { webView }));
|
||||||
this.addObjectListener(AndroidDevice.Events.WebViewRemoved, socketName => this._dispatchEvent('webViewRemoved', { socketName }));
|
this.addObjectListener(AndroidDevice.Events.WebViewRemoved, socketName => this._dispatchEvent('webViewRemoved', { socketName }));
|
||||||
|
this.addObjectListener(AndroidDevice.Events.Close, socketName => this._dispatchEvent('close'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async wait(params: channels.AndroidDeviceWaitParams) {
|
async wait(params: channels.AndroidDeviceWaitParams) {
|
||||||
|
|
|
||||||
35
packages/playwright-core/types/types.d.ts
vendored
35
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -12475,31 +12475,61 @@ export interface Android {
|
||||||
* [android.devices([options])](https://playwright.dev/docs/api/class-android#android-devices).
|
* [android.devices([options])](https://playwright.dev/docs/api/class-android#android-devices).
|
||||||
*/
|
*/
|
||||||
export interface AndroidDevice {
|
export interface AndroidDevice {
|
||||||
|
/**
|
||||||
|
* Emitted when the device connection gets closed.
|
||||||
|
*/
|
||||||
|
on(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when a new WebView instance is detected.
|
* Emitted when a new WebView instance is detected.
|
||||||
*/
|
*/
|
||||||
on(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
on(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
|
||||||
|
*/
|
||||||
|
once(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
|
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
|
||||||
*/
|
*/
|
||||||
once(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
once(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the device connection gets closed.
|
||||||
|
*/
|
||||||
|
addListener(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when a new WebView instance is detected.
|
* Emitted when a new WebView instance is detected.
|
||||||
*/
|
*/
|
||||||
addListener(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
addListener(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an event listener added by `on` or `addListener`.
|
||||||
|
*/
|
||||||
|
removeListener(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an event listener added by `on` or `addListener`.
|
* Removes an event listener added by `on` or `addListener`.
|
||||||
*/
|
*/
|
||||||
removeListener(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
removeListener(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an event listener added by `on` or `addListener`.
|
||||||
|
*/
|
||||||
|
off(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an event listener added by `on` or `addListener`.
|
* Removes an event listener added by `on` or `addListener`.
|
||||||
*/
|
*/
|
||||||
off(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
off(event: 'webview', listener: (androidWebView: AndroidWebView) => void): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the device connection gets closed.
|
||||||
|
*/
|
||||||
|
prependListener(event: 'close', listener: (androidDevice: AndroidDevice) => void): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when a new WebView instance is detected.
|
* Emitted when a new WebView instance is detected.
|
||||||
*/
|
*/
|
||||||
|
|
@ -13105,6 +13135,11 @@ export interface AndroidDevice {
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the device connection gets closed.
|
||||||
|
*/
|
||||||
|
waitForEvent(event: 'close', optionsOrPredicate?: { predicate?: (androidDevice: AndroidDevice) => boolean | Promise<boolean>, timeout?: number } | ((androidDevice: AndroidDevice) => boolean | Promise<boolean>)): Promise<AndroidDevice>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when a new WebView instance is detected.
|
* Emitted when a new WebView instance is detected.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -4045,6 +4045,7 @@ export type AndroidDeviceInitializer = {
|
||||||
serial: string,
|
serial: string,
|
||||||
};
|
};
|
||||||
export interface AndroidDeviceEventTarget {
|
export interface AndroidDeviceEventTarget {
|
||||||
|
on(event: 'close', callback: (params: AndroidDeviceCloseEvent) => void): this;
|
||||||
on(event: 'webViewAdded', callback: (params: AndroidDeviceWebViewAddedEvent) => void): this;
|
on(event: 'webViewAdded', callback: (params: AndroidDeviceWebViewAddedEvent) => void): this;
|
||||||
on(event: 'webViewRemoved', callback: (params: AndroidDeviceWebViewRemovedEvent) => void): this;
|
on(event: 'webViewRemoved', callback: (params: AndroidDeviceWebViewRemovedEvent) => void): this;
|
||||||
}
|
}
|
||||||
|
|
@ -4076,6 +4077,7 @@ export interface AndroidDeviceChannel extends AndroidDeviceEventTarget, EventTar
|
||||||
connectToWebView(params: AndroidDeviceConnectToWebViewParams, metadata?: Metadata): Promise<AndroidDeviceConnectToWebViewResult>;
|
connectToWebView(params: AndroidDeviceConnectToWebViewParams, metadata?: Metadata): Promise<AndroidDeviceConnectToWebViewResult>;
|
||||||
close(params?: AndroidDeviceCloseParams, metadata?: Metadata): Promise<AndroidDeviceCloseResult>;
|
close(params?: AndroidDeviceCloseParams, metadata?: Metadata): Promise<AndroidDeviceCloseResult>;
|
||||||
}
|
}
|
||||||
|
export type AndroidDeviceCloseEvent = {};
|
||||||
export type AndroidDeviceWebViewAddedEvent = {
|
export type AndroidDeviceWebViewAddedEvent = {
|
||||||
webView: AndroidWebView,
|
webView: AndroidWebView,
|
||||||
};
|
};
|
||||||
|
|
@ -4406,6 +4408,7 @@ export type AndroidDeviceCloseOptions = {};
|
||||||
export type AndroidDeviceCloseResult = void;
|
export type AndroidDeviceCloseResult = void;
|
||||||
|
|
||||||
export interface AndroidDeviceEvents {
|
export interface AndroidDeviceEvents {
|
||||||
|
'close': AndroidDeviceCloseEvent;
|
||||||
'webViewAdded': AndroidDeviceWebViewAddedEvent;
|
'webViewAdded': AndroidDeviceWebViewAddedEvent;
|
||||||
'webViewRemoved': AndroidDeviceWebViewRemovedEvent;
|
'webViewRemoved': AndroidDeviceWebViewRemovedEvent;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3267,6 +3267,8 @@ AndroidDevice:
|
||||||
close:
|
close:
|
||||||
|
|
||||||
events:
|
events:
|
||||||
|
close:
|
||||||
|
|
||||||
webViewAdded:
|
webViewAdded:
|
||||||
parameters:
|
parameters:
|
||||||
webView: AndroidWebView
|
webView: AndroidWebView
|
||||||
|
|
|
||||||
|
|
@ -92,3 +92,14 @@ test('androidDevice.options.omitDriverInstall', async function({ playwright }) {
|
||||||
|
|
||||||
expect(fillStatus).toBe('success');
|
expect(fillStatus).toBe('success');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('androidDevice.close', async function({ playwright }) {
|
||||||
|
const devices = await playwright._android.devices();
|
||||||
|
expect(devices.length).toBe(1);
|
||||||
|
const device = devices[0];
|
||||||
|
const events = [];
|
||||||
|
device.on('close', () => events.push('close'));
|
||||||
|
await device.close();
|
||||||
|
await device.close();
|
||||||
|
expect(events).toEqual(['close']);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,29 @@ test('android.launchServer should connect to a device', async ({ playwright }) =
|
||||||
await browserServer.close();
|
await browserServer.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('android.launchServer should be abe to reconnect to a device', async ({ playwright }) => {
|
test('android.launchServer should handle close event correctly', async ({ playwright }) => {
|
||||||
|
const receivedEvents = [];
|
||||||
|
const browserServer = await playwright._android.launchServer();
|
||||||
|
const device = await playwright._android.connect(browserServer.wsEndpoint());
|
||||||
|
device.on('close', () => receivedEvents.push('device'));
|
||||||
|
browserServer.on('close', () => receivedEvents.push('browserServer'));
|
||||||
|
{
|
||||||
|
const waitForDeviceClose = new Promise(f => device.on('close', f));
|
||||||
|
await device.close();
|
||||||
|
await waitForDeviceClose;
|
||||||
|
}
|
||||||
|
expect(receivedEvents).toEqual(['device']);
|
||||||
|
await device.close();
|
||||||
|
expect(receivedEvents).toEqual(['device']);
|
||||||
|
await browserServer.close();
|
||||||
|
expect(receivedEvents).toEqual(['device', 'browserServer']);
|
||||||
|
await browserServer.close();
|
||||||
|
expect(receivedEvents).toEqual(['device', 'browserServer']);
|
||||||
|
await device.close();
|
||||||
|
expect(receivedEvents).toEqual(['device', 'browserServer']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('android.launchServer should be able to reconnect to a device', async ({ playwright }) => {
|
||||||
const browserServer = await playwright._android.launchServer();
|
const browserServer = await playwright._android.launchServer();
|
||||||
try {
|
try {
|
||||||
{
|
{
|
||||||
|
|
@ -94,10 +116,12 @@ test('android.launchServer should terminate WS connection when device gets disco
|
||||||
forwardingServer.on('connection', connection => {
|
forwardingServer.on('connection', connection => {
|
||||||
receivedConnection = connection;
|
receivedConnection = connection;
|
||||||
const actualConnection = new ws.WebSocket(browserServer.wsEndpoint());
|
const actualConnection = new ws.WebSocket(browserServer.wsEndpoint());
|
||||||
actualConnection.on('message', message => connection.send(message));
|
actualConnection.on('open', () => {
|
||||||
connection.on('message', message => actualConnection.send(message));
|
actualConnection.on('message', message => connection.send(message));
|
||||||
connection.on('close', () => actualConnection.close());
|
connection.on('message', message => actualConnection.send(message));
|
||||||
actualConnection.on('close', () => connection.close());
|
connection.on('close', () => actualConnection.close());
|
||||||
|
actualConnection.on('close', () => connection.close());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
const device = await playwright._android.connect(`ws://localhost:${(forwardingServer.address() as ws.AddressInfo).port}/connect`);
|
const device = await playwright._android.connect(`ws://localhost:${(forwardingServer.address() as ws.AddressInfo).port}/connect`);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue