mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(rpc): support electron (#2933)
This commit is contained in:
parent
9fdb3e23c3
commit
cc8fe5a763
@ -29,6 +29,7 @@ export type PlaywrightInitializer = {
|
||||
chromium: BrowserTypeChannel,
|
||||
firefox: BrowserTypeChannel,
|
||||
webkit: BrowserTypeChannel,
|
||||
electron?: ElectronChannel,
|
||||
deviceDescriptors: types.Devices,
|
||||
selectors: SelectorsChannel,
|
||||
};
|
||||
@ -384,4 +385,33 @@ export type PDFOptions = {
|
||||
preferCSSPageSize?: boolean,
|
||||
margin?: {top?: string, bottom?: string, left?: string, right?: string},
|
||||
path?: string,
|
||||
};
|
||||
|
||||
|
||||
export type ElectronLaunchOptions = {
|
||||
args?: string[],
|
||||
cwd?: string,
|
||||
env?: {[key: string]: string|number|boolean},
|
||||
handleSIGINT?: boolean,
|
||||
handleSIGTERM?: boolean,
|
||||
handleSIGHUP?: boolean,
|
||||
timeout?: number,
|
||||
};
|
||||
export interface ElectronChannel extends Channel {
|
||||
launch(params: { executablePath: string } & ElectronLaunchOptions): Promise<ElectronApplicationChannel>;
|
||||
}
|
||||
export type ElectronInitializer = {};
|
||||
|
||||
|
||||
export interface ElectronApplicationChannel extends Channel {
|
||||
on(event: 'close', callback: () => void): this;
|
||||
on(event: 'window', callback: (params: PageChannel) => void): this;
|
||||
|
||||
newBrowserWindow(params: { arg: any }): Promise<PageChannel>;
|
||||
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
||||
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise<JSHandleChannel>;
|
||||
close(): Promise<void>;
|
||||
}
|
||||
export type ElectronApplicationInitializer = {
|
||||
context: BrowserContextChannel,
|
||||
};
|
||||
|
@ -25,7 +25,6 @@ import { helper } from '../../helper';
|
||||
import { Browser } from './browser';
|
||||
import { Events } from '../../events';
|
||||
import { TimeoutSettings } from '../../timeoutSettings';
|
||||
import { BrowserType } from './browserType';
|
||||
import { Waiter } from './waiter';
|
||||
import { TimeoutError } from '../../errors';
|
||||
|
||||
@ -33,7 +32,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||
_pages = new Set<Page>();
|
||||
private _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
||||
readonly _browser: Browser | undefined;
|
||||
readonly _browserType: BrowserType;
|
||||
readonly _browserName: string;
|
||||
readonly _bindings = new Map<string, frames.FunctionWithSource>();
|
||||
_timeoutSettings = new TimeoutSettings();
|
||||
_ownerPage: Page | undefined;
|
||||
@ -48,15 +47,11 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||
return context ? BrowserContext.from(context) : null;
|
||||
}
|
||||
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: BrowserContextInitializer) {
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: BrowserContextInitializer, browserName: string) {
|
||||
super(parent, type, guid, initializer, true);
|
||||
if (parent instanceof Browser) {
|
||||
if (parent instanceof Browser)
|
||||
this._browser = parent;
|
||||
this._browserType = this._browser._browserType;
|
||||
} else {
|
||||
// Launching persistent context does not produce a browser at all.
|
||||
this._browserType = parent as BrowserType;
|
||||
}
|
||||
this._browserName = browserName;
|
||||
|
||||
this._channel.on('bindingCall', bindingCall => this._onBinding(BindingCall.from(bindingCall)));
|
||||
this._channel.on('close', () => this._onClose());
|
||||
|
@ -28,7 +28,7 @@ export class ChromiumBrowserContext extends BrowserContext {
|
||||
_serviceWorkers = new Set<Worker>();
|
||||
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: BrowserContextInitializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
super(parent, type, guid, initializer, 'chromium');
|
||||
this._channel.on('crBackgroundPage', pageChannel => {
|
||||
const page = Page.from(pageChannel);
|
||||
this._backgroundPages.add(page);
|
||||
|
@ -32,6 +32,7 @@ import { parseError } from '../serializers';
|
||||
import { BrowserServer } from './browserServer';
|
||||
import { CDPSession } from './cdpSession';
|
||||
import { Playwright } from './playwright';
|
||||
import { Electron, ElectronApplication } from './electron';
|
||||
import { Channel } from '../channels';
|
||||
import { ChromiumBrowser } from './chromiumBrowser';
|
||||
import { ChromiumBrowserContext } from './chromiumBrowserContext';
|
||||
@ -151,12 +152,21 @@ export class Connection {
|
||||
result = new CDPSession(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'context':
|
||||
// Launching persistent context produces BrowserType parent directly for BrowserContext.
|
||||
const browserType = parent instanceof Browser ? parent._browserType : parent as BrowserType;
|
||||
if (browserType.name() === 'chromium')
|
||||
let browserName = '';
|
||||
if (parent instanceof Electron) {
|
||||
// Launching electron produces Electron parent for BrowserContext.
|
||||
browserName = 'electron';
|
||||
} else if (parent instanceof Browser) {
|
||||
// Launching a browser produces Browser parent for BrowserContext.
|
||||
browserName = parent._browserType.name();
|
||||
} else {
|
||||
// Launching persistent context produces BrowserType parent for BrowserContext.
|
||||
browserName = (parent as BrowserType).name();
|
||||
}
|
||||
if (browserName === 'chromium')
|
||||
result = new ChromiumBrowserContext(parent, type, guid, initializer);
|
||||
else
|
||||
result = new BrowserContext(parent, type, guid, initializer);
|
||||
result = new BrowserContext(parent, type, guid, initializer, browserName);
|
||||
break;
|
||||
case 'consoleMessage':
|
||||
result = new ConsoleMessage(parent, type, guid, initializer);
|
||||
@ -167,6 +177,12 @@ export class Connection {
|
||||
case 'download':
|
||||
result = new Download(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'electron':
|
||||
result = new Electron(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'electronApplication':
|
||||
result = new ElectronApplication(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'elementHandle':
|
||||
result = new ElementHandle(parent, type, guid, initializer);
|
||||
break;
|
||||
|
112
src/rpc/client/electron.ts
Normal file
112
src/rpc/client/electron.ts
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as types from '../../types';
|
||||
import { ElectronChannel, ElectronInitializer, ElectronLaunchOptions, ElectronApplicationChannel, ElectronApplicationInitializer } from '../channels';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Page } from './page';
|
||||
import { serializeArgument, FuncOn, parseResult, SmartHandle, JSHandle } from './jsHandle';
|
||||
import { ElectronEvents } from '../../server/electron';
|
||||
import { TimeoutSettings } from '../../timeoutSettings';
|
||||
import { Waiter } from './waiter';
|
||||
import { TimeoutError } from '../../errors';
|
||||
|
||||
export class Electron extends ChannelOwner<ElectronChannel, ElectronInitializer> {
|
||||
static from(electron: ElectronChannel): Electron {
|
||||
return (electron as any)._object;
|
||||
}
|
||||
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: ElectronInitializer) {
|
||||
super(parent, type, guid, initializer, true);
|
||||
}
|
||||
|
||||
async launch(executablePath: string, options: ElectronLaunchOptions = {}): Promise<ElectronApplication> {
|
||||
options = { ...options };
|
||||
delete (options as any).logger;
|
||||
return ElectronApplication.from(await this._channel.launch({ executablePath, ...options }));
|
||||
}
|
||||
}
|
||||
|
||||
export class ElectronApplication extends ChannelOwner<ElectronApplicationChannel, ElectronApplicationInitializer> {
|
||||
private _context: BrowserContext;
|
||||
private _windows = new Set<Page>();
|
||||
private _timeoutSettings = new TimeoutSettings();
|
||||
|
||||
static from(electronApplication: ElectronApplicationChannel): ElectronApplication {
|
||||
return (electronApplication as any)._object;
|
||||
}
|
||||
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: ElectronApplicationInitializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
this._context = BrowserContext.from(initializer.context);
|
||||
this._channel.on('window', pageChannel => {
|
||||
const page = Page.from(pageChannel);
|
||||
this._windows.add(page);
|
||||
this.emit(ElectronEvents.ElectronApplication.Window, page);
|
||||
});
|
||||
this._channel.on('close', () => {
|
||||
this.emit(ElectronEvents.ElectronApplication.Close);
|
||||
});
|
||||
}
|
||||
|
||||
windows(): Page[] {
|
||||
return [...this._windows];
|
||||
}
|
||||
|
||||
async firstWindow(): Promise<Page> {
|
||||
if (this._windows.size)
|
||||
return this._windows.values().next().value;
|
||||
return this.waitForEvent('window');
|
||||
}
|
||||
|
||||
async newBrowserWindow(options: any): Promise<Page> {
|
||||
return Page.from(await this._channel.newBrowserWindow({ arg: serializeArgument(options) }));
|
||||
}
|
||||
|
||||
context(): BrowserContext {
|
||||
return this._context;
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this._channel.close();
|
||||
}
|
||||
|
||||
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
|
||||
const timeout = this._timeoutSettings.timeout(optionsOrPredicate instanceof Function ? {} : optionsOrPredicate);
|
||||
const predicate = optionsOrPredicate instanceof Function ? optionsOrPredicate : optionsOrPredicate.predicate;
|
||||
const waiter = new Waiter();
|
||||
waiter.rejectOnTimeout(timeout, new TimeoutError(`Timeout while waiting for event "${event}"`));
|
||||
if (event !== ElectronEvents.ElectronApplication.Close)
|
||||
waiter.rejectOnEvent(this, ElectronEvents.ElectronApplication.Close, new Error('Electron application closed'));
|
||||
const result = await waiter.waitForEvent(this, event, predicate as any);
|
||||
waiter.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<R>;
|
||||
async evaluate<R>(pageFunction: FuncOn<any, void, R>, arg?: any): Promise<R>;
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<R> {
|
||||
return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }));
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R>(pageFunction: FuncOn<any, void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<any, Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||
const handleChannel = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
|
||||
return JSHandle.from(handleChannel) as SmartHandle<R>;
|
||||
}
|
||||
}
|
@ -104,7 +104,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||
this._channel.on('route', ({ route, request }) => this._onRoute(Route.from(route), Request.from(request)));
|
||||
this._channel.on('worker', worker => this._onWorker(Worker.from(worker)));
|
||||
|
||||
if (this._browserContext._browserType.name() === 'chromium') {
|
||||
if (this._browserContext._browserName === 'chromium') {
|
||||
this.coverage = new Coverage(this._channel);
|
||||
this.pdf = options => this._pdf(options);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import * as types from '../../types';
|
||||
import { BrowserType } from './browserType';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Selectors } from './selectors';
|
||||
import { Electron } from './electron';
|
||||
|
||||
export class Playwright extends ChannelOwner<PlaywrightChannel, PlaywrightInitializer> {
|
||||
chromium: BrowserType;
|
||||
@ -32,6 +33,8 @@ export class Playwright extends ChannelOwner<PlaywrightChannel, PlaywrightInitia
|
||||
this.chromium = BrowserType.from(initializer.chromium);
|
||||
this.firefox = BrowserType.from(initializer.firefox);
|
||||
this.webkit = BrowserType.from(initializer.webkit);
|
||||
if (initializer.electron)
|
||||
(this as any).electron = Electron.from(initializer.electron);
|
||||
this.devices = initializer.deviceDescriptors;
|
||||
this.selectors = Selectors.from(initializer.selectors);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import { Transport } from './transport';
|
||||
import { DispatcherConnection } from './server/dispatcher';
|
||||
import { Playwright } from '../server/playwright';
|
||||
import { PlaywrightDispatcher } from './server/playwrightDispatcher';
|
||||
import { Electron } from '../server/electron';
|
||||
|
||||
const dispatcherConnection = new DispatcherConnection();
|
||||
const transport = new Transport(process.stdout, process.stdin);
|
||||
@ -26,4 +27,5 @@ transport.onmessage = message => dispatcherConnection.dispatch(JSON.parse(messag
|
||||
dispatcherConnection.onmessage = message => transport.send(JSON.stringify(message));
|
||||
|
||||
const playwright = new Playwright(__dirname, require('../../browsers.json')['browsers']);
|
||||
(playwright as any).electron = new Electron();
|
||||
new PlaywrightDispatcher(dispatcherConnection.rootDispatcher(), playwright);
|
||||
|
66
src/rpc/server/electronDispatcher.ts
Normal file
66
src/rpc/server/electronDispatcher.ts
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Dispatcher, DispatcherScope, lookupDispatcher } from './dispatcher';
|
||||
import { Electron, ElectronApplication, ElectronEvents } from '../../server/electron';
|
||||
import { ElectronApplicationChannel, ElectronApplicationInitializer, PageChannel, JSHandleChannel, ElectronInitializer, ElectronChannel, ElectronLaunchOptions } from '../channels';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import { BrowserContextBase } from '../../browserContext';
|
||||
import { Page } from '../../page';
|
||||
import { PageDispatcher } from './pageDispatcher';
|
||||
import { parseArgument } from './jsHandleDispatcher';
|
||||
import { createHandle } from './elementHandlerDispatcher';
|
||||
|
||||
export class ElectronDispatcher extends Dispatcher<Electron, ElectronInitializer> implements ElectronChannel {
|
||||
constructor(scope: DispatcherScope, electron: Electron) {
|
||||
super(scope, electron, 'electron', {}, true);
|
||||
}
|
||||
|
||||
async launch(params: { executablePath: string } & ElectronLaunchOptions): Promise<ElectronApplicationChannel> {
|
||||
const electronApplication = await this._object.launch(params.executablePath, params);
|
||||
return new ElectronApplicationDispatcher(this._scope, electronApplication);
|
||||
}
|
||||
}
|
||||
|
||||
export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplication, ElectronApplicationInitializer> implements ElectronApplicationChannel {
|
||||
constructor(scope: DispatcherScope, electronApplication: ElectronApplication) {
|
||||
super(scope, electronApplication, 'electronApplication', {
|
||||
context: new BrowserContextDispatcher(scope, electronApplication.context() as BrowserContextBase),
|
||||
});
|
||||
|
||||
electronApplication.on(ElectronEvents.ElectronApplication.Close, () => this._dispatchEvent('close'));
|
||||
electronApplication.on(ElectronEvents.ElectronApplication.Window, (page: Page) => this._dispatchEvent('window', lookupDispatcher<PageDispatcher>(page)));
|
||||
}
|
||||
|
||||
async newBrowserWindow(params: { arg: any }): Promise<PageChannel> {
|
||||
return lookupDispatcher<PageChannel>(await this._object.newBrowserWindow(parseArgument(params.arg)));
|
||||
}
|
||||
|
||||
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any> {
|
||||
const handle = this._object._nodeElectronHandle!;
|
||||
return handle._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg));
|
||||
}
|
||||
|
||||
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<JSHandleChannel> {
|
||||
const handle = this._object._nodeElectronHandle!;
|
||||
const result = await handle._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg));
|
||||
return createHandle(this._scope, result);
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
await this._object.close();
|
||||
}
|
||||
}
|
@ -19,13 +19,17 @@ import { PlaywrightChannel, PlaywrightInitializer } from '../channels';
|
||||
import { BrowserTypeDispatcher } from './browserTypeDispatcher';
|
||||
import { Dispatcher, DispatcherScope } from './dispatcher';
|
||||
import { SelectorsDispatcher } from './selectorsDispatcher';
|
||||
import { Electron } from '../../server/electron';
|
||||
import { ElectronDispatcher } from './electronDispatcher';
|
||||
|
||||
export class PlaywrightDispatcher extends Dispatcher<Playwright, PlaywrightInitializer> implements PlaywrightChannel {
|
||||
constructor(scope: DispatcherScope, playwright: Playwright) {
|
||||
const electron = (playwright as any).electron as (Electron | undefined);
|
||||
super(scope, playwright, 'playwright', {
|
||||
chromium: new BrowserTypeDispatcher(scope, playwright.chromium!),
|
||||
firefox: new BrowserTypeDispatcher(scope, playwright.firefox!),
|
||||
webkit: new BrowserTypeDispatcher(scope, playwright.webkit!),
|
||||
electron: electron ? new ElectronDispatcher(scope, electron) : undefined,
|
||||
deviceDescriptors: playwright.devices,
|
||||
selectors: new SelectorsDispatcher(scope, playwright.selectors),
|
||||
}, false, 'playwright');
|
||||
|
@ -63,7 +63,7 @@ export class ElectronApplication extends EventEmitter {
|
||||
private _nodeConnection: CRConnection;
|
||||
private _nodeSession: CRSession;
|
||||
private _nodeExecutionContext: js.ExecutionContext | undefined;
|
||||
private _nodeElectronHandle: js.JSHandle<any> | undefined;
|
||||
_nodeElectronHandle: js.JSHandle<any> | undefined;
|
||||
private _windows = new Set<ElectronPage>();
|
||||
private _lastWindowId = 0;
|
||||
readonly _timeoutSettings = new TimeoutSettings();
|
||||
|
@ -33,6 +33,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
{ _guid: 'browserType', objects: [] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
@ -57,6 +58,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
});
|
||||
|
||||
@ -75,6 +77,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
{ _guid: 'browserType', objects: [] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
@ -92,6 +95,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
{ _guid: 'browserType', objects: [] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
});
|
||||
|
||||
@ -110,6 +114,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
{ _guid: 'browserType', objects: [] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
@ -129,6 +134,7 @@ describe.skip(!CHANNEL)('Channels', function() {
|
||||
{ _guid: 'browserType', objects: [] },
|
||||
{ _guid: 'playwright' },
|
||||
{ _guid: 'selectors' },
|
||||
{ _guid: 'electron', objects: [] },
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -21,7 +21,7 @@ const {CHANNEL} = utils.testOptions(browserType);
|
||||
|
||||
const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron';
|
||||
|
||||
describe.skip(CHANNEL)('Electron', function() {
|
||||
describe('Electron', function() {
|
||||
beforeEach(async (state, testRun) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
state.logger = utils.createTestLogger(config.dumpLogOnFailure, testRun);
|
||||
@ -55,7 +55,7 @@ describe.skip(CHANNEL)('Electron', function() {
|
||||
await page.goto('data:text/html,<title>Hello World 2</title>');
|
||||
expect(await page.title()).toBe('Hello World 2');
|
||||
});
|
||||
it('should create multiple windows', async ({ application }) => {
|
||||
it.skip(CHANNEL)('should create multiple windows', async ({ application }) => {
|
||||
const createPage = async ordinal => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await Promise.all([
|
||||
@ -117,7 +117,7 @@ describe.skip(CHANNEL)('Electron', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(CHANNEL)('Electron per window', function() {
|
||||
describe('Electron per window', function() {
|
||||
beforeAll(async state => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
state.application = await state.playwright.electron.launch(electronPath, {
|
||||
|
Loading…
x
Reference in New Issue
Block a user