Skip to content

Commit

Permalink
fix(electron): fix the directory app path
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman committed Dec 20, 2022
1 parent 971e304 commit ede0ac9
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 68 deletions.
8 changes: 7 additions & 1 deletion packages/playwright-core/src/client/electron.ts
Expand Up @@ -62,6 +62,7 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
readonly _context: BrowserContext;
private _windows = new Set<Page>();
private _timeoutSettings = new TimeoutSettings();
private _isClosed = false;

static from(electronApplication: channels.ElectronApplicationChannel): ElectronApplication {
return (electronApplication as any)._object;
Expand All @@ -73,7 +74,10 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
for (const page of this._context._pages)
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 {
Expand Down Expand Up @@ -102,6 +106,8 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
}

async close() {
if (this._isClosed)
return;
await this._channel.close();
}

Expand Down
9 changes: 8 additions & 1 deletion packages/playwright-core/src/server/electron/loader.ts
Expand Up @@ -15,6 +15,7 @@
*/

const { app } = require('electron');
const fs = require('fs');
const path = require('path');
const { chromiumSwitches } = require('../chromium/chromiumSwitches');

Expand Down Expand Up @@ -42,7 +43,13 @@ app.emit = (event: string | symbol, ...args: any[]): boolean => {
}
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 whenReadyCallback: (event: any) => any;
const whenReadyPromise = new Promise<void>(f => whenReadyCallback = f);
Expand Down
2 changes: 2 additions & 0 deletions tests/electron/electron-app-pre-ready-app.js
@@ -0,0 +1,2 @@
const { protocol } = require('electron');
protocol.registerSchemesAsPrivileged([]);
3 changes: 0 additions & 3 deletions tests/electron/electron-app.js
@@ -1,9 +1,6 @@
const { app, protocol } = require('electron');
const path = require('path');

// Test using pre-ready apis.
protocol.registerSchemesAsPrivileged([]);

app.on('window-all-closed', e => e.preventDefault());

app.whenReady().then(() => {
Expand Down
97 changes: 39 additions & 58 deletions tests/electron/electron-app.spec.ts
Expand Up @@ -19,10 +19,8 @@ import path from 'path';
import fs from 'fs';
import { electronTest as test, expect } from './electronTest';

test('should fire close event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-app.js')],
});
test('should fire close event', async ({ launchElectronApp }) => {
const electronApp = await launchElectronApp('electron-app.js');
const events = [];
electronApp.on('close', () => events.push('application'));
electronApp.context().on('close', () => events.push('context'));
Expand All @@ -33,22 +31,16 @@ test('should fire close event', async ({ playwright }) => {
expect(events.join('|')).toBe('context|application');
});

test('should dispatch ready event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-app-ready-event.js')],
});
try {
const events = await electronApp.evaluate(() => globalThis.__playwrightLog);
expect(events).toEqual([
'isReady == false',
'will-finish-launching fired',
'ready fired',
'whenReady resolved',
'isReady == true',
]);
} finally {
await electronApp.close();
}
test('should dispatch ready event', async ({ launchElectronApp }) => {
const electronApp = await launchElectronApp('electron-app-ready-event.js');
const events = await electronApp.evaluate(() => globalThis.__playwrightLog);
expect(events).toEqual([
'isReady == false',
'will-finish-launching fired',
'ready fired',
'whenReady resolved',
'isReady == true',
]);
});

