test: respect fixtures in describe, match image snapshots (#2989)

This commit is contained in:
Pavel Feldman 2020-07-16 22:38:52 -07:00 committed by GitHub
parent fe95ee00c3
commit 1c0504ae28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 56 additions and 43 deletions

View file

@ -204,8 +204,8 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
}
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 timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = new Waiter();
waiter.rejectOnTimeout(timeout, new TimeoutError(`Timeout while waiting for event "${event}"`));
if (event !== Events.BrowserContext.Close)

View file

@ -93,8 +93,8 @@ export class ElectronApplication extends ChannelOwner<ElectronApplicationChannel
}
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 timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = new Waiter();
waiter.rejectOnTimeout(timeout, new TimeoutError(`Timeout while waiting for event "${event}"`));
if (event !== ElectronEvents.ElectronApplication.Close)

View file

@ -332,8 +332,8 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
}
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 timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = new Waiter();
waiter.rejectOnTimeout(timeout, new TimeoutError(`Timeout while waiting for event "${event}"`));
if (event !== Events.Page.Crash)

View file

@ -20,13 +20,15 @@ import { BrowserType } from './browserType';
import { ChannelOwner } from './channelOwner';
import { Selectors } from './selectors';
import { Electron } from './electron';
import { TimeoutError } from '../../errors';
export class Playwright extends ChannelOwner<PlaywrightChannel, PlaywrightInitializer> {
chromium: BrowserType;
firefox: BrowserType;
webkit: BrowserType;
devices: types.Devices;
selectors: Selectors;
readonly chromium: BrowserType;
readonly firefox: BrowserType;
readonly webkit: BrowserType;
readonly devices: types.Devices;
readonly selectors: Selectors;
readonly errors: { TimeoutError: typeof TimeoutError };
constructor(parent: ChannelOwner, type: string, guid: string, initializer: PlaywrightInitializer) {
super(parent, type, guid, initializer);
@ -39,5 +41,6 @@ export class Playwright extends ChannelOwner<PlaywrightChannel, PlaywrightInitia
for (const { name, descriptor } of initializer.deviceDescriptors)
this.devices[name] = descriptor;
this.selectors = Selectors.from(initializer.selectors);
this.errors = { TimeoutError };
}
}

View file

