test: migrate electron tests to new folio (#6043)

This commit is contained in:
Dmitry Gozman 2021-04-02 09:00:49 -07:00 committed by GitHub
parent 2357f0b562
commit 1444cc873a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 239 additions and 205 deletions

View file

@ -1,95 +0,0 @@
/**
* 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 path from 'path';
import { folio } from './electron.fixture';
const { it, expect, describe } = folio;
describe('electron app', (suite, { browserName }) => {
suite.skip(browserName !== 'chromium');
}, () => {
it('should fire close event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'testApp.js')],
});
const events = [];
electronApp.on('close', () => events.push('application'));
electronApp.context().on('close', () => events.push('context'));
await electronApp.close();
expect(events.join('|')).toBe('context|application');
// Give it some time to fire more events - there should not be any.
await new Promise(f => setTimeout(f, 1000));
expect(events.join('|')).toBe('context|application');
});
it('should script application', async ({ electronApp }) => {
const appPath = await electronApp.evaluate(async ({ app }) => app.getAppPath());
expect(appPath).toContain('electron');
});
it('should return windows', async ({ electronApp, newWindow }) => {
const window = await newWindow();
expect(electronApp.windows()).toEqual([window]);
});
it('should evaluate handle', async ({ electronApp }) => {
const appHandle = await electronApp.evaluateHandle(({ app }) => app);
expect(await electronApp.evaluate(({ app }, appHandle) => app === appHandle, appHandle)).toBeTruthy();
});
it('should route network', async ({ electronApp, newWindow }) => {
await electronApp.context().route('**/empty.html', (route, request) => {
route.fulfill({
status: 200,
contentType: 'text/html',
body: '<title>Hello World</title>',
});
});
const window = await newWindow();
await window.goto('https://localhost:1000/empty.html');
expect(await window.title()).toBe('Hello World');
});
it('should support init script', async ({ electronApp, newWindow }) => {
await electronApp.context().addInitScript('window.magic = 42;');
const window = await newWindow();
await window.goto('data:text/html,<script>window.copy = magic</script>');
expect(await window.evaluate(() => window['copy'])).toBe(42);
});
it('should expose function', async ({ electronApp, newWindow }) => {
await electronApp.context().exposeFunction('add', (a, b) => a + b);
const window = await newWindow();
await window.goto('data:text/html,<script>window["result"] = add(20, 22);</script>');
expect(await window.evaluate(() => window['result'])).toBe(42);
});
it('should wait for first window', async ({ electronApp }) => {
await electronApp.evaluate(({ BrowserWindow }) => {
const window = new BrowserWindow({ width: 800, height: 600 });
window.loadURL('data:text/html,<title>Hello World!</title>');
});
const window = await electronApp.firstWindow();
expect(await window.title()).toBe('Hello World!');
});
it('should have a clipboard instance', async ({ electronApp }) => {
const clipboardContentToWrite = 'Hello from Playwright';
await electronApp.evaluate(async ({clipboard}, text) => clipboard.writeText(text), clipboardContentToWrite);
const clipboardContentRead = await electronApp.evaluate(async ({clipboard}) => clipboard.readText());
expect(clipboardContentRead).toEqual(clipboardContentToWrite);
});
});

View file

