fix(electron): fix the directory app path (#19601)
This commit is contained in:
parent
51782cfa5d
commit
95cc5c2a2e
|
|
@ -62,6 +62,7 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
||||||
readonly _context: BrowserContext;
|
readonly _context: BrowserContext;
|
||||||
private _windows = new Set<Page>();
|
private _windows = new Set<Page>();
|
||||||
private _timeoutSettings = new TimeoutSettings();
|
private _timeoutSettings = new TimeoutSettings();
|
||||||
|
private _isClosed = false;
|
||||||
|
|
||||||
static from(electronApplication: channels.ElectronApplicationChannel): ElectronApplication {
|
static from(electronApplication: channels.ElectronApplicationChannel): ElectronApplication {
|
||||||
return (electronApplication as any)._object;
|
return (electronApplication as any)._object;
|
||||||
|
|
@ -73,7 +74,10 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
||||||
for (const page of this._context._pages)
|
for (const page of this._context._pages)
|
||||||
this._onPage(page);
|
this._onPage(page);
|
||||||
this._context.on(Events.BrowserContext.Page, page => this._onPage(page));
|
this._context.on(Events.BrowserContext.Page, page => this._onPage(page));
|
||||||
this._channel.on('close', () => this.emit(Events.ElectronApplication.Close));
|
this._channel.on('close', () => {
|
||||||
|
this._isClosed = true;
|
||||||
|
this.emit(Events.ElectronApplication.Close);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
process(): childProcess.ChildProcess {
|
process(): childProcess.ChildProcess {
|
||||||
|
|
@ -102,6 +106,8 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
|
if (this._isClosed)
|
||||||
|
return;
|
||||||
await this._channel.close();
|
await this._channel.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { app } = require('electron');
|
const { app } = require('electron');
|
||||||
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { chromiumSwitches } = require('../chromium/chromiumSwitches');
|
const { chromiumSwitches } = require('../chromium/chromiumSwitches');
|
||||||
|
|
||||||
|
|
@ -42,7 +43,13 @@ app.emit = (event: string | symbol, ...args: any[]): boolean => {
|
||||||
}
|
}
|
||||||
return originalEmit(event, ...args);
|
return originalEmit(event, ...args);
|
||||||
};
|
};
|
||||||
app.getAppPath = () => path.dirname(appPath);
|
|
||||||
|
app.getAppPath = () => {
|
||||||
|
if (fs.statSync(appPath).isFile())
|
||||||
|
return path.dirname(appPath);
|
||||||
|
return appPath;
|
||||||
|
};
|
||||||
|
|
||||||
let isReady = false;
|
let isReady = false;
|
||||||
let whenReadyCallback: (event: any) => any;
|
let whenReadyCallback: (event: any) => any;
|
||||||
const whenReadyPromise = new Promise<void>(f => whenReadyCallback = f);
|
const whenReadyPromise = new Promise<void>(f => whenReadyCallback = f);
|
||||||
|
|
|
||||||
2
tests/electron/electron-app-pre-ready-app.js
Normal file
2
tests/electron/electron-app-pre-ready-app.js
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
const { protocol } = require('electron');
|
||||||
|
protocol.registerSchemesAsPrivileged([]);
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
const { app, protocol } = require('electron');
|
const { app, protocol } = require('electron');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
// Test using pre-ready apis.
|
|
||||||
protocol.registerSchemesAsPrivileged([]);
|
|
||||||
|
|
||||||
app.on('window-all-closed', e => e.preventDefault());
|
app.on('window-all-closed', e => e.preventDefault());
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,8 @@ import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { electronTest as test, expect } from './electronTest';
|
import { electronTest as test, expect } from './electronTest';
|
||||||
|
|
||||||
test('should fire close event', async ({ playwright }) => {
|
test('should fire close event', async ({ launchElectronApp }) => {
|
||||||
const electronApp = await playwright._electron.launch({
|
const electronApp = await launchElectronApp('electron-app.js');
|
||||||
args: [path.join(__dirname, 'electron-app.js')],
|
|
||||||
});
|
|
||||||
const events = [];
|
const events = [];
|
||||||
electronApp.on('close', () => events.push('application'));
|
electronApp.on('close', () => events.push('application'));
|
||||||
electronApp.context().on('close', () => events.push('context'));
|
electronApp.context().on('close', () => events.push('context'));
|
||||||
|
|
@ -33,11 +31,8 @@ test('should fire close event', async ({ playwright }) => {
|
||||||
expect(events.join('|')).toBe('context|application');
|
expect(events.join('|')).toBe('context|application');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should dispatch ready event', async ({ playwright }) => {
|
test('should dispatch ready event', async ({ launchElectronApp }) => {
|
||||||
const electronApp = await playwright._electron.launch({
|
const electronApp = await launchElectronApp('electron-app-ready-event.js');
|
||||||
args: [path.join(__dirname, 'electron-app-ready-event.js')],
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
const events = await electronApp.evaluate(() => globalThis.__playwrightLog);
|
const events = await electronApp.evaluate(() => globalThis.__playwrightLog);
|
||||||
expect(events).toEqual([
|
expect(events).toEqual([
|
||||||
'isReady == false',
|
'isReady == false',
|
||||||
|
|
@ -46,9 +41,6 @@ test('should dispatch ready event', async ({ playwright }) => {
|
||||||
'whenReady resolved',
|
'whenReady resolved',
|
||||||
'isReady == true',
|
'isReady == true',
|
||||||
]);
|
]);
|
||||||
} finally {
|
|
||||||
await electronApp.close();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should script application', async ({ electronApp }) => {
|
test('should script application', async ({ electronApp }) => {
|
||||||
|
|
@ -114,28 +106,19 @@ test('should have a clipboard instance', async ({ electronApp }) => {
|
||||||
expect(clipboardContentRead).toEqual(clipboardContentToWrite);
|
expect(clipboardContentRead).toEqual(clipboardContentToWrite);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should test app that opens window fast', async ({ playwright }) => {
|
test('should test app that opens window fast', async ({ launchElectronApp }) => {
|
||||||
const electronApp = await playwright._electron.launch({
|
await launchElectronApp('electron-window-app.js');
|
||||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
|
||||||
});
|
|
||||||
await electronApp.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return browser window', async ({ playwright }) => {
|
test('should return browser window', async ({ launchElectronApp }) => {
|
||||||
const electronApp = await playwright._electron.launch({
|
const electronApp = await launchElectronApp('electron-window-app.js');
|
||||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
|
||||||
});
|
|
||||||
const page = await electronApp.firstWindow();
|
const page = await electronApp.firstWindow();
|
||||||
const bwHandle = await electronApp.browserWindow(page);
|
const bwHandle = await electronApp.browserWindow(page);
|
||||||
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
|
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
|
||||||
await electronApp.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should bypass csp', async ({ playwright, server }) => {
|
test('should bypass csp', async ({ launchElectronApp, server }) => {
|
||||||
const app = await playwright._electron.launch({
|
const app = await launchElectronApp('electron-app.js', { bypassCSP: true });
|
||||||
args: [require('path').join(__dirname, 'electron-app.js')],
|
|
||||||
bypassCSP: true,
|
|
||||||
});
|
|
||||||
await app.evaluate(electron => {
|
await app.evaluate(electron => {
|
||||||
const window = new electron.BrowserWindow({
|
const window = new electron.BrowserWindow({
|
||||||
width: 800,
|
width: 800,
|
||||||
|
|
@ -147,13 +130,10 @@ test('should bypass csp', async ({ playwright, server }) => {
|
||||||
await page.goto(server.PREFIX + '/csp.html');
|
await page.goto(server.PREFIX + '/csp.html');
|
||||||
await page.addScriptTag({ content: 'window["__injected"] = 42;' });
|
await page.addScriptTag({ content: 'window["__injected"] = 42;' });
|
||||||
expect(await page.evaluate('window["__injected"]')).toBe(42);
|
expect(await page.evaluate('window["__injected"]')).toBe(42);
|
||||||
await app.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create page for browser view', async ({ playwright }) => {
|
test('should create page for browser view', async ({ launchElectronApp }) => {
|
||||||
const app = await playwright._electron.launch({
|
const app = await launchElectronApp('electron-window-app.js');
|
||||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
|
||||||
});
|
|
||||||
await app.firstWindow();
|
await app.firstWindow();
|
||||||
await app.evaluate(async electron => {
|
await app.evaluate(async electron => {
|
||||||
const window = electron.BrowserWindow.getAllWindows()[0];
|
const window = electron.BrowserWindow.getAllWindows()[0];
|
||||||
|
|
@ -163,13 +143,10 @@ test('should create page for browser view', async ({ playwright }) => {
|
||||||
view.setBounds({ x: 0, y: 0, width: 256, height: 256 });
|
view.setBounds({ x: 0, y: 0, width: 256, height: 256 });
|
||||||
});
|
});
|
||||||
await expect.poll(() => app.windows().length).toBe(2);
|
await expect.poll(() => app.windows().length).toBe(2);
|
||||||
await app.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return same browser window for browser view pages', async ({ playwright }) => {
|
test('should return same browser window for browser view pages', async ({ launchElectronApp }) => {
|
||||||
const app = await playwright._electron.launch({
|
const app = await launchElectronApp('electron-window-app.js');
|
||||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
|
||||||
});
|
|
||||||
await app.firstWindow();
|
await app.firstWindow();
|
||||||
await app.evaluate(async electron => {
|
await app.evaluate(async electron => {
|
||||||
const window = electron.BrowserWindow.getAllWindows()[0];
|
const window = electron.BrowserWindow.getAllWindows()[0];
|
||||||
|
|
@ -187,12 +164,10 @@ test('should return same browser window for browser view pages', async ({ playwr
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(firstWindowId).toEqual(secondWindowId);
|
expect(firstWindowId).toEqual(secondWindowId);
|
||||||
await app.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should record video', async ({ playwright }, testInfo) => {
|
test('should record video', async ({ launchElectronApp }, testInfo) => {
|
||||||
const app = await playwright._electron.launch({
|
const app = await launchElectronApp('electron-window-app.js', {
|
||||||
args: [path.join(__dirname, 'electron-window-app.js')],
|
|
||||||
recordVideo: { dir: testInfo.outputPath('video') }
|
recordVideo: { dir: testInfo.outputPath('video') }
|
||||||
});
|
});
|
||||||
const page = await app.firstWindow();
|
const page = await app.firstWindow();
|
||||||
|
|
@ -203,25 +178,31 @@ test('should record video', async ({ playwright }, testInfo) => {
|
||||||
expect(fs.statSync(videoPath).size).toBeGreaterThan(0);
|
expect(fs.statSync(videoPath).size).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should be able to get the first window when with a delayed navigation', async ({ playwright }) => {
|
test('should be able to get the first window when with a delayed navigation', async ({ launchElectronApp }) => {
|
||||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/17765' });
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/17765' });
|
||||||
|
|
||||||
const app = await playwright._electron.launch({
|
const app = await launchElectronApp('electron-window-app-delayed-loadURL.js');
|
||||||
args: [path.join(__dirname, 'electron-window-app-delayed-loadURL.js')],
|
|
||||||
});
|
|
||||||
const page = await app.firstWindow();
|
const page = await app.firstWindow();
|
||||||
await expect(page).toHaveURL('data:text/html,<h1>Foobar</h1>');
|
await expect(page).toHaveURL('data:text/html,<h1>Foobar</h1>');
|
||||||
await expect(page.locator('h1')).toHaveText('Foobar');
|
await expect(page.locator('h1')).toHaveText('Foobar');
|
||||||
await app.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should detach debugger on app-initiated exit', async ({ playwright }) => {
|
test('should detach debugger on app-initiated exit', async ({ launchElectronApp }) => {
|
||||||
const electronApp = await playwright._electron.launch({
|
const electronApp = await launchElectronApp('electron-app.js');
|
||||||
args: [path.join(__dirname, 'electron-app.js')],
|
|
||||||
});
|
|
||||||
const closePromise = new Promise(f => electronApp.process().on('close', f));
|
const closePromise = new Promise(f => electronApp.process().on('close', f));
|
||||||
await electronApp.evaluate(({ app }) => {
|
await electronApp.evaluate(({ app }) => {
|
||||||
app.quit();
|
app.quit();
|
||||||
});
|
});
|
||||||
await closePromise;
|
await closePromise;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should run pre-ready apis', async ({ launchElectronApp }) => {
|
||||||
|
await launchElectronApp('electron-pre-ready-app.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should resolve app path for folder apps', async ({ launchElectronApp }) => {
|
||||||
|
const electronApp = await launchElectronApp('.');
|
||||||
|
const appPath = await electronApp.evaluate(async ({ app }) => app.getAppPath());
|
||||||
|
expect(appPath).toBe(path.resolve(__dirname));
|
||||||
|
await electronApp.close();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import { assert } from 'playwright-core/lib/utils';
|
||||||
|
|
||||||
type ElectronTestFixtures = PageTestFixtures & {
|
type ElectronTestFixtures = PageTestFixtures & {
|
||||||
electronApp: ElectronApplication;
|
electronApp: ElectronApplication;
|
||||||
|
launchElectronApp: (appFile: string, options?: any) => Promise<ElectronApplication>;
|
||||||
newWindow: () => Promise<Page>;
|
newWindow: () => Promise<Page>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -40,14 +41,21 @@ export const electronTest = baseTest.extend<TraceViewerFixtures>(traceViewerFixt
|
||||||
isElectron: [true, { scope: 'worker' }],
|
isElectron: [true, { scope: 'worker' }],
|
||||||
isWebView2: [false, { scope: 'worker' }],
|
isWebView2: [false, { scope: 'worker' }],
|
||||||
|
|
||||||
electronApp: async ({ playwright }, run) => {
|
launchElectronApp: async ({ playwright }, use) => {
|
||||||
// This env prevents 'Electron Security Policy' console message.
|
// This env prevents 'Electron Security Policy' console message.
|
||||||
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
|
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
|
||||||
const electronApp = await playwright._electron.launch({
|
const apps: ElectronApplication[] = [];
|
||||||
args: [path.join(__dirname, 'electron-app.js')],
|
await use(async (appFile: string, options?: any[]) => {
|
||||||
|
const app = await playwright._electron.launch({ ...options, args: [path.join(__dirname, appFile)] });
|
||||||
|
apps.push(app);
|
||||||
|
return app;
|
||||||
});
|
});
|
||||||
await run(electronApp);
|
for (const app of apps)
|
||||||
await electronApp.close();
|
await app.close();
|
||||||
|
},
|
||||||
|
|
||||||
|
electronApp: async ({ launchElectronApp }, use) => {
|
||||||
|
await use(await launchElectronApp('electron-app.js'));
|
||||||
},
|
},
|
||||||
|
|
||||||
newWindow: async ({ electronApp }, run) => {
|
newWindow: async ({ electronApp }, run) => {
|
||||||
|
|
|
||||||
1
tests/electron/index.js
Normal file
1
tests/electron/index.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
require('electron');
|
||||||
Loading…
Reference in a new issue