test('should script application', async ({ electronApp }) => {
Expand Down Expand Up @@ -114,28 +106,19 @@ test('should have a clipboard instance', async ({ electronApp }) => {
expect(clipboardContentRead).toEqual(clipboardContentToWrite);
});

test('should test app that opens window fast', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
await electronApp.close();
test('should test app that opens window fast', async ({ launchElectronApp }) => {
await launchElectronApp('electron-window-app.js');
});

test('should return browser window', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
test('should return browser window', async ({ launchElectronApp }) => {
const electronApp = await launchElectronApp('electron-window-app.js');
const page = await electronApp.firstWindow();
const bwHandle = await electronApp.browserWindow(page);
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
await electronApp.close();
});

test('should bypass csp', async ({ playwright, server }) => {
const app = await playwright._electron.launch({
args: [require('path').join(__dirname, 'electron-app.js')],
bypassCSP: true,
});
test('should bypass csp', async ({ launchElectronApp, server }) => {
const app = await launchElectronApp('electron-app.js', { bypassCSP: true });
await app.evaluate(electron => {
const window = new electron.BrowserWindow({
width: 800,
Expand All @@ -147,13 +130,10 @@ test('should bypass csp', async ({ playwright, server }) => {
await page.goto(server.PREFIX + '/csp.html');
await page.addScriptTag({ content: 'window["__injected"] = 42;' });
expect(await page.evaluate('window["__injected"]')).toBe(42);
await app.close();
});

test('should create page for browser view', async ({ playwright }) => {
const app = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
test('should create page for browser view', async ({ launchElectronApp }) => {
const app = await launchElectronApp('electron-window-app.js');
await app.firstWindow();
await app.evaluate(async electron => {
const window = electron.BrowserWindow.getAllWindows()[0];
Expand All @@ -163,13 +143,10 @@ test('should create page for browser view', async ({ playwright }) => {
view.setBounds({ x: 0, y: 0, width: 256, height: 256 });
});
await expect.poll(() => app.windows().length).toBe(2);
await app.close();
});

test('should return same browser window for browser view pages', async ({ playwright }) => {
const app = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
test('should return same browser window for browser view pages', async ({ launchElectronApp }) => {
const app = await launchElectronApp('electron-window-app.js');
await app.firstWindow();
await app.evaluate(async electron => {
const window = electron.BrowserWindow.getAllWindows()[0];
Expand All @@ -187,12 +164,10 @@ 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')],
test('should record video', async ({ launchElectronApp }, testInfo) => {
const app = await launchElectronApp('electron-window-app.js', {
recordVideo: { dir: testInfo.outputPath('video') }
});
const page = await app.firstWindow();
Expand All @@ -203,25 +178,31 @@ test('should record video', async ({ playwright }, testInfo) => {
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' });

const app = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app-delayed-loadURL.js')],
});
const app = await launchElectronApp('electron-window-app-delayed-loadURL.js');
const page = await app.firstWindow();
await expect(page).toHaveURL('data:text/html,<h1>Foobar</h1>');
await expect(page.locator('h1')).toHaveText('Foobar');
await app.close();
});

test('should detach debugger on app-initiated exit', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-app.js')],
});
test('should detach debugger on app-initiated exit', async ({ launchElectronApp }) => {
const electronApp = await launchElectronApp('electron-app.js');
const closePromise = new Promise(f => electronApp.process().on('close', f));
await electronApp.evaluate(({ app }) => {
app.quit();
});
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();
});
18 changes: 13 additions & 5 deletions tests/electron/electronTest.ts
Expand Up @@ -26,6 +26,7 @@ import { assert } from 'playwright-core/lib/utils';

type ElectronTestFixtures = PageTestFixtures & {
electronApp: ElectronApplication;
launchElectronApp: (appFile: string, options?: any) => Promise<ElectronApplication>;
newWindow: () => Promise<Page>;
};

Expand All @@ -40,14 +41,21 @@ export const electronTest = baseTest.extend<TraceViewerFixtures>(traceViewerFixt
isElectron: [true, { scope: 'worker' }],
isWebView2: [false, { scope: 'worker' }],

electronApp: async ({ playwright }, run) => {
launchElectronApp: async ({ playwright }, use) => {
// This env prevents 'Electron Security Policy' console message.
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-app.js')],
const apps: ElectronApplication[] = [];
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);
await electronApp.close();
for (const app of apps)
await app.close();
},

electronApp: async ({ launchElectronApp }, use) => {
await use(await launchElectronApp('electron-app.js'));
},

newWindow: async ({ electronApp }, run) => {
Expand Down
1 change: 1 addition & 0 deletions tests/electron/index.js
@@ -0,0 +1 @@
require('electron');

0 comments on commit ede0ac9

Please sign in to comment.