@ -1,51 +0,0 @@
/**
* 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 { folio } from './electron.fixture';
const { it, expect, describe } = folio;
describe('electron window', (suite, { browserName }) => {
suite.skip(browserName !== 'chromium');
}, () => {
it('should click the button', async ({window, server}) => {
await window.goto(server.PREFIX + '/input/button.html');
await window.click('button');
expect(await window.evaluate('result')).toBe('Clicked');
});
it('should check the box', async ({window}) => {
await window.setContent(`<input id='checkbox' type='checkbox'></input>`);
await window.check('input');
expect(await window.evaluate('checkbox.checked')).toBe(true);
});
it('should not check the checked box', async ({window}) => {
await window.setContent(`<input id='checkbox' type='checkbox' checked></input>`);
await window.check('input');
expect(await window.evaluate('checkbox.checked')).toBe(true);
});
it('should type into a textarea', async ({window, server}) => {
await window.evaluate(() => {
const textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.focus();
});
const text = 'Hello world. I am the text that was typed!';
await window.keyboard.type(text);
expect(await window.evaluate(() => document.querySelector('textarea').value)).toBe(text);
});
});

View file

@ -1,58 +0,0 @@
/**
* Copyright Microsoft Corporation. All rights reserved.
*
* 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 { folio as base } from '../fixtures';
import path from 'path';
import { ElectronApplication, Page } from '../..';
type TestState = {
electronApp: ElectronApplication;
window: Page;
newWindow: () => Promise<Page>;
};
const fixtures = base.extend<TestState>();
fixtures.electronApp.init(async ({ playwright }, run) => {
const application = await playwright._electron.launch({
args: [path.join(__dirname, 'testApp.js')],
});
await run(application);
await application.close();
});
fixtures.newWindow.init(async ({ electronApp }, run) => {
const windows = [];
const newWindow = async () => {
const [ window ] = await Promise.all([
electronApp.waitForEvent('window'),
electronApp.evaluate(electron => {
const window = new electron.BrowserWindow({ width: 800, height: 600 });
window.loadURL('data:text/html,<title>Hello World 1</title>');
})
]);
windows.push(window);
return window;
};
await run(newWindow);
for (const window of windows)
await window.close();
});
fixtures.window.init(async ({ newWindow }, run) => {
await run(await newWindow());
});
export const folio = fixtures.build();

View file

@ -19,8 +19,10 @@ import * as path from 'path';
import { test as playwrightTest, slowTest as playwrightSlowTest } from './playwrightTest';
import { test as browserTest } from './browserTest';
import { test as pageTest } from './pageTest';
import { test as electronTest } from './electronTest';
import { PlaywrightEnv, BrowserEnv, PageEnv, BrowserName } from './browserEnv';
import { ServerEnv } from './serverEnv';
import { ElectronEnv } from './electronEnv';
const config: Config = {
testDir: path.join(__dirname, '..'),
@ -48,8 +50,9 @@ const serverEnv = new ServerEnv();
const browsers = ['chromium', 'webkit', 'firefox'] as BrowserName[];
for (const browserName of browsers) {
const executablePath = getExecutablePath(browserName);
const mode = (process.env.PWMODE || 'default') as ('default' | 'driver' | 'service');
const options = {
mode: (process.env.PWMODE || 'default') as ('default' | 'driver' | 'service'),
mode,
executablePath,
trace: !!process.env.PWTRACE,
headless: !process.env.HEADFUL,
@ -60,4 +63,6 @@ for (const browserName of browsers) {
playwrightSlowTest.runWith(browserName, serverEnv, new PlaywrightEnv(browserName, options), { timeout: config.timeout * 3 });
browserTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, options), {});
pageTest.runWith(browserName, serverEnv, new PageEnv(browserName, options), {});
if (browserName === 'chromium')
electronTest.runWith(browserName, serverEnv, new ElectronEnv({ mode }));
}

View file

@ -0,0 +1,65 @@
/**
* 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 type { Env, TestInfo } from '../folio/out';
import { PlaywrightEnv } from './browserEnv';
import * as path from 'path';
import { ElectronTestArgs } from './electronTest';
import { ElectronApplication, Page } from '../../index';
export class ElectronEnv extends PlaywrightEnv implements Env<ElectronTestArgs> {
private _electronApp: ElectronApplication | undefined;
private _windows: Page[] = [];
constructor(options: { mode: 'default' | 'driver' | 'service' }) {
super('chromium', options);
}
private async _newWindow() {
const [ window ] = await Promise.all([
this._electronApp!.waitForEvent('window'),
this._electronApp!.evaluate(electron => {
const window = new electron.BrowserWindow({ width: 800, height: 600 });
window.loadURL('data:text/html,<title>Hello World 1</title>');
})
]);
this._windows.push(window);
return window;
}
async beforeEach(testInfo: TestInfo) {
const result = await super.beforeEach(testInfo);
this._electronApp = await result.playwright._electron.launch({
args: [path.join(__dirname, 'electron-app.js')],
});
return {
...result,
electronApp: this._electronApp,
newWindow: this._newWindow.bind(this),
};
}
async afterEach(testInfo: TestInfo) {
for (const window of this._windows)
await window.close();
this._windows = [];
if (this._electronApp) {
await this._electronApp.close();
this._electronApp = undefined;
}
await super.afterEach(testInfo);
}
}

View file

@ -0,0 +1,28 @@
/**
* 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 { newTestType } from '../folio/out';
import { ElectronApplication, Page } from '../../index';
import type { CommonTestArgs } from './pageTest';
import type { ServerTestArgs } from './serverTest';
export { expect } from 'folio';
export type ElectronTestArgs = CommonTestArgs & {
electronApp: ElectronApplication;
newWindow: () => Promise<Page>;
};
export const test = newTestType<ElectronTestArgs & ServerTestArgs>();

View file

@ -0,0 +1,90 @@
/**
* 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 path from 'path';
import { test, expect } from '../config/electronTest';
test('should fire close event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, '..', 'config', 'electron-app.js')],
});
const events = [];
electronApp.on('close', () => events.push('application'));
electronApp.context().on('close', () => events.push('context'));
await electronApp.close();
expect(events.join('|')).toBe('context|application');
// Give it some time to fire more events - there should not be any.
await new Promise(f => setTimeout(f, 1000));
expect(events.join('|')).toBe('context|application');
});
test('should script application', async ({ electronApp }) => {
const appPath = await electronApp.evaluate(async ({ app }) => app.getAppPath());
expect(appPath).toBe(path.resolve(__dirname, '..', 'config'));
});
test('should return windows', async ({ electronApp, newWindow }) => {
const window = await newWindow();
expect(electronApp.windows()).toEqual([window]);
});
test('should evaluate handle', async ({ electronApp }) => {
const appHandle = await electronApp.evaluateHandle(({ app }) => app);
expect(await electronApp.evaluate(({ app }, appHandle) => app === appHandle, appHandle)).toBeTruthy();
});
test('should route network', async ({ electronApp, newWindow }) => {
await electronApp.context().route('**/empty.html', (route, request) => {
route.fulfill({
status: 200,
contentType: 'text/html',
body: '<title>Hello World</title>',
});
});
const window = await newWindow();
await window.goto('https://localhost:1000/empty.html');
expect(await window.title()).toBe('Hello World');
});
test('should support init script', async ({ electronApp, newWindow }) => {
await electronApp.context().addInitScript('window.magic = 42;');
const window = await newWindow();
await window.goto('data:text/html,<script>window.copy = magic</script>');
expect(await window.evaluate(() => window['copy'])).toBe(42);
});
test('should expose function', async ({ electronApp, newWindow }) => {
await electronApp.context().exposeFunction('add', (a, b) => a + b);
const window = await newWindow();
await window.goto('data:text/html,<script>window["result"] = add(20, 22);</script>');
expect(await window.evaluate(() => window['result'])).toBe(42);
});
test('should wait for first window', async ({ electronApp }) => {
await electronApp.evaluate(({ BrowserWindow }) => {
const window = new BrowserWindow({ width: 800, height: 600 });
window.loadURL('data:text/html,<title>Hello World!</title>');
});
const window = await electronApp.firstWindow();
expect(await window.title()).toBe('Hello World!');
});
test('should have a clipboard instance', async ({ electronApp }) => {
const clipboardContentToWrite = 'Hello from Playwright';
await electronApp.evaluate(async ({clipboard}, text) => clipboard.writeText(text), clipboardContentToWrite);
const clipboardContentRead = await electronApp.evaluate(async ({clipboard}) => clipboard.readText());
expect(clipboardContentRead).toEqual(clipboardContentToWrite);
});

View file

@ -0,0 +1,50 @@
/**
* 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 { test, expect } from '../config/electronTest';
test('should click the button', async ({newWindow, server}) => {
const window = await newWindow();
await window.goto(server.PREFIX + '/input/button.html');
await window.click('button');
expect(await window.evaluate('result')).toBe('Clicked');
});
test('should check the box', async ({newWindow}) => {
const window = await newWindow();
await window.setContent(`<input id='checkbox' type='checkbox'></input>`);
await window.check('input');
expect(await window.evaluate('checkbox.checked')).toBe(true);
});
test('should not check the checked box', async ({newWindow}) => {
const window = await newWindow();
await window.setContent(`<input id='checkbox' type='checkbox' checked></input>`);
await window.check('input');
expect(await window.evaluate('checkbox.checked')).toBe(true);
});
test('should type into a textarea', async ({newWindow}) => {
const window = await newWindow();
await window.evaluate(() => {
const textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.focus();
});
const text = 'Hello world. I am the text that was typed!';
await window.keyboard.type(text);
expect(await window.evaluate(() => document.querySelector('textarea').value)).toBe(text);
});