@ -746,7 +746,7 @@ describe('Page.click', function() {
await page.click('button');
expect(await page.evaluate(() => window.result)).toBe(1);
});
it.skip(USES_HOOKS).fail(true)('should retarget when element is recycled during hit testing', async ({page, server}) => {
it.fail(true)('should retarget when element is recycled during hit testing', async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
await page.evaluate(() => {
renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })] ));
@ -760,7 +760,7 @@ describe('Page.click', function() {
expect(await page.evaluate(() => window.button1)).toBe(true);
expect(await page.evaluate(() => window.button2)).toBe(undefined);
});
it.skip(USES_HOOKS).fail(true)('should report that selector does not match anymore', async ({page, server}) => {
it.fail(true)('should report that selector does not match anymore', async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
await page.evaluate(() => {
renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })] ));
@ -778,7 +778,7 @@ describe('Page.click', function() {
expect(error.message).toContain('page.dblclick: Timeout 3000ms exceeded.');
expect(error.message).toContain('element does not match the selector anymore');
});
it.skip(USES_HOOKS).fail(true)('should retarget when element is recycled before enabled check', async ({page, server}) => {
it.fail(true)('should retarget when element is recycled before enabled check', async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
await page.evaluate(() => {
renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })] ));
@ -792,7 +792,7 @@ describe('Page.click', function() {
expect(await page.evaluate(() => window.button1)).toBe(true);
expect(await page.evaluate(() => window.button2)).toBe(undefined);
});
it.skip(USES_HOOKS).fail(true)('should not retarget the handle when element is recycled', async ({page, server}) => {
it.fail(true)('should not retarget the handle when element is recycled', async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
await page.evaluate(() => {
renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })] ));

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('./utils').testOptions(browserType);
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
describe('Page.Events.Dialog', function() {
it('should fire', async({page, server}) => {

View file

@ -15,7 +15,7 @@
*/
const utils = require('./utils');
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = utils.testOptions(browserType);
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
describe('Page.dispatchEvent(click)', function() {
it('should dispatch click event', async({page, server}) => {

View file

@ -16,16 +16,16 @@
const fs = require('fs');
const path = require('path');
const {FFOX, CHROMIUM, WEBKIT, MAC, WIN} = require('./utils').testOptions(browserType);
const {FFOX, CHROMIUM, WEBKIT, HEADLESS} = testOptions;
describe('Download', function() {
beforeEach(async(state) => {
state.server.setRoute('/download', (req, res) => {
beforeEach(async ({server}) => {
server.setRoute('/download', (req, res) => {
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment');
res.end(`Hello world`);
});
state.server.setRoute('/downloadWithFilename', (req, res) => {
server.setRoute('/downloadWithFilename', (req, res) => {
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename=file.txt');
res.end(`Hello world`);
@ -103,7 +103,7 @@ describe('Download', function() {
expect(fs.readFileSync(path).toString()).toBe('Hello world');
await page.close();
})
it.skip(FFOX).fail(WEBKIT)('should report alt-click downloads', async({browser, server}) => {
it.fail(FFOX || WEBKIT)('should report alt-click downloads', async({browser, server}) => {
// Firefox does not download on alt-click by default.
// Our WebKit embedder does not download on alt-click, although Safari does.
server.setRoute('/download', (req, res) => {

View file

@ -16,7 +16,7 @@
*/
const utils = require('./utils');
const {FFOX, CHROMIUM, WEBKIT, USES_HOOKS} = require('./utils').testOptions(browserType);
const {FFOX, HEADLESS} = testOptions;
describe('ElementHandle.boundingBox', function() {
it.fail(FFOX && !HEADLESS)('should work', async({page, server}) => {

View file

@ -16,7 +16,7 @@
*/
const utils = require('./utils');
const {FFOX, CHROMIUM, WEBKIT, LINUX} = utils.testOptions(browserType);
const {FFOX, HEADLESS} = testOptions;
describe('BrowserContext({viewport})', function() {
it('should get the proper default viewport size', async({page, server}) => {
@ -567,7 +567,7 @@ describe('focus', function() {
]);
expect(active).toEqual(['INPUT', 'TEXTAREA']);
});
it.skip(FFOX && !HEADLESS)('should not affect screenshots', async({page, server, golden}) => {
it.skip(FFOX && !HEADLESS)('should not affect screenshots', async({page, server}) => {
// Firefox headful produces a different image.
const page2 = await page.context().newPage();
await Promise.all([
@ -584,8 +584,8 @@ describe('focus', function() {
page.screenshot(),
page2.screenshot(),
]);
expect(screenshots[0]).toBeGolden(golden('screenshot-sanity.png'));
expect(screenshots[1]).toBeGolden(golden('grid-cell-0.png'));
expect(screenshots[0]).toMatchImageSnapshot('screenshot-sanity');
expect(screenshots[1]).toMatchImageSnapshot('grid-cell-0');
});
it('should change focused iframe', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
const {FFOX, CHROMIUM, LINUX, WEBKIT} = require('./utils').testOptions(browserType);
const {FFOX, CHROMIUM, LINUX, WEBKIT} = testOptions;
describe('Page.focus', function() {
it('should work', async function({page, server}) {

View file

@ -16,7 +16,7 @@
*/
const utils = require('./utils');
const {FFOX, CHROMIUM, WEBKIT} = utils.testOptions(browserType);
const {FFOX, CHROMIUM, WEBKIT} = testOptions;
describe('Frame.evaluateHandle', function() {
it('should work', async({page, server}) => {
@ -101,7 +101,7 @@ describe('Frame.evaluate', function() {
// Main world should work.
expect(await page.frames()[1].evaluate(() => window.location.href)).toBe('about:blank');
// Utility world should work.
expect(await page.frames()[1].$('div')).toBeTruthy(null);
expect(await page.frames()[1].$('div')).toBeTruthy();
});
it.fail(CHROMIUM)('should work in iframes that interrupted initial javascript url navigation', async({page, server}) => {
// Chromium does not report isolated world for the iframe.
@ -117,7 +117,7 @@ describe('Frame.evaluate', function() {
// Main world should work.
expect(await page.frames()[1].evaluate(() => window.top.location.href)).toBe(server.EMPTY_PAGE);
// Utility world should work.
expect(await page.frames()[1].$('div')).toBeTruthy(null);
expect(await page.frames()[1].$('div')).toBeTruthy();
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -26,7 +26,6 @@ const { PlaywrightDispatcher } = require('../../lib/rpc/server/playwrightDispatc
const { setUseApiName } = require('../../lib/progress');
module.exports = function registerFixtures(global) {
global.registerWorkerFixture('http_server', async ({}, test) => {
const assetsPath = path.join(__dirname, '..', 'assets');
const cachedPath = path.join(__dirname, '..', 'assets', 'cached');

View file

@ -16,10 +16,13 @@
const NodeEnvironment = require('jest-environment-node');
const registerFixtures = require('./fixtures');
const { toMatchImageSnapshot: jestImageSnapshot } = require('jest-image-snapshot');
const os = require('os');
const path = require('path');
const platform = os.platform();
const browserName = process.env.BROWSER || 'chromium';
class PlaywrightEnvironment extends NodeEnvironment {
constructor(config, context) {
super(config, context);
@ -28,9 +31,9 @@ class PlaywrightEnvironment extends NodeEnvironment {
testOptions.MAC = platform === 'darwin';
testOptions.LINUX = platform === 'linux';
testOptions.WIN = platform === 'win32';
testOptions.CHROMIUM = process.env.BROWSER === 'chromium' || !process.env.BROWSER;
testOptions.FFOX = process.env.BROWSER === 'firefox';
testOptions.WEBKIT = process.env.BROWSER === 'webkit';
testOptions.CHROMIUM = browserName === 'chromium';
testOptions.FFOX = browserName === 'firefox';
testOptions.WEBKIT = browserName === 'webkit';
testOptions.USES_HOOKS = process.env.PWCHANNEL === 'wire';
testOptions.CHANNEL = !!process.env.PWCHANNEL;
testOptions.HEADLESS = !!valueFromEnv('HEADLESS', true);
@ -60,6 +63,12 @@ class PlaywrightEnvironment extends NodeEnvironment {
async handleTestEvent(event, state) {
if (event.name === 'setup') {
const beforeEach = this.global.beforeEach;
this.global.beforeEach = fn => {
return beforeEach(async () => {
return await this.fixturePool.resolveParametersAndRun(fn);
});
}
const describeSkip = this.global.describe.skip;
this.global.describe.skip = (...args) => {
if (args.length = 1)
@ -76,6 +85,15 @@ class PlaywrightEnvironment extends NodeEnvironment {
};
this.global.it.fail = this.global.it.skip;
this.global.it.slow = () => this.global.it;
function toMatchImageSnapshot(received, fileName) {
return jestImageSnapshot.call(this, received, {
customDiffConfig: { threshold: 0.2 },
customSnapshotsDir: path.join(__dirname, '..', `golden-${browserName}`),
customSnapshotIdentifier: fileName
});
};
this.global.expect.extend({ toMatchImageSnapshot });
}
if (event.name === 'test_start') {
const fn = event.test.fn;

View file

@ -71,13 +71,6 @@ module.exports = {
specs: [
{
files: [
'./dialog.spec.js',
'./dispatchevent.spec.js',
'./download.spec.js',
'./elementhandle.spec.js',
'./emulation.spec.js',
'./frame.spec.js',
'./focus.spec.js',
'./input.spec.js',
'./jshandle.spec.js',
'./keyboard.spec.ts',