fix(electron): make recordVideo work (#10810)
This commit is contained in:
parent
a4e68dbac1
commit
4996e184bf
|
|
@ -51,12 +51,14 @@ export class Electron extends ChannelOwner<channels.ElectronChannel> implements
|
|||
extraHTTPHeaders: options.extraHTTPHeaders && headersObjectToArray(options.extraHTTPHeaders),
|
||||
env: envObjectToArray(options.env ? options.env : process.env),
|
||||
};
|
||||
return ElectronApplication.from((await this._channel.launch(params)).electronApplication);
|
||||
const app = ElectronApplication.from((await this._channel.launch(params)).electronApplication);
|
||||
app._context._options = params;
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
export class ElectronApplication extends ChannelOwner<channels.ElectronApplicationChannel> implements api.ElectronApplication {
|
||||
private _context: BrowserContext;
|
||||
readonly _context: BrowserContext;
|
||||
private _windows = new Set<Page>();
|
||||
private _timeoutSettings = new TimeoutSettings();
|
||||
|
||||
|
|
@ -91,7 +93,7 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
|||
}
|
||||
|
||||
context(): BrowserContext {
|
||||
return this._context! as BrowserContext;
|
||||
return this._context;
|
||||
}
|
||||
|
||||
async close() {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||
readonly _harRecorder: HarRecorder | undefined;
|
||||
readonly tracing: Tracing;
|
||||
readonly fetchRequest: BrowserContextAPIRequestContext;
|
||||
private _customCloseHandler?: () => Promise<any>;
|
||||
|
||||
constructor(browser: Browser, options: types.BrowserContextOptions, browserContextId: string | undefined) {
|
||||
super(browser, 'browser-context');
|
||||
|
|
@ -275,6 +276,10 @@ export abstract class BrowserContext extends SdkObject {
|
|||
await Promise.all(Array.from(this._downloads).map(download => download.artifact.deleteOnContextClose()));
|
||||
}
|
||||
|
||||
setCustomCloseHandler(handler: (() => Promise<any>) | undefined) {
|
||||
this._customCloseHandler = handler;
|
||||
}
|
||||
|
||||
async close(metadata: CallMetadata) {
|
||||
if (this._closedStatus === 'open') {
|
||||
this.emit(BrowserContext.Events.BeforeClose);
|
||||
|
|
@ -291,7 +296,9 @@ export abstract class BrowserContext extends SdkObject {
|
|||
promises.push(artifact.finishedPromise());
|
||||
}
|
||||
|
||||
if (this._isPersistentContext) {
|
||||
if (this._customCloseHandler) {
|
||||
await this._customCloseHandler();
|
||||
} else if (this._isPersistentContext) {
|
||||
// Close all the pages instead of the context,
|
||||
// because we cannot close the default context.
|
||||
await Promise.all(this.pages().map(page => page.close(metadata)));
|
||||
|
|
@ -305,6 +312,10 @@ export abstract class BrowserContext extends SdkObject {
|
|||
promises.push(this._deleteAllDownloads());
|
||||
await Promise.all(promises);
|
||||
|
||||
// Custom handler should trigger didCloseInternal itself.
|
||||
if (this._customCloseHandler)
|
||||
return;
|
||||
|
||||
// Persistent context should also close the browser.
|
||||
if (this._isPersistentContext)
|
||||
await this._browser.close();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { Page } from '../page';
|
|||
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
||||
import { WebSocketTransport } from '../transport';
|
||||
import { launchProcess, envArrayToObject } from '../../utils/processLauncher';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { BrowserContext, validateBrowserContextOptions } from '../browserContext';
|
||||
import type { BrowserWindow } from 'electron';
|
||||
import { Progress, ProgressController } from '../progress';
|
||||
import { helper } from '../helper';
|
||||
|
|
@ -37,6 +37,7 @@ import * as readline from 'readline';
|
|||
import { RecentLogsCollector } from '../../utils/debugLogger';
|
||||
import { internalCallMetadata, SdkObject } from '../instrumentation';
|
||||
import * as channels from '../../protocol/channels';
|
||||
import { BrowserContextOptions } from '../types';
|
||||
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
|
|
@ -69,6 +70,10 @@ export class ElectronApplication extends SdkObject {
|
|||
}
|
||||
});
|
||||
});
|
||||
this._browserContext.setCustomCloseHandler(async () => {
|
||||
const electronHandle = await this._nodeElectronHandlePromise;
|
||||
await electronHandle.evaluate(({ app }) => app.quit());
|
||||
});
|
||||
this._nodeSession.send('Runtime.enable', {}).catch(e => {});
|
||||
}
|
||||
|
||||
|
|
@ -79,8 +84,7 @@ export class ElectronApplication extends SdkObject {
|
|||
async close() {
|
||||
const progressController = new ProgressController(internalCallMetadata(), this);
|
||||
const closed = progressController.run(progress => helper.waitForEvent(progress, this, ElectronApplication.Events.Close).promise, this._timeoutSettings.timeout({}));
|
||||
const electronHandle = await this._nodeElectronHandlePromise;
|
||||
await electronHandle.evaluate(({ app }) => app.quit());
|
||||
await this._browserContext.close(internalCallMetadata());
|
||||
this._nodeConnection.close();
|
||||
await closed;
|
||||
}
|
||||
|
|
@ -168,26 +172,16 @@ export class Electron extends SdkObject {
|
|||
close: gracefullyClose,
|
||||
kill
|
||||
};
|
||||
const contextOptions: BrowserContextOptions = {
|
||||
...options,
|
||||
noDefaultViewport: true,
|
||||
};
|
||||
const browserOptions: BrowserOptions = {
|
||||
...this._playwrightOptions,
|
||||
name: 'electron',
|
||||
isChromium: true,
|
||||
headful: true,
|
||||
persistent: {
|
||||
noDefaultViewport: true,
|
||||
acceptDownloads: options.acceptDownloads,
|
||||
bypassCSP: options.bypassCSP,
|
||||
colorScheme: options.colorScheme,
|
||||
extraHTTPHeaders: options.extraHTTPHeaders,
|
||||
geolocation: options.geolocation,
|
||||
httpCredentials: options.httpCredentials,
|
||||
ignoreHTTPSErrors: options.ignoreHTTPSErrors,
|
||||
locale: options.locale,
|
||||
offline: options.offline,
|
||||
recordHar: options.recordHar,
|
||||
recordVideo: options.recordVideo,
|
||||
timezoneId: options.timezoneId,
|
||||
},
|
||||
persistent: contextOptions,
|
||||
browserProcess,
|
||||
protocolLogger: helper.debugProtocolLogger(),
|
||||
browserLogsCollector,
|
||||
|
|
@ -195,6 +189,7 @@ export class Electron extends SdkObject {
|
|||
downloadsPath: artifactsDir,
|
||||
tracesDir: artifactsDir,
|
||||
};
|
||||
validateBrowserContextOptions(contextOptions, browserOptions);
|
||||
const browser = await CRBrowser.connect(chromeTransport, browserOptions);
|
||||
app = new ElectronApplication(this, browser, nodeConnection);
|
||||
return app;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import type { BrowserWindow } from 'electron';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { electronTest as test, expect } from './electronTest';
|
||||
|
||||
test('should fire close event', async ({ playwright }) => {
|
||||
|
|
@ -166,3 +167,16 @@ test('should return same browser window for browser view pages', async ({ playwr
|
|||
expect(firstWindowId).toEqual(secondWindowId);
|
||||
await app.close();
|
||||
});
|
||||
|
||||
test('should record video', async ({ playwright }, testInfo) => {
|
||||
const app = await playwright._electron.launch({
|
||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
||||
recordVideo: { dir: testInfo.outputPath('video') }
|
||||
});
|
||||
const page = await app.firstWindow();
|
||||
await page.setContent(`<style>body {background:red}</style>`);
|
||||
await page.waitForTimeout(1000);
|
||||
await app.close();
|
||||
const videoPath = await page.video().path();
|
||||
expect(fs.statSync(videoPath).size).toBeGreaterThan(0);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ export const electronTest = baseTest.extend<ElectronTestFixtures, PageWorkerFixt
|
|||
await run(async () => {
|
||||
const [ window ] = await Promise.all([
|
||||
electronApp.waitForEvent('window'),
|
||||
electronApp.evaluate(electron => {
|
||||
electronApp.evaluate(async electron => {
|
||||
// Avoid "Error: Cannot create BrowserWindow before app is ready".
|
||||
await electron.app.whenReady();
|
||||
const window = new electron.BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
|
|
|
|||
Loading…
Reference in a new issue