chore: roll test runner to 0.3.9 (#3847)

This commit is contained in:
Pavel Feldman 2020-09-11 10:02:07 -07:00 committed by GitHub
parent 38ed8de23d
commit f94df318d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
77 changed files with 446 additions and 441 deletions

12
package-lock.json generated
View file

@ -1168,9 +1168,9 @@
}
},
"@playwright/test-runner": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@playwright/test-runner/-/test-runner-0.3.5.tgz",
"integrity": "sha512-G/X9fjqr4ZOyZojQpKAlid7KC8Bw+S834KxSD9nQSqLaN8QFpebFr9xqVhEs/G82RP8DRzxlp8vi5CqLhGrU0w==",
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@playwright/test-runner/-/test-runner-0.3.9.tgz",
"integrity": "sha512-+kFADjH/g7GQ4uXzCJ5/1ke79n2WCnwRsccbrRgCYcUW96/r97FQnywfYZjJnPcTbvJf4DqYBZ2/0wS7pAEmvQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
@ -3050,9 +3050,9 @@
}
},
"electron-to-chromium": {
"version": "1.3.564",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz",
"integrity": "sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==",
"version": "1.3.565",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.565.tgz",
"integrity": "sha512-me5dGlHFd8Q7mKhqbWRLIYnKjw4i0fO6hmW0JBxa7tM87fBfNEjWokRnDF7V+Qme/9IYpwhfMn+soWs40tXWqg==",
"dev": true
},
"elliptic": {

View file

@ -49,7 +49,7 @@
"ws": "^7.3.1"
},
"devDependencies": {
"@playwright/test-runner": "^0.3.5",
"@playwright/test-runner": "^0.3.9",
"@types/debug": "^4.1.5",
"@types/extract-zip": "^1.6.2",
"@types/mime": "^2.0.3",

View file

@ -17,7 +17,7 @@
import { it, expect, describe, options } from './playwright.fixtures';
it('should work', async function({page}) {
it('should work', async ({ page, isFirefox, isChromium }) => {
await page.setContent(`
<head>
<title>Accessibility Test</title>
@ -36,7 +36,7 @@ it('should work', async function({page}) {
// autofocus happens after a delay in chrome these days
await page.waitForFunction(() => document.activeElement.hasAttribute('autofocus'));
const golden = options.FIREFOX ? {
const golden = isFirefox ? {
role: 'document',
name: 'Accessibility Test',
children: [
@ -49,7 +49,7 @@ it('should work', async function({page}) {
{role: 'textbox', name: '', value: 'and a value'}, // firefox doesn't use aria-placeholder for the name
{role: 'textbox', name: '', value: 'and a value', description: 'This is a description!'}, // and here
]
} : options.CHROMIUM ? {
} : isChromium ? {
role: 'WebArea',
name: 'Accessibility Test',
children: [
@ -79,11 +79,11 @@ it('should work', async function({page}) {
expect(await page.accessibility.snapshot()).toEqual(golden);
});
it('should work with regular text', async ({page}) => {
it('should work with regular text', async ({page, isFirefox}) => {
await page.setContent(`<div>Hello World</div>`);
const snapshot = await page.accessibility.snapshot();
expect(snapshot.children[0]).toEqual({
role: options.FIREFOX ? 'text leaf' : 'text',
role: isFirefox ? 'text leaf' : 'text',
name: 'Hello World',
});
});
@ -118,14 +118,14 @@ it('keyshortcuts', async ({page}) => {
expect(snapshot.children[0].keyshortcuts).toEqual('foo');
});
it('should not report text nodes inside controls', async function({page}) {
it('should not report text nodes inside controls', async function({page, isFirefox}) {
await page.setContent(`
<div role="tablist">
<div role="tab" aria-selected="true"><b>Tab1</b></div>
<div role="tab">Tab2</div>
</div>`);
const golden = {
role: options.FIREFOX ? 'document' : 'WebArea',
role: isFirefox ? 'document' : 'WebArea',
name: '',
children: [{
role: 'tab',
@ -139,14 +139,14 @@ it('should not report text nodes inside controls', async function({page}) {
expect(await page.accessibility.snapshot()).toEqual(golden);
});
it('rich text editable fields should have children', test => {
test.skip(options.WEBKIT, 'WebKit rich text accessibility is iffy');
}, async function({page}) {
it('rich text editable fields should have children', (test, parameters) => {
test.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy');
}, async function({page, isFirefox}) {
await page.setContent(`
<div contenteditable="true">
Edit this image: <img src="fakeimage.png" alt="my fake image">
</div>`);
const golden = options.FIREFOX ? {
const golden = isFirefox ? {
role: 'section',
name: '',
children: [{
@ -172,14 +172,14 @@ it('rich text editable fields should have children', test => {
expect(snapshot.children[0]).toEqual(golden);
});
it('rich text editable fields with role should have children', test => {
test.skip(options.WEBKIT, 'WebKit rich text accessibility is iffy');
}, async function({page}) {
it('rich text editable fields with role should have children', (test, parameters) => {
test.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy');
}, async function({page, isFirefox}) {
await page.setContent(`
<div contenteditable="true" role='textbox'>
Edit this image: <img src="fakeimage.png" alt="my fake image">
</div>`);
const golden = options.FIREFOX ? {
const golden = isFirefox ? {
role: 'textbox',
name: '',
value: 'Edit this image: my fake image',
@ -203,9 +203,9 @@ it('rich text editable fields with role should have children', test => {
expect(snapshot.children[0]).toEqual(golden);
});
describe('contenteditable', suite => {
suite.skip(options.FIREFOX, 'Firefox does not support contenteditable="plaintext-only"');
suite.skip(options.WEBKIT, 'WebKit rich text accessibility is iffy');
describe('contenteditable', (suite, parameters) => {
suite.skip(options.FIREFOX(parameters), 'Firefox does not support contenteditable="plaintext-only"');
suite.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy');
}, () => {
it('plain text field with role should not have children', async function({page}) {
await page.setContent(`
@ -239,17 +239,17 @@ describe('contenteditable', suite => {
});
});
it('non editable textbox with role and tabIndex and label should not have children', async function({page}) {
it('non editable textbox with role and tabIndex and label should not have children', async function({page, isChromium, isFirefox}) {
await page.setContent(`
<div role="textbox" tabIndex=0 aria-checked="true" aria-label="my favorite textbox">
this is the inner content
<img alt="yo" src="fakeimg.png">
</div>`);
const golden = options.FIREFOX ? {
const golden = isFirefox ? {
role: 'textbox',
name: 'my favorite textbox',
value: 'this is the inner content yo'
} : options.CHROMIUM ? {
} : isChromium ? {
role: 'textbox',
name: 'my favorite textbox',
value: 'this is the inner content '
@ -277,13 +277,13 @@ it('checkbox with and tabIndex and label should not have children', async functi
expect(snapshot.children[0]).toEqual(golden);
});
it('checkbox without label should not have children', async function({page}) {
it('checkbox without label should not have children', async ({page, isFirefox}) => {
await page.setContent(`
<div role="checkbox" aria-checked="true">
this is the inner content
<img alt="yo" src="fakeimg.png">
</div>`);
const golden = options.FIREFOX ? {
const golden = isFirefox ? {
role: 'checkbox',
name: 'this is the inner content yo',
checked: true
@ -317,7 +317,7 @@ it('should work an input', async ({page}) => {
});
});
it('should work on a menu', async ({page}) => {
it('should work on a menu', async ({page, isWebKit}) => {
await page.setContent(`
<div role="menu" title="My Menu">
<div role="menuitem">First Item</div>
@ -334,7 +334,7 @@ it('should work on a menu', async ({page}) => {
[ { role: 'menuitem', name: 'First Item' },
{ role: 'menuitem', name: 'Second Item' },
{ role: 'menuitem', name: 'Third Item' } ],
orientation: options.WEBKIT ? 'vertical' : undefined
orientation: isWebKit ? 'vertical' : undefined
});
});

View file

@ -201,7 +201,7 @@ it('should work with goto following click', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);
});
it('should report navigation in the log when clicking anchor', test => {
it('should report navigation in the log when clicking anchor', (test, parameters) => {
test.skip(options.WIRE);
}, async ({page, server}) => {
await page.setContent(`<a href="${server.PREFIX + '/frames/one-frame.html'}">click me</a>`);

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should create new page', async function({browser}) {
const page1 = await browser.newPage();
@ -38,9 +38,9 @@ it('should throw upon second create new page', async function({browser}) {
expect(error.message).toContain('Please use browser.newContext()');
});
it('version should work', async function({browser}) {
it('version should work', async function({browser, isChromium}) {
const version = browser.version();
if (options.CHROMIUM)
if (isChromium)
expect(version.match(/^\d+\.\d+\.\d+\.\d+$/)).toBeTruthy();
else
expect(version.match(/^\d+\.\d+/)).toBeTruthy();

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should work', async ({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
@ -139,7 +139,7 @@ it('should isolate send cookie header', async ({server, context, browser}) => {
}
});
it('should isolate cookies between launches', test => {
it('should isolate cookies between launches', (test, parameters) => {
test.slow();
}, async ({browserType, server, defaultBrowserOptions}) => {
const browser1 = await browserType.launch(defaultBrowserOptions);
@ -315,7 +315,7 @@ it('should set cookies for a frame', async ({context, page, server}) => {
expect(await page.frames()[1].evaluate('document.cookie')).toBe('frame-cookie=value');
});
it('should(not) block third party cookies', async ({context, page, server}) => {
it('should(not) block third party cookies', async ({context, page, server, isChromium, isFirefox}) => {
await page.goto(server.EMPTY_PAGE);
await page.evaluate(src => {
let fulfill;
@ -328,7 +328,7 @@ it('should(not) block third party cookies', async ({context, page, server}) => {
}, server.CROSS_PROCESS_PREFIX + '/grid.html');
await page.frames()[1].evaluate(`document.cookie = 'username=John Doe'`);
await page.waitForTimeout(2000);
const allowsThirdParty = options.CHROMIUM || options.FIREFOX;
const allowsThirdParty = isChromium || isFirefox;
const cookies = await context.cookies(server.CROSS_PROCESS_PREFIX + '/grid.html');
if (allowsThirdParty) {
expect(cookies).toEqual([

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
import utils from './utils';
@ -178,14 +178,14 @@ it('should close all belonging pages once closing context', async function({brow
expect(context.pages().length).toBe(0);
});
it('should disable javascript', async ({browser}) => {
it('should disable javascript', async ({browser, isWebKit}) => {
{
const context = await browser.newContext({ javaScriptEnabled: false });
const page = await context.newPage();
await page.goto('data:text/html, <script>var something = "forbidden"</script>');
let error = null;
await page.evaluate('something').catch(e => error = e);
if (options.WEBKIT)
if (isWebKit)
expect(error.message).toContain('Can\'t find variable: something');
else
expect(error.message).toContain('something is not defined');

View file

@ -73,8 +73,8 @@ it('should properly report httpOnly cookie', async ({context, page, server}) =>
expect(cookies[0].httpOnly).toBe(true);
});
it('should properly report "Strict" sameSite cookie', test => {
test.fail(options.WEBKIT && WIN);
it('should properly report "Strict" sameSite cookie', (test, parameters) => {
test.fail(options.WEBKIT(parameters) && WIN);
}, async ({context, page, server}) => {
server.setRoute('/empty.html', (req, res) => {
res.setHeader('Set-Cookie', 'name=value;SameSite=Strict');
@ -86,8 +86,8 @@ it('should properly report "Strict" sameSite cookie', test => {
expect(cookies[0].sameSite).toBe('Strict');
});
it('should properly report "Lax" sameSite cookie', test => {
test.fail(options.WEBKIT && WIN);
it('should properly report "Lax" sameSite cookie', (test, parameters) => {
test.fail(options.WEBKIT(parameters) && WIN);
}, async ({context, page, server}) => {
server.setRoute('/empty.html', (req, res) => {
res.setHeader('Set-Cookie', 'name=value;SameSite=Lax');

View file

@ -17,8 +17,8 @@
import { it, expect, options } from './playwright.fixtures';
it('should fail without credentials', test => {
test.fail(options.CHROMIUM && !options.HEADLESS);
it('should fail without credentials', (test, parameters) => {
test.fail(options.CHROMIUM(parameters) && !options.HEADLESS);
}, async ({browser, server}) => {
server.setAuth('/empty.html', 'user', 'pass');
const context = await browser.newContext();
@ -28,8 +28,8 @@ it('should fail without credentials', test => {
await context.close();
});
it('should work with setHTTPCredentials', test => {
test.fail(options.CHROMIUM && !options.HEADLESS);
it('should work with setHTTPCredentials', (test, parameters) => {
test.fail(options.CHROMIUM(parameters) && !options.HEADLESS);
}, async ({browser, server}) => {
server.setAuth('/empty.html', 'user', 'pass');
const context = await browser.newContext();

View file

@ -17,8 +17,8 @@
import { it, expect, describe, options } from './playwright.fixtures';
describe('device', suite => {
suite.skip(options.FIREFOX);
describe('device', (suite, parameters) => {
suite.skip(options.FIREFOX(parameters));
}, () => {
it('should work', async ({playwright, browser, server}) => {
const iPhone = playwright.devices['iPhone 6'];

View file

@ -157,8 +157,8 @@ it('should fire page lifecycle events', async function({browser, server}) {
await context.close();
});
it('should work with Shift-clicking', test => {
test.fixme(options.WEBKIT, 'WebKit: Shift+Click does not open a new window.');
it('should work with Shift-clicking', (test, parameters) => {
test.fixme(options.WEBKIT(parameters), 'WebKit: Shift+Click does not open a new window.');
}, async ({browser, server}) => {
const context = await browser.newContext();
const page = await context.newPage();
@ -172,9 +172,9 @@ it('should work with Shift-clicking', test => {
await context.close();
});
it('should work with Ctrl-clicking', test => {
test.fixme(options.WEBKIT, 'Ctrl+Click does not open a new tab.');
test.fixme(options.FIREFOX, 'Reports an opener in this case.');
it('should work with Ctrl-clicking', (test, parameters) => {
test.fixme(options.WEBKIT(parameters), 'Ctrl+Click does not open a new tab.');
test.fixme(options.FIREFOX(parameters), 'Reports an opener in this case.');
}, async ({browser, server}) => {
const context = await browser.newContext();
const page = await context.newPage();

View file

@ -17,8 +17,8 @@
import { it, expect, describe, options } from './playwright.fixtures';
describe('mobile viewport', suite => {
suite.skip(options.FIREFOX);
describe('mobile viewport', (suite, parameters) => {
suite.skip(options.FIREFOX(parameters));
}, () => {
it('should support mobile emulation', async ({playwright, browser, server}) => {
const iPhone = playwright.devices['iPhone 6'];

View file

@ -16,7 +16,7 @@
*/
import fs from 'fs';
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('browserType.executablePath should work', test => {
test.skip(Boolean(process.env.CRPATH || process.env.FFPATH || process.env.WKPATH));
@ -26,12 +26,12 @@ it('browserType.executablePath should work', test => {
expect(fs.realpathSync(executablePath)).toBe(executablePath);
});
it('browserType.name should work', async ({browserType}) => {
if (options.WEBKIT)
it('browserType.name should work', async ({browserType, isChromium, isFirefox, isWebKit}) => {
if (isWebKit)
expect(browserType.name()).toBe('webkit');
else if (options.FIREFOX)
else if (isFirefox)
expect(browserType.name()).toBe('firefox');
else if (options.CHROMIUM)
else if (isChromium)
expect(browserType.name()).toBe('chromium');
else
throw new Error('Unknown browser');

View file

@ -36,8 +36,8 @@ it('should throw if userDataDir option is passed', async ({browserType, defaultB
expect(waitError.message).toContain('launchPersistentContext');
});
it('should throw if page argument is passed', test => {
test.skip(options.FIREFOX);
it('should throw if page argument is passed', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
let waitError = null;
const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] });
@ -45,7 +45,7 @@ it('should throw if page argument is passed', test => {
expect(waitError.message).toContain('can not specify page');
});
it('should reject if launched browser fails immediately', test => {
it('should reject if launched browser fails immediately', (test, parameters) => {
test.fixme(`I'm getting ENCONRESET on this one.`);
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')});
@ -61,7 +61,7 @@ it('should reject if executable path is invalid', async ({browserType, defaultBr
expect(waitError.message).toContain('Failed to launch');
});
it('should handle timeout', test => {
it('should handle timeout', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions}) => {
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
@ -71,7 +71,7 @@ it('should handle timeout', test => {
expect(error.message).toContain(`<launched> pid=`);
});
it('should handle exception', test => {
it('should handle exception', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions}) => {
const e = new Error('Dummy');
@ -80,7 +80,7 @@ it('should handle exception', test => {
expect(error.message).toContain('Dummy');
});
it('should report launch log', test => {
it('should report launch log', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions}) => {
const e = new Error('Dummy');
@ -89,7 +89,7 @@ it('should report launch log', test => {
expect(error.message).toContain('<launching>');
});
it('should accept objects as options', test => {
it('should accept objects as options', (test, parameters) => {
test.slow();
}, async ({browserType, defaultBrowserOptions}) => {
// @ts-expect-error process is not a real option.

View file

@ -17,8 +17,8 @@
import url from 'url';
import { it, expect, options } from './playwright.fixtures';
it('Web Assembly should work', test => {
test.fail(options.WEBKIT && WIN);
it('Web Assembly should work', (test, parameters) => {
test.fail(options.WEBKIT(parameters) && WIN);
}, async function({page, server}) {
await page.goto(server.PREFIX + '/wasm/table2.html');
expect(await page.evaluate('loadTable()')).toBe('42, 83');
@ -50,15 +50,15 @@ it('should respect CSP', async ({page, server}) => {
expect(await page.evaluate(() => window['testStatus'])).toBe('SUCCESS');
});
it('should play video', test => {
test.fixme(options.WEBKIT && (WIN || LINUX));
}, async ({page, asset}) => {
it('should play video', (test, parameters) => {
test.fixme(options.WEBKIT(parameters) && (WIN || LINUX));
}, async ({page, asset, isWebKit}) => {
// TODO: the test passes on Windows locally but fails on GitHub Action bot,
// apparently due to a Media Pack issue in the Windows Server.
// Also the test is very flaky on Linux WebKit.
//
// Safari only plays mp4 so we test WebKit with an .mp4 clip.
const fileName = options.WEBKIT ? 'video_mp4.html' : 'video.html';
const fileName = isWebKit ? 'video_mp4.html' : 'video.html';
const absolutePath = asset(fileName);
// Our test server doesn't support range requests required to play on Mac,
// so we load the page using a file url.

View file

@ -66,8 +66,8 @@ it('should scope context handles', async ({browserType, browser, server}) => {
await expectScopeState(browser, GOLDEN_PRECONDITION);
});
it('should scope CDPSession handles', test => {
test.skip(!options.CHROMIUM);
it('should scope CDPSession handles', (test, parameters) => {
test.skip(!options.CHROMIUM(parameters));
}, async ({browserType, browser}) => {
const GOLDEN_PRECONDITION = {
_guid: '',

View file

@ -16,8 +16,8 @@
import { it, expect, describe, options } from './playwright.fixtures';
describe('oopif', suite => {
suite.skip(!options.CHROMIUM);
describe('oopif', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should work', async function({browserType, page, server}) {
await page.coverage.startCSSCoverage();

View file

@ -16,15 +16,15 @@
import { it, expect, describe, options } from './playwright.fixtures';
it('should be missing', test => {
test.skip(options.CHROMIUM);
it('should be missing', (test, parameters) => {
test.skip(options.CHROMIUM(parameters));
},
async function({page}) {
expect(page.coverage).toBe(null);
});
describe('oopif', suite => {
suite.skip(!options.CHROMIUM);
describe('oopif', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should work', async function({page, server}) {
await page.coverage.startJSCoverage();

View file

@ -16,8 +16,8 @@
import { it, expect, describe, options } from '../playwright.fixtures';
import type { ChromiumBrowserContext } from '../..';
describe('chromium', suite => {
suite.skip(!options.CHROMIUM);
describe('chromium', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should create a worker from a service worker', async ({page, server, context}) => {
const [worker] = await Promise.all([

View file

@ -20,8 +20,8 @@ import utils from '../utils';
import type { ChromiumBrowser, ChromiumBrowserContext } from '../..';
const { makeUserDataDir, removeUserDataDir } = utils;
it('should throw with remote-debugging-pipe argument', test => {
test.skip(options.WIRE || !options.CHROMIUM);
it('should throw with remote-debugging-pipe argument', (test, parameters) => {
test.skip(options.WIRE || !options.CHROMIUM(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions);
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
@ -29,8 +29,8 @@ it('should throw with remote-debugging-pipe argument', test => {
expect(error.message).toContain('Playwright manages remote debugging connection itself');
});
it('should not throw with remote-debugging-port argument', test => {
test.skip(options.WIRE || !options.CHROMIUM);
it('should not throw with remote-debugging-port argument', (test, parameters) => {
test.skip(options.WIRE || !options.CHROMIUM(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions);
options.args = ['--remote-debugging-port=0'].concat(options.args || []);
@ -38,8 +38,8 @@ it('should not throw with remote-debugging-port argument', test => {
await browser.close();
});
it('should open devtools when "devtools: true" option is given', test => {
test.skip(!options.CHROMIUM || options.WIRE || WIN);
it('should open devtools when "devtools: true" option is given', (test, parameters) => {
test.skip(!options.CHROMIUM(parameters) || options.WIRE || WIN);
}, async ({browserType, defaultBrowserOptions}) => {
let devtoolsCallback;
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
@ -56,8 +56,8 @@ it('should open devtools when "devtools: true" option is given', test => {
await browser.close();
});
it('should return background pages', test => {
test.skip(!options.CHROMIUM);
it('should return background pages', (test, parameters) => {
test.skip(!options.CHROMIUM(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
const userDataDir = await makeUserDataDir();
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
@ -80,8 +80,8 @@ it('should return background pages', test => {
await removeUserDataDir(userDataDir);
});
it('should not create pages automatically', test => {
test.skip(!options.CHROMIUM);
it('should not create pages automatically', (test, parameters) => {
test.skip(!options.CHROMIUM(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch(defaultBrowserOptions);
const browserSession = await (browser as ChromiumBrowser).newBrowserCDPSession();

View file

@ -15,9 +15,9 @@
*/
import { options, playwrightFixtures } from '../playwright.fixtures';
const { it, expect, describe, registerWorkerFixture } = playwrightFixtures;
const { it, expect, describe, overrideWorkerFixture } = playwrightFixtures;
registerWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => {
overrideWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => {
const browser = await browserType.launch({
...defaultBrowserOptions,
args: (defaultBrowserOptions.args || []).concat(['--site-per-process'])
@ -26,8 +26,8 @@ registerWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, te
await browser.close();
});
describe('oopif', suite => {
suite.skip(!options.CHROMIUM);
describe('oopif', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should report oopif frames', async function({browser, page, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
@ -68,9 +68,9 @@ describe('oopif', suite => {
expect(await countOOPIFs(browser)).toBe(1);
});
it('should get the proper viewport', test => {
test.fixme(options.CHROMIUM);
test.skip(!options.CHROMIUM);
it('should get the proper viewport', (test, parameters) => {
test.fixme(options.CHROMIUM(parameters));
test.skip(!options.CHROMIUM(parameters));
}, async ({browser, page, server}) => {
expect(page.viewportSize()).toEqual({width: 1280, height: 720});
await page.goto(server.PREFIX + '/dynamic-oopif.html');

View file

@ -16,8 +16,8 @@
import { it, expect, describe, options } from '../playwright.fixtures';
import type { ChromiumBrowserContext, ChromiumBrowser } from '../../types/types';
describe('session', suite => {
suite.skip(!options.CHROMIUM);
describe('session', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should work', async function({page}) {
const client = await (page.context() as ChromiumBrowserContext).newCDPSession(page);

View file

@ -22,19 +22,19 @@ import type { ChromiumBrowser } from '../..';
type TestState = {
outputTraceFile: string;
};
const fixtures = playwrightFixtures.extend<{}, TestState>();
const { it, expect, describe, registerFixture } = fixtures;
const fixtures = playwrightFixtures.declareTestFixtures<TestState>();
const { it, expect, describe, defineTestFixture } = fixtures;
registerFixture('outputTraceFile', async ({tmpDir}, test) => {
defineTestFixture('outputTraceFile', async ({tmpDir}, test) => {
const outputTraceFile = path.join(tmpDir, `trace.json`);
await test(outputTraceFile);
if (fs.existsSync(outputTraceFile))
fs.unlinkSync(outputTraceFile);
});
describe('oopif', suite => {
suite.skip(!options.CHROMIUM);
describe('oopif', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should output a trace', async ({browser, page, server, outputTraceFile}) => {
await (browser as ChromiumBrowser).startTracing(page, {screenshots: true, path: outputTraceFile});

View file

@ -20,7 +20,7 @@ declare const renderComponent;
declare const e;
declare const MyButton;
it('should report that selector does not match anymore', test => {
it('should report that selector does not match anymore', (test, parameters) => {
test.fail(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -41,7 +41,7 @@ it('should report that selector does not match anymore', test => {
expect(error.message).toContain('element does not match the selector anymore');
});
it('should not retarget the handle when element is recycled', test => {
it('should not retarget the handle when element is recycled', (test, parameters) => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -70,7 +70,7 @@ it('should timeout when click opens alert', async ({page, server}) => {
await dialog.dismiss();
});
it('should retarget when element is recycled during hit testing', test => {
it('should retarget when element is recycled during hit testing', (test, parameters) => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -87,7 +87,7 @@ it('should retarget when element is recycled during hit testing', test => {
expect(await page.evaluate('window.button2')).toBe(undefined);
});
it('should retarget when element is recycled before enabled check', test => {
it('should retarget when element is recycled before enabled check', (test, parameters) => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');

View file

@ -17,7 +17,7 @@
import { it, expect, options } from './playwright.fixtures';
it('should avoid side effects after timeout', test => {
it('should avoid side effects after timeout', (test, parameters) => {
test.skip(options.WIRE);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/input/button.html');

View file

@ -17,7 +17,7 @@
import { it, expect, options } from './playwright.fixtures';
it('should fail when element jumps during hit testing', test => {
it('should fail when element jumps during hit testing', (test, parameters) => {
test.skip(options.WIRE);
}, async ({page}) => {
await page.setContent('<button>Click me</button>');

View file

@ -322,8 +322,8 @@ it('should click the button inside an iframe', async ({page, server}) => {
expect(await frame.evaluate(() => window['result'])).toBe('Clicked');
});
it('should click the button with fixed position inside an iframe', test => {
test.fixme(options.CHROMIUM || options.WEBKIT);
it('should click the button with fixed position inside an iframe', (test, parameters) => {
test.fixme(options.CHROMIUM(parameters) || options.WEBKIT(parameters));
}, async ({page, server}) => {
// @see https://github.com/GoogleChrome/puppeteer/issues/4110
// @see https://bugs.chromium.org/p/chromium/issues/detail?id=986390
@ -351,39 +351,39 @@ it('should click the button with deviceScaleFactor set', async ({browser, server
await context.close();
});
it('should click the button with px border with offset', async ({page, server}) => {
it('should click the button with px border with offset', async ({page, server, isWebKit}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => button.style.borderWidth = '8px');
await page.click('button', { position: { x: 20, y: 10 } });
expect(await page.evaluate('result')).toBe('Clicked');
// Safari reports border-relative offsetX/offsetY.
expect(await page.evaluate('offsetX')).toBe(options.WEBKIT ? 20 + 8 : 20);
expect(await page.evaluate('offsetY')).toBe(options.WEBKIT ? 10 + 8 : 10);
expect(await page.evaluate('offsetX')).toBe(isWebKit ? 20 + 8 : 20);
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 10 + 8 : 10);
});
it('should click the button with em border with offset', async ({page, server}) => {
it('should click the button with em border with offset', async ({page, server, isWebKit}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => button.style.borderWidth = '2em');
await page.$eval('button', button => button.style.fontSize = '12px');
await page.click('button', { position: { x: 20, y: 10 } });
expect(await page.evaluate('result')).toBe('Clicked');
// Safari reports border-relative offsetX/offsetY.
expect(await page.evaluate('offsetX')).toBe(options.WEBKIT ? 12 * 2 + 20 : 20);
expect(await page.evaluate('offsetY')).toBe(options.WEBKIT ? 12 * 2 + 10 : 10);
expect(await page.evaluate('offsetX')).toBe(isWebKit ? 12 * 2 + 20 : 20);
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 12 * 2 + 10 : 10);
});
it('should click a very large button with offset', async ({page, server}) => {
it('should click a very large button with offset', async ({page, server, isWebKit}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => button.style.borderWidth = '8px');
await page.$eval('button', button => button.style.height = button.style.width = '2000px');
await page.click('button', { position: { x: 1900, y: 1910 } });
expect(await page.evaluate(() => window['result'])).toBe('Clicked');
// Safari reports border-relative offsetX/offsetY.
expect(await page.evaluate('offsetX')).toBe(options.WEBKIT ? 1900 + 8 : 1900);
expect(await page.evaluate('offsetY')).toBe(options.WEBKIT ? 1910 + 8 : 1910);
expect(await page.evaluate('offsetX')).toBe(isWebKit ? 1900 + 8 : 1900);
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 1910 + 8 : 1910);
});
it('should click a button in scrolling container with offset', async ({page, server}) => {
it('should click a button in scrolling container with offset', async ({page, server, isWebKit}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => {
const container = document.createElement('div');
@ -399,13 +399,13 @@ it('should click a button in scrolling container with offset', async ({page, ser
await page.click('button', { position: { x: 1900, y: 1910 } });
expect(await page.evaluate(() => window['result'])).toBe('Clicked');
// Safari reports border-relative offsetX/offsetY.
expect(await page.evaluate('offsetX')).toBe(options.WEBKIT ? 1900 + 8 : 1900);
expect(await page.evaluate('offsetY')).toBe(options.WEBKIT ? 1910 + 8 : 1910);
expect(await page.evaluate('offsetX')).toBe(isWebKit ? 1900 + 8 : 1900);
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 1910 + 8 : 1910);
});
it('should click the button with offset with page scale', test => {
test.skip(options.FIREFOX);
}, async ({browser, server}) => {
it('should click the button with offset with page scale', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, isWebKit, isChromium}) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true });
const page = await context.newPage();
await page.goto(server.PREFIX + '/input/button.html');
@ -417,10 +417,10 @@ it('should click the button with offset with page scale', test => {
expect(await page.evaluate('result')).toBe('Clicked');
const round = x => Math.round(x + 0.01);
let expected = { x: 28, y: 18 }; // 20;10 + 8px of border in each direction
if (options.WEBKIT) {
if (isWebKit) {
// WebKit rounds up during css -> dip -> css conversion.
expected = { x: 29, y: 19 };
} else if (options.CHROMIUM && options.HEADLESS) {
} else if (isChromium && options.HEADLESS) {
// Headless Chromium rounds down during css -> dip -> css conversion.
expected = { x: 27, y: 18 };
}

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
import fs from 'fs';
import utils from './utils';
@ -79,7 +79,7 @@ it('context.clearCookies() should work', async ({server, launchPersistent}) => {
expect(await page.evaluate('document.cookie')).toBe('');
});
it('should(not) block third party cookies', async ({server, launchPersistent}) => {
it('should(not) block third party cookies', async ({server, launchPersistent, isChromium, isFirefox}) => {
const {page, context} = await launchPersistent();
await page.goto(server.EMPTY_PAGE);
await page.evaluate(src => {
@ -96,7 +96,7 @@ it('should(not) block third party cookies', async ({server, launchPersistent}) =
return document.cookie;
});
await page.waitForTimeout(2000);
const allowsThirdParty = options.CHROMIUM || options.FIREFOX;
const allowsThirdParty = isChromium || isFirefox;
expect(documentCookie).toBe(allowsThirdParty ? 'username=John Doe' : '');
const cookies = await context.cookies(server.CROSS_PROCESS_PREFIX + '/grid.html');
if (allowsThirdParty) {
@ -146,12 +146,12 @@ it('should support bypassCSP option', async ({server, launchPersistent}) => {
expect(await page.evaluate('__injected')).toBe(42);
});
it('should support javascriptEnabled option', async ({launchPersistent}) => {
it('should support javascriptEnabled option', async ({launchPersistent, isWebKit}) => {
const {page} = await launchPersistent({javaScriptEnabled: false});
await page.goto('data:text/html, <script>var something = "forbidden"</script>');
let error = null;
await page.evaluate('something').catch(e => error = e);
if (options.WEBKIT)
if (isWebKit)
expect(error.message).toContain('Can\'t find variable: something');
else
expect(error.message).toContain('something is not defined');
@ -170,7 +170,7 @@ it('should support offline option', async ({server, launchPersistent}) => {
expect(error).toBeTruthy();
});
it('should support acceptDownloads option', test => {
it('should support acceptDownloads option', (test, parameters) => {
test.skip('Unskip once we support downloads in persistent context.');
}, async ({server, launchPersistent}) => {
const {page} = await launchPersistent({acceptDownloads: true});

View file

@ -26,8 +26,8 @@ it('should support hasTouch option', async ({server, launchPersistent}) => {
expect(await page.evaluate(() => 'ontouchstart' in window)).toBe(true);
});
it('should work in persistent context', test => {
test.skip(options.FIREFOX);
it('should work in persistent context', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({server, launchPersistent}) => {
// Firefox does not support mobile.
const {page} = await launchPersistent({viewport: {width: 320, height: 480}, isMobile: true});
@ -68,8 +68,8 @@ it('should support ignoreHTTPSErrors option', async ({httpsServer, launchPersist
expect(response.ok()).toBe(true);
});
it('should support extraHTTPHeaders option', test => {
test.flaky(options.FIREFOX && !options.HEADLESS && LINUX, 'Intermittent timeout on bots');
it('should support extraHTTPHeaders option', (test, parameters) => {
test.flaky(options.FIREFOX(parameters) && !options.HEADLESS && LINUX, 'Intermittent timeout on bots');
}, async ({server, launchPersistent}) => {
const {page} = await launchPersistent({extraHTTPHeaders: { foo: 'bar' }});
const [request] = await Promise.all([
@ -79,8 +79,8 @@ it('should support extraHTTPHeaders option', test => {
expect(request.headers['foo']).toBe('bar');
});
it('should accept userDataDir', test => {
test.flaky(options.CHROMIUM);
it('should accept userDataDir', (test, parameters) => {
test.flaky(options.CHROMIUM(parameters));
}, async ({launchPersistent, tmpDir}) => {
const {context} = await launchPersistent();
// Note: we need an open page to make sure its functional.
@ -91,7 +91,7 @@ it('should accept userDataDir', test => {
await removeUserDataDir(tmpDir);
});
it('should restore state from userDataDir', test => {
it('should restore state from userDataDir', (test, parameters) => {
test.slow();
}, async ({browserType, defaultBrowserOptions, server, launchPersistent}) => {
const userDataDir = await makeUserDataDir();
@ -119,9 +119,9 @@ it('should restore state from userDataDir', test => {
await removeUserDataDir(userDataDir2);
});
it('should restore cookies from userDataDir', test => {
it('should restore cookies from userDataDir', (test, parameters) => {
test.slow();
test.flaky(options.CHROMIUM);
test.flaky(options.CHROMIUM(parameters));
}, async ({browserType, defaultBrowserOptions, server, launchPersistent}) => {
const userDataDir = await makeUserDataDir();
const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
@ -158,15 +158,15 @@ it('should have default URL when launching browser', async ({launchPersistent})
expect(urls).toEqual(['about:blank']);
});
it('should throw if page argument is passed', test => {
test.skip(options.FIREFOX);
it('should throw if page argument is passed', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browserType, defaultBrowserOptions, server, tmpDir}) => {
const options = {...defaultBrowserOptions, args: [server.EMPTY_PAGE] };
const error = await browserType.launchPersistentContext(tmpDir, options).catch(e => e);
expect(error.message).toContain('can not specify page');
});
it('should have passed URL when launching with ignoreDefaultArgs: true', test => {
it('should have passed URL when launching with ignoreDefaultArgs: true', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions, server, tmpDir, toImpl}) => {
const args = toImpl(browserType)._defaultArgs(defaultBrowserOptions, 'persistent', tmpDir, 0).filter(a => a !== 'about:blank');
@ -184,7 +184,7 @@ it('should have passed URL when launching with ignoreDefaultArgs: true', test =>
await browserContext.close();
});
it('should handle timeout', test => {
it('should handle timeout', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions, tmpDir}) => {
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
@ -192,7 +192,7 @@ it('should handle timeout', test => {
expect(error.message).toContain(`browserType.launchPersistentContext: Timeout 5000ms exceeded.`);
});
it('should handle exception', test => {
it('should handle exception', (test, parameters) => {
test.skip(options.WIRE);
}, async ({browserType, defaultBrowserOptions, tmpDir}) => {
const e = new Error('Dummy');
@ -209,8 +209,8 @@ it('should fire close event for a persistent context', async ({launchPersistent}
expect(closed).toBe(true);
});
it('coverage should work', test => {
test.skip(!options.CHROMIUM);
it('coverage should work', (test, parameters) => {
test.skip(!options.CHROMIUM(parameters));
}, async ({server, launchPersistent}) => {
const {page} = await launchPersistent();
await page.coverage.startJSCoverage();
@ -221,8 +221,8 @@ it('coverage should work', test => {
expect(coverage[0].functions.find(f => f.functionName === 'foo').ranges[0].count).toEqual(1);
});
it('coverage should be missing', test => {
test.skip(options.CHROMIUM);
it('coverage should be missing', (test, parameters) => {
test.skip(options.CHROMIUM(parameters));
}, async ({launchPersistent}) => {
const {page} = await launchPersistent();
expect(page.coverage).toBe(null);

View file

@ -62,8 +62,8 @@ it('should dismiss the confirm prompt', async ({page}) => {
expect(result).toBe(false);
});
it('should be able to close context with open alert', test => {
test.fixme(options.WEBKIT && MAC);
it('should be able to close context with open alert', (test, parameters) => {
test.fixme(options.WEBKIT(parameters) && MAC);
}, async ({browser}) => {
const context = await browser.newContext();
const page = await context.newPage();

View file

@ -127,8 +127,8 @@ it('should be atomic', async ({playwright, page}) => {
expect(await page.evaluate(() => window['_clicked'])).toBe(true);
});
it('should dispatch drag drop events', test => {
test.fail(options.WEBKIT);
it('should dispatch drag drop events', (test, parameters) => {
test.fail(options.WEBKIT(parameters));
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
@ -141,8 +141,8 @@ it('should dispatch drag drop events', test => {
}, {source, target})).toBeTruthy();
});
it('should dispatch drag drop events', test => {
test.fail(options.WEBKIT);
it('should dispatch drag drop events', (test, parameters) => {
test.fail(options.WEBKIT(parameters));
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
const dataTransfer = await page.evaluateHandle(() => new DataTransfer());

View file

@ -144,7 +144,7 @@ it('should create subdirectories when saving to non-existent user-specified path
await page.close();
});
it('should save when connected remotely', test => {
it('should save when connected remotely', (test, parameters) => {
test.skip(options.WIRE);
}, async ({tmpDir, server, browserType, remoteServer}) => {
const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() });
@ -190,7 +190,7 @@ it('should error when saving after deletion', async ({tmpDir, browser, server})
await page.close();
});
it('should error when saving after deletion when connected remotely', test => {
it('should error when saving after deletion when connected remotely', (test, parameters) => {
test.skip(options.WIRE);
}, async ({tmpDir, server, browserType, remoteServer}) => {
const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() });
@ -254,8 +254,8 @@ it(`should report download path within page.on('download', …) handler for Blob
expect(fs.readFileSync(path).toString()).toBe('Hello world');
await page.close();
});
it('should report alt-click downloads', test => {
test.fixme(options.FIREFOX || options.WEBKIT);
it('should report alt-click downloads', (test, parameters) => {
test.fixme(options.FIREFOX(parameters) || options.WEBKIT(parameters));
}, async ({browser, server}) => {
// Firefox does not download on alt-click by default.
// Our WebKit embedder does not download on alt-click, although Safari does.
@ -277,8 +277,8 @@ it('should report alt-click downloads', test => {
await page.close();
});
it('should report new window downloads', test => {
test.fixme(options.CHROMIUM && !options.HEADLESS);
it('should report new window downloads', (test, parameters) => {
test.fixme(options.CHROMIUM(parameters) && !options.HEADLESS);
}, async ({browser, server}) => {
// TODO: - the test fails in headful Chromium as the popup page gets closed along
// with the session before download completed event arrives.

View file

@ -26,10 +26,10 @@ type TestState = {
downloadsBrowser: Browser;
persistentDownloadsContext: BrowserContext;
};
const fixtures = playwrightFixtures.extend<{}, TestState>();
const { it, expect, registerFixture } = fixtures;
const fixtures = playwrightFixtures.declareTestFixtures<TestState>();
const { it, expect, defineTestFixture } = fixtures;
registerFixture('downloadsBrowser', async ({server, browserType, defaultBrowserOptions, tmpDir}, test) => {
defineTestFixture('downloadsBrowser', async ({server, browserType, defaultBrowserOptions, tmpDir}, test) => {
server.setRoute('/download', (req, res) => {
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename=file.txt');
@ -43,7 +43,7 @@ registerFixture('downloadsBrowser', async ({server, browserType, defaultBrowserO
await browser.close();
});
registerFixture('persistentDownloadsContext', async ({server, browserType, defaultBrowserOptions, tmpDir}, test) => {
defineTestFixture('persistentDownloadsContext', async ({server, browserType, defaultBrowserOptions, tmpDir}, test) => {
const userDataDir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-'));
server.setRoute('/download', (req, res) => {
res.setHeader('Content-Type', 'application/octet-stream');

View file

@ -21,8 +21,8 @@ const { it, expect, describe } = electronFixtures;
import path from 'path';
const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron';
describe('electron app', suite => {
suite.skip(!options.CHROMIUM);
describe('electron app', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should fire close event', async ({ playwright }) => {
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);

View file

@ -18,8 +18,8 @@ import { options } from '../playwright.fixtures';
import { electronFixtures } from './electron.fixture';
const { it, expect, describe } = electronFixtures;
describe('electron window', suite => {
suite.skip(!options.CHROMIUM);
describe('electron window', (suite, parameters) => {
suite.skip(!options.CHROMIUM(parameters));
}, () => {
it('should click the button', async ({window, server}) => {
await window.goto(server.PREFIX + '/input/button.html');

View file

@ -25,14 +25,14 @@ type TestState = {
window: ElectronPage;
};
export const electronFixtures = playwrightFixtures.extend<{}, TestState>();
const { registerFixture } = electronFixtures;
export const electronFixtures = playwrightFixtures.declareTestFixtures<TestState>();
const { defineTestFixture } = electronFixtures;
declare module '../../index' {
const electron: ElectronLauncher;
}
registerFixture('application', async ({playwright}, test) => {
defineTestFixture('application', async ({playwright}, test) => {
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
const application = await playwright.electron.launch(electronPath, {
args: [path.join(__dirname, 'testApp.js')],
@ -41,7 +41,7 @@ registerFixture('application', async ({playwright}, test) => {
await application.close();
});
registerFixture('window', async ({application}, test) => {
defineTestFixture('window', async ({application}, test) => {
const page = await application.newBrowserWindow({ width: 800, height: 600 });
await test(page);
await page.close();

View file

@ -18,8 +18,8 @@
import { it, expect, options } from './playwright.fixtures';
it('should work', test => {
test.fail(options.FIREFOX && !options.HEADLESS);
it('should work', (test, parameters) => {
test.fail(options.FIREFOX(parameters) && !options.HEADLESS);
}, async ({ page, server }) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.goto(server.PREFIX + '/grid.html');
@ -67,8 +67,8 @@ it('should work with SVG nodes', async ({ page, server }) => {
expect(pwBoundingBox).toEqual(webBoundingBox);
});
it('should work with page scale', test => {
test.skip(options.FIREFOX);
it('should work with page scale', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true });
const page = await context.newPage();

View file

@ -34,8 +34,8 @@ it('should work for cross-process iframes', async ({ page, server }) => {
expect(await elementHandle.ownerFrame()).toBe(frame);
});
it('should work for document', test => {
test.flaky(WIN && options.WEBKIT);
it('should work for document', (test, parameters) => {
test.flaky(WIN && options.WEBKIT(parameters));
}, async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);

View file

@ -22,11 +22,8 @@ import {PNG} from 'pngjs';
import path from 'path';
import fs from 'fs';
// Firefox headful produces a different image.
const ffheadful = options.FIREFOX && !options.HEADLESS;
describe('element screenshot', suite => {
suite.skip(ffheadful);
describe('element screenshot', (suite, parameters) => {
suite.skip(parameters.browserName === 'firefox' && !options.HEADLESS);
}, () => {
it('should work', async ({page, server, golden}) => {
await page.setViewportSize({width: 500, height: 500});
@ -214,8 +211,8 @@ describe('element screenshot', suite => {
expect(screenshot).toMatchImage(golden('screenshot-element-fractional.png'));
});
it('should work with a mobile viewport', test => {
test.skip(options.FIREFOX);
it('should work with a mobile viewport', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, golden}) => {
const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true});
const page = await context.newPage();
@ -227,8 +224,8 @@ describe('element screenshot', suite => {
await context.close();
});
it('should work with device scale factor', test => {
test.skip(options.FIREFOX);
it('should work with device scale factor', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, golden}) => {
const context = await browser.newContext({ viewport: { width: 320, height: 480 }, deviceScaleFactor: 2 });
const page = await context.newPage();
@ -292,7 +289,7 @@ describe('element screenshot', suite => {
await context.close();
});
it('should restore viewport after page screenshot and exception', test => {
it('should restore viewport after page screenshot and exception', (test, parameters) => {
test.skip(options.WIRE);
}, async ({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
@ -305,7 +302,7 @@ describe('element screenshot', suite => {
await context.close();
});
it('should restore viewport after page screenshot and timeout', test => {
it('should restore viewport after page screenshot and timeout', (test, parameters) => {
test.skip(options.WIRE);
}, async ({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
@ -351,9 +348,9 @@ describe('element screenshot', suite => {
await context.close();
});
it('should restore viewport after element screenshot and exception', test => {
it('should restore viewport after element screenshot and exception', (test, parameters) => {
test.skip(options.WIRE);
}, async ({server, browser}) => {
}, async ({browser}) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
const page = await context.newPage();
await page.setContent(`<div style="width:600px;height:600px;"></div>`);
@ -365,8 +362,8 @@ describe('element screenshot', suite => {
await context.close();
});
it('should wait for element to stop moving', test => {
test.flaky(options.WEBKIT && !options.HEADLESS && LINUX);
it('should wait for element to stop moving', (test, parameters) => {
test.flaky(options.WEBKIT(parameters) && !options.HEADLESS && LINUX);
}, async ({ page, server, golden }) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.goto(server.PREFIX + '/grid.html');

View file

@ -15,14 +15,14 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should select textarea', async ({ page, server }) => {
it('should select textarea', async ({ page, server, isFirefox }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
await textarea.evaluate(textarea => textarea.value = 'some value');
await textarea.selectText();
if (options.FIREFOX) {
if (isFirefox) {
expect(await textarea.evaluate(el => el.selectionStart)).toBe(0);
expect(await textarea.evaluate(el => el.selectionEnd)).toBe(10);
} else {
@ -30,12 +30,12 @@ it('should select textarea', async ({ page, server }) => {
}
});
it('should select input', async ({ page, server }) => {
it('should select input', async ({ page, server, isFirefox }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const input = await page.$('input');
await input.evaluate(input => input.value = 'some value');
await input.selectText();
if (options.FIREFOX) {
if (isFirefox) {
expect(await input.evaluate(el => el.selectionStart)).toBe(0);
expect(await input.evaluate(el => el.selectionEnd)).toBe(10);
} else {

View file

@ -114,8 +114,8 @@ it('should wait for disabled button', async ({page}) => {
await promise;
});
it('should wait for stable position', test => {
test.fixme(options.FIREFOX && LINUX);
it('should wait for stable position', (test, parameters) => {
test.fixme(options.FIREFOX(parameters) && LINUX);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/input/button.html');
const button = await page.$('button');

View file

@ -101,8 +101,8 @@ it('should change document.activeElement', async ({page, server}) => {
expect(active).toEqual(['INPUT', 'TEXTAREA']);
});
it('should not affect screenshots', test => {
test.skip(options.FIREFOX && !options.HEADLESS);
it('should not affect screenshots', (test, parameters) => {
test.skip(options.FIREFOX(parameters) && !options.HEADLESS);
}, async ({page, server, golden}) => {
// Firefox headful produces a different image.
const page2 = await page.context().newPage();

View file

@ -15,8 +15,8 @@
*/
import { it, expect, options } from '../playwright.fixtures';
it('should pass firefox user preferences', test => {
test.skip(!options.FIREFOX);
it('should pass firefox user preferences', (test, parameters) => {
test.skip(!options.FIREFOX(parameters));
}, async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch({
...defaultBrowserOptions,

View file

@ -26,10 +26,10 @@ export type FixturesFixtures = {
stallingConnectedRemoteServer: RemoteServer;
};
const fixturesFixtures = serverFixtures.extend<{}, FixturesFixtures>();
const { it, describe, expect, registerFixture } = fixturesFixtures;
const fixturesFixtures = serverFixtures.declareTestFixtures<FixturesFixtures>();
const { it, describe, expect, defineTestFixture } = fixturesFixtures;
registerFixture('connectedRemoteServer', async ({browserType, remoteServer, server}, test) => {
defineTestFixture('connectedRemoteServer', async ({browserType, remoteServer, server}, test) => {
const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() });
const page = await browser.newPage();
await page.goto(server.EMPTY_PAGE);
@ -37,7 +37,7 @@ registerFixture('connectedRemoteServer', async ({browserType, remoteServer, serv
await browser.close();
});
registerFixture('stallingConnectedRemoteServer', async ({browserType, stallingRemoteServer, server}, test) => {
defineTestFixture('stallingConnectedRemoteServer', async ({browserType, stallingRemoteServer, server}, test) => {
const browser = await browserType.connect({ wsEndpoint: stallingRemoteServer.wsEndpoint() });
const page = await browser.newPage();
await page.goto(server.EMPTY_PAGE);
@ -45,7 +45,7 @@ registerFixture('stallingConnectedRemoteServer', async ({browserType, stallingRe
await browser.close();
});
it('should close the browser when the node process closes', test => {
it('should close the browser when the node process closes', (test, parameters) => {
test.slow();
}, async ({connectedRemoteServer}) => {
if (WIN)

View file

@ -16,8 +16,8 @@
import { it, expect, options } from './playwright.fixtures';
it('should work', test => {
test.skip(options.FIREFOX);
it('should work', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async function({page}) {
await page.setContent(`<div id=d1 tabIndex=0></div>`);
expect(await page.evaluate(() => document.activeElement.nodeName)).toBe('BODY');
@ -78,8 +78,8 @@ it('should traverse focus in all directions', async function({page}) {
expect(await page.evaluate(() => (document.activeElement as HTMLInputElement).value)).toBe('1');
});
it('should traverse only form elements', test => {
test.skip(!MAC || !options.WEBKIT,
it('should traverse only form elements', (test, parameters) => {
test.skip(!MAC || !options.WEBKIT(parameters),
'Chromium and WebKit both have settings for tab traversing all links, but it is only on by default in WebKit.');
}, async function({page}) {
await page.setContent(`

View file

@ -36,8 +36,8 @@ it('should have correct execution contexts', async ({ page, server }) => {
expect(await page.frames()[1].evaluate(() => document.body.textContent.trim())).toBe(`Hi, I'm frame`);
});
function expectContexts(pageImpl, count) {
if (options.CHROMIUM)
function expectContexts(pageImpl, count, isChromium) {
if (isChromium)
expect(pageImpl._delegate._mainFrameSession._contextIdToContext.size).toBe(count);
else
expect(pageImpl._delegate._contextIdToContext.size).toBe(count);
@ -45,22 +45,22 @@ function expectContexts(pageImpl, count) {
it('should dispose context on navigation', test => {
test.skip(options.WIRE);
}, async ({ page, server, toImpl }) => {
}, async ({ page, server, toImpl, isChromium }) => {
await page.goto(server.PREFIX + '/frames/one-frame.html');
expect(page.frames().length).toBe(2);
expectContexts(toImpl(page), 4);
expectContexts(toImpl(page), 4, isChromium);
await page.goto(server.EMPTY_PAGE);
expectContexts(toImpl(page), 2);
expectContexts(toImpl(page), 2, isChromium);
});
it('should dispose context on cross-origin navigation', test => {
it('should dispose context on cross-origin navigation', (test, parameters) => {
test.skip(options.WIRE);
}, async ({ page, server, toImpl }) => {
}, async ({ page, server, toImpl, isChromium }) => {
await page.goto(server.PREFIX + '/frames/one-frame.html');
expect(page.frames().length).toBe(2);
expectContexts(toImpl(page), 4);
expectContexts(toImpl(page), 4, isChromium);
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
expectContexts(toImpl(page), 2);
expectContexts(toImpl(page), 2, isChromium);
});
it('should execute after cross-site navigation', async ({ page, server }) => {
@ -131,9 +131,9 @@ it('should be isolated between frames', async ({page, server}) => {
expect(a2).toBe(2);
});
it('should work in iframes that failed initial navigation', test => {
test.fail(options.CHROMIUM);
test.fixme(options.FIREFOX);
it('should work in iframes that failed initial navigation', (test, parameters) => {
test.fail(options.CHROMIUM(parameters));
test.fixme(options.FIREFOX(parameters));
}, async ({page}) => {
// - Firefox does not report domcontentloaded for the iframe.
// - Chromium and Firefox report empty url.
@ -155,8 +155,8 @@ it('should work in iframes that failed initial navigation', test => {
expect(await page.frames()[1].$('div')).toBeTruthy();
});
it('should work in iframes that interrupted initial javascript url navigation', test => {
test.fixme(options.CHROMIUM);
it('should work in iframes that interrupted initial javascript url navigation', (test, parameters) => {
test.fixme(options.CHROMIUM(parameters));
}, async ({page, server}) => {
// Chromium does not report isolated world for the iframe.
await page.goto(server.EMPTY_PAGE);

View file

@ -172,8 +172,8 @@ it('should report different frame instance when frame re-attaches', async ({page
expect(frame1).not.toBe(frame2);
});
it('should refuse to display x-frame-options:deny iframe', test => {
test.fixme(options.FIREFOX);
it('should refuse to display x-frame-options:deny iframe', (test, parameters) => {
test.fixme(options.FIREFOX(parameters));
}, async ({page, server}) => {
server.setRoute('/x-frame-options-deny.html', async (req, res) => {
res.setHeader('Content-Type', 'text/html');

View file

@ -26,9 +26,9 @@ it('should have default url when launching browser', async ({browserType, defaul
await browserContext.close();
});
it('headless should be able to read cookies written by headful', test => {
test.fail(WIN && options.CHROMIUM);
test.flaky(options.FIREFOX);
it('headless should be able to read cookies written by headful', (test, parameters) => {
test.fail(WIN && options.CHROMIUM(parameters));
test.flaky(options.FIREFOX(parameters));
test.slow();
}, async ({browserType, defaultBrowserOptions, server}) => {
// see https://github.com/microsoft/playwright/issues/717
@ -50,7 +50,7 @@ it('headless should be able to read cookies written by headful', test => {
expect(cookie).toBe('foo=true');
});
it('should close browser with beforeunload page', test => {
it('should close browser with beforeunload page', (test, parameters) => {
test.slow();
}, async ({browserType, defaultBrowserOptions, server, tmpDir}) => {
const browserContext = await browserType.launchPersistentContext(tmpDir, {...defaultBrowserOptions, headless: false});
@ -94,7 +94,7 @@ it('should close browser after context menu was triggered', async ({browserType,
await browser.close();
});
it('should(not) block third party cookies', async ({browserType, defaultBrowserOptions, server}) => {
it('should(not) block third party cookies', async ({browserType, defaultBrowserOptions, server, isChromium, isFirefox}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const page = await browser.newPage();
await page.goto(server.EMPTY_PAGE);
@ -112,7 +112,7 @@ it('should(not) block third party cookies', async ({browserType, defaultBrowserO
return document.cookie;
});
await page.waitForTimeout(2000);
const allowsThirdParty = options.CHROMIUM || options.FIREFOX;
const allowsThirdParty = isChromium || isFirefox;
expect(documentCookie).toBe(allowsThirdParty ? 'username=John Doe' : '');
const cookies = await page.context().cookies(server.CROSS_PROCESS_PREFIX + '/grid.html');
if (allowsThirdParty) {
@ -134,8 +134,8 @@ it('should(not) block third party cookies', async ({browserType, defaultBrowserO
await browser.close();
});
it('should not override viewport size when passed null', test => {
test.fixme(options.WEBKIT);
it('should not override viewport size when passed null', (test, parameters) => {
test.fixme(options.WEBKIT(parameters));
}, async function({browserType, defaultBrowserOptions, server}) {
// Our WebKit embedder does not respect window features.
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should work for primitives', async ({page}) => {
const numberHandle = await page.evaluateHandle(() => 2);
@ -36,7 +36,7 @@ it('should work for promises', async ({page}) => {
expect(bHandle.toString()).toBe('JSHandle@promise');
});
it('should work with different subtypes', async ({page}) => {
it('should work with different subtypes', async ({page, isWebKit}) => {
expect((await page.evaluateHandle('(function(){})')).toString()).toBe('JSHandle@function');
expect((await page.evaluateHandle('12')).toString()).toBe('JSHandle@12');
expect((await page.evaluateHandle('true')).toString()).toBe('JSHandle@true');
@ -54,6 +54,6 @@ it('should work with different subtypes', async ({page}) => {
expect((await page.evaluateHandle('new WeakSet()')).toString()).toBe('JSHandle@weakset');
expect((await page.evaluateHandle('new Error()')).toString()).toBe('JSHandle@error');
// TODO(yurys): change subtype from array to typedarray in WebKit.
expect((await page.evaluateHandle('new Int32Array()')).toString()).toBe(options.WEBKIT ? 'JSHandle@array' : 'JSHandle@typedarray');
expect((await page.evaluateHandle('new Int32Array()')).toString()).toBe(isWebKit ? 'JSHandle@array' : 'JSHandle@typedarray');
expect((await page.evaluateHandle('new Proxy({}, {})')).toString()).toBe('JSHandle@proxy');
});

View file

@ -83,8 +83,8 @@ it('insertText should only emit input event', async ({page, server}) => {
expect(await events.jsonValue()).toEqual(['input']);
});
it('should report shiftKey', test => {
test.fail(options.FIREFOX && MAC);
it('should report shiftKey', (test, parameters) => {
test.fail(options.FIREFOX(parameters) && MAC);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
const keyboard = page.keyboard;
@ -342,7 +342,7 @@ it('should be able to prevent selectAll', async ({page, server}) => {
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some tex');
});
it('should support MacOS shortcuts', test => {
it('should support MacOS shortcuts', (test, parameters) => {
test.skip(!MAC);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
@ -354,21 +354,21 @@ it('should support MacOS shortcuts', test => {
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some ');
});
it('should press the meta key', async ({page}) => {
it('should press the meta key', async ({page, isFirefox}) => {
const lastEvent = await captureLastKeydown(page);
await page.keyboard.press('Meta');
const {key, code, metaKey} = await lastEvent.jsonValue();
if (options.FIREFOX && !MAC)
if (isFirefox && !MAC)
expect(key).toBe('OS');
else
expect(key).toBe('Meta');
if (options.FIREFOX)
if (isFirefox)
expect(code).toBe('OSLeft');
else
expect(code).toBe('MetaLeft');
if (options.FIREFOX && !MAC)
if (isFirefox && !MAC)
expect(metaKey).toBe(false);
else
expect(metaKey).toBe(true);
@ -384,9 +384,9 @@ it('should work after a cross origin navigation', async ({page, server}) => {
});
// event.keyIdentifier has been removed from all browsers except WebKit
it('should expose keyIdentifier in webkit', test => {
test.skip(!options.WEBKIT);
}, async ({page, server}) => {
it('should expose keyIdentifier in webkit', (test, parameters) => {
test.skip(!options.WEBKIT(parameters));
}, async ({page}) => {
const lastEvent = await captureLastKeydown(page);
const keyMap = {
'ArrowUp': 'Up',

View file

@ -27,10 +27,9 @@ function dimensions() {
};
}
it('should click the document', test => {
test.flaky(options.FIREFOX && WIN);
it('should click the document', (test, parameters) => {
test.flaky(options.FIREFOX(parameters) && WIN, 'Occasionally times out on options.FIREFOX on Windows: https://github.com/microsoft/playwright/pull/1911/checks?check_run_id=607149016');
}, async ({page, server}) => {
// Occasionally times out on options.FIREFOX on Windows: https://github.com/microsoft/playwright/pull/1911/checks?check_run_id=607149016
await page.evaluate(() => {
window['clickPromise'] = new Promise(resolve => {
document.addEventListener('click', event => {
@ -124,12 +123,12 @@ it('should trigger hover state with removed window.Node', async ({page, server})
expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6');
});
it('should set modifier keys on click', async ({page, server}) => {
it('should set modifier keys on click', async ({page, server, isFirefox}) => {
await page.goto(server.PREFIX + '/input/scrollable.html');
await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window['lastEvent'] = e, true));
const modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'};
// In Firefox, the Meta modifier only exists on Mac
if (options.FIREFOX && !MAC)
if (isFirefox && !MAC)
delete modifiers['Meta'];
for (const modifier in modifiers) {
await page.keyboard.down(modifier);
@ -145,9 +144,9 @@ it('should set modifier keys on click', async ({page, server}) => {
}
});
it('should tween mouse movement', async ({page}) => {
it('should tween mouse movement', async ({page, isWebKit}) => {
// The test becomes flaky on WebKit without next line.
if (options.WEBKIT)
if (isWebKit)
await page.evaluate(() => new Promise(requestAnimationFrame));
await page.mouse.move(100, 100);
await page.evaluate(() => {
@ -166,8 +165,8 @@ it('should tween mouse movement', async ({page}) => {
]);
});
it('should work with mobile viewports and cross process navigations', test => {
test.skip(options.FIREFOX);
it('should work with mobile viewports and cross process navigations', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server}) => {
// @see https://crbug.com/929806
const context = await browser.newContext({ viewport: {width: 360, height: 640}, isMobile: true });

View file

@ -45,18 +45,18 @@ it('should work for fetch requests', async ({page, server}) => {
expect(requests[0].frame()).toBe(page.mainFrame());
});
it('should return headers', async ({page, server}) => {
it('should return headers', async ({page, server, isChromium, isFirefox, isWebKit}) => {
const response = await page.goto(server.EMPTY_PAGE);
if (options.CHROMIUM)
if (isChromium)
expect(response.request().headers()['user-agent']).toContain('Chrome');
else if (options.FIREFOX)
else if (isFirefox)
expect(response.request().headers()['user-agent']).toContain('Firefox');
else if (options.WEBKIT)
else if (isWebKit)
expect(response.request().headers()['user-agent']).toContain('WebKit');
});
it('should get the same headers as the server', test => {
test.fail(options.CHROMIUM || options.WEBKIT);
it('should get the same headers as the server', (test, parameters) => {
test.fail(options.CHROMIUM(parameters) || options.WEBKIT(parameters));
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/empty.html');
let serverRequest;

View file

@ -74,8 +74,8 @@ it('should work with a path', async ({page, server}) => {
expect(await page.evaluate(() => window['__injected'])).toBe(42);
});
it('should include sourceURL when path is provided', test => {
test.skip(options.WEBKIT);
it('should include sourceURL when path is provided', (test, parameters) => {
test.skip(options.WEBKIT(parameters));
}, async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.addScriptTag({ path: path.join(__dirname, 'assets/injectedfile.js') });

View file

@ -34,7 +34,7 @@ it('should not be visible in context.pages', async ({context}) => {
expect(context.pages()).not.toContain(newPage);
});
it('should run beforeunload if asked for', async ({context, server}) => {
it('should run beforeunload if asked for', async ({context, server, isChromium, isWebKit}) => {
const newPage = await context.newPage();
await newPage.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
@ -44,9 +44,9 @@ it('should run beforeunload if asked for', async ({context, server}) => {
const dialog = await newPage.waitForEvent('dialog');
expect(dialog.type()).toBe('beforeunload');
expect(dialog.defaultValue()).toBe('');
if (options.CHROMIUM)
if (isChromium)
expect(dialog.message()).toBe('');
else if (options.WEBKIT)
else if (isWebKit)
expect(dialog.message()).toBe('Leave?');
else
expect(dialog.message()).toBe('This page is asking you to confirm that you want to leave - data you have entered may not be saved.');
@ -197,7 +197,7 @@ it('page.frame should respect url', async function({page, server}) {
expect(page.frame({ url: /empty/ }).url()).toBe(server.EMPTY_PAGE);
});
it('should have sane user agent', async ({page}) => {
it('should have sane user agent', async ({page, isChromium, isFirefox}) => {
const userAgent = await page.evaluate(() => navigator.userAgent);
const [
part1,
@ -211,7 +211,7 @@ it('should have sane user agent', async ({page}) => {
// Second part in parenthesis is platform - ignore it.
// Third part for Firefox is the last one and encodes engine and browser versions.
if (options.FIREFOX) {
if (isFirefox) {
const [engine, browser] = part3.split(' ');
expect(engine.startsWith('Gecko')).toBe(true);
expect(browser.startsWith('Firefox')).toBe(true);
@ -225,7 +225,7 @@ it('should have sane user agent', async ({page}) => {
// 5th part encodes real browser name and engine version.
const [engine, browser] = part5.split(' ');
expect(browser.startsWith('Safari/')).toBe(true);
if (options.CHROMIUM)
if (isChromium)
expect(engine.includes('Chrome/')).toBe(true);
else
expect(engine.startsWith('Version/')).toBe(true);
@ -252,8 +252,8 @@ it('frame.press should work', async ({page, server}) => {
expect(await frame.evaluate(() => document.querySelector('textarea').value)).toBe('a');
});
it('frame.focus should work multiple times', test => {
test.fail(options.FIREFOX);
it('frame.focus should work multiple times', (test, parameters) => {
test.fail(options.FIREFOX(parameters));
}, async ({ context, server }) => {
const page1 = await context.newPage();
const page2 = await context.newPage();

View file

@ -415,8 +415,8 @@ it('should not throw an error when evaluation does a navigation', async ({ page,
expect(result).toEqual([42]);
});
it('should not throw an error when evaluation does a synchronous navigation and returns an object', test => {
test.fixme(options.WEBKIT);
it('should not throw an error when evaluation does a synchronous navigation and returns an object', (test, parameters) => {
test.fixme(options.WEBKIT(parameters));
}, async ({ page, server }) => {
// It is imporant to be on about:blank for sync reload.
const result = await page.evaluate(() => {
@ -435,7 +435,7 @@ it('should not throw an error when evaluation does a synchronous navigation and
expect(result).toBe(undefined);
});
it('should transfer 100Mb of data from page to node.js', test => {
it('should transfer 100Mb of data from page to node.js', (test, parameters) => {
test.skip(options.WIRE);
}, async ({ page }) => {
// This is too slow with wire.

View file

@ -26,9 +26,9 @@ function crash(pageImpl, browserName) {
pageImpl._delegate._session.send('Page.crash', {}).catch(e => {});
}
describe('', suite => {
describe('', (suite, parameters) => {
suite.fixme(options.WIRE);
suite.flaky(options.FIREFOX && WIN);
suite.flaky(options.FIREFOX(parameters) && WIN);
}, () => {
it('should emit crash event when page crashes', async ({page, browserName, toImpl}) => {
await page.setContent(`<div>This page should crash</div>`);
@ -63,9 +63,9 @@ describe('', suite => {
expect(error.message).toContain('Navigation failed because page crashed');
});
it('should be able to close context when page crashes', test => {
it('should be able to close context when page crashes', (test, parameters) => {
test.fixme(options.WIRE);
test.flaky(options.FIREFOX && WIN);
test.flaky(options.FIREFOX(parameters) && WIN);
}, async ({page, browserName, toImpl}) => {
await page.setContent(`<div>This page should crash</div>`);
crash(toImpl(page), browserName);

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('Page.Events.Request', async ({page, server}) => {
const requests = [];
@ -41,7 +41,7 @@ it('Page.Events.Response', async ({page, server}) => {
expect(responses[0].request()).toBeTruthy();
});
it('Page.Events.RequestFailed', async ({page, server}) => {
it('Page.Events.RequestFailed', async ({page, server, isChromium, isWebKit}) => {
server.setRoute('/one-style.css', (req, res) => {
res.setHeader('Content-Type', 'text/css');
res.connection.destroy();
@ -53,9 +53,9 @@ it('Page.Events.RequestFailed', async ({page, server}) => {
expect(failedRequests[0].url()).toContain('one-style.css');
expect(await failedRequests[0].response()).toBe(null);
expect(failedRequests[0].resourceType()).toBe('stylesheet');
if (options.CHROMIUM) {
if (isChromium) {
expect(failedRequests[0].failure().errorText).toBe('net::ERR_EMPTY_RESPONSE');
} else if (options.WEBKIT) {
} else if (isWebKit) {
if (MAC)
expect(failedRequests[0].failure().errorText).toBe('The network connection was lost.');
else if (WIN)

View file

@ -17,7 +17,7 @@
import { it, expect, options } from './playwright.fixtures';
it('should fire', async ({page, server}) => {
it('should fire', async ({page, server, isWebKit}) => {
const [error] = await Promise.all([
page.waitForEvent('pageerror'),
page.goto(server.PREFIX + '/error.html'),
@ -26,13 +26,13 @@ it('should fire', async ({page, server}) => {
expect(error.message).toBe('Fancy error!');
let stack = await page.evaluate(() => window['e'].stack);
// Note that WebKit reports the stack of the 'throw' statement instead of the Error constructor call.
if (options.WEBKIT)
if (isWebKit)
stack = stack.replace('14:25', '15:19');
expect(error.stack).toBe(stack);
});
it('should contain sourceURL', test => {
test.fail(options.WEBKIT);
it('should contain sourceURL', (test, parameters) => {
test.fail(options.WEBKIT(parameters));
}, async ({page, server}) => {
const [error] = await Promise.all([
page.waitForEvent('pageerror'),
@ -41,7 +41,7 @@ it('should contain sourceURL', test => {
expect(error.stack).toContain('myscript.js');
});
it('should handle odd values', async ({page}) => {
it('should handle odd values', async ({page, isFirefox}) => {
const cases = [
[null, 'null'],
[undefined, 'undefined'],
@ -53,28 +53,28 @@ it('should handle odd values', async ({page}) => {
page.waitForEvent('pageerror'),
page.evaluate(value => setTimeout(() => { throw value; }, 0), value),
]);
expect(error.message).toBe(options.FIREFOX ? 'uncaught exception: ' + message : message);
expect(error.message).toBe(isFirefox ? 'uncaught exception: ' + message : message);
}
});
it('should handle object', test => {
test.fixme(options.FIREFOX);
}, async ({page}) => {
it('should handle object', (test, parameters) => {
test.fixme(options.FIREFOX(parameters));
}, async ({page, isChromium}) => {
// Firefox just does not report this error.
const [error] = await Promise.all([
page.waitForEvent('pageerror'),
page.evaluate(() => setTimeout(() => { throw {}; }, 0)),
]);
expect(error.message).toBe(options.CHROMIUM ? 'Object' : '[object Object]');
expect(error.message).toBe(isChromium ? 'Object' : '[object Object]');
});
it('should handle window', test => {
test.fixme(options.FIREFOX);
}, async ({page}) => {
it('should handle window', (test, parameters) => {
test.fixme(options.FIREFOX(parameters));
}, async ({page, isChromium}) => {
// Firefox just does not report this error.
const [error] = await Promise.all([
page.waitForEvent('pageerror'),
page.evaluate(() => setTimeout(() => { throw window; }, 0)),
]);
expect(error.message).toBe(options.CHROMIUM ? 'Window' : '[object Window]');
expect(error.message).toBe(isChromium ? 'Window' : '[object Window]');
});

View file

@ -60,8 +60,8 @@ it('should fill date input after clicking', async ({page, server}) => {
expect(await page.$eval('input', input => input.value)).toBe('2020-03-02');
});
it('should throw on incorrect date', test => {
test.skip(options.WEBKIT);
it('should throw on incorrect date', (test, parameters) => {
test.skip(options.WEBKIT(parameters));
}, async ({page}) => {
await page.setContent('<input type=date>');
const error = await page.fill('input', '2020-13-05').catch(e => e);
@ -74,8 +74,8 @@ it('should fill time input', async ({page, server}) => {
expect(await page.$eval('input', input => input.value)).toBe('13:15');
});
it('should throw on incorrect time', test => {
test.skip(options.WEBKIT);
it('should throw on incorrect time', (test, parameters) => {
test.skip(options.WEBKIT(parameters));
}, async ({page}) => {
await page.setContent('<input type=time>');
const error = await page.fill('input', '25:05').catch(e => e);
@ -88,8 +88,8 @@ it('should fill datetime-local input', async ({page, server}) => {
expect(await page.$eval('input', input => input.value)).toBe('2020-03-02T05:15');
});
it('should throw on incorrect datetime-local', test => {
test.skip(options.WEBKIT || options.FIREFOX);
it('should throw on incorrect datetime-local', (test, parameters) => {
test.skip(options.WEBKIT(parameters) || options.FIREFOX(parameters));
}, async ({page, server}) => {
await page.setContent('<input type=datetime-local>');
const error = await page.fill('input', 'abc').catch(e => e);

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
import utils from './utils';
import path from 'path';
@ -134,7 +134,7 @@ it('should work with subframes return 204 with domcontentloaded', async ({page,
await page.goto(server.PREFIX + '/frames/one-frame.html', { waitUntil: 'domcontentloaded' });
});
it('should fail when server returns 204', async ({page, server}) => {
it('should fail when server returns 204', async ({page, server, isChromium, isWebKit}) => {
// Webkit just loads an empty page.
server.setRoute('/empty.html', (req, res) => {
res.statusCode = 204;
@ -143,9 +143,9 @@ it('should fail when server returns 204', async ({page, server}) => {
let error = null;
await page.goto(server.EMPTY_PAGE).catch(e => error = e);
expect(error).not.toBe(null);
if (options.CHROMIUM)
if (isChromium)
expect(error.message).toContain('net::ERR_ABORTED');
else if (options.WEBKIT)
else if (isWebKit)
expect(error.message).toContain('Aborted: 204 No Content');
else
expect(error.message).toContain('NS_BINDING_ABORTED');
@ -165,10 +165,10 @@ it('should work when page calls history API in beforeunload', async ({page, serv
expect(response.status()).toBe(200);
});
it('should fail when navigating to bad url', async ({page}) => {
it('should fail when navigating to bad url', async ({page, isChromium, isWebKit}) => {
let error = null;
await page.goto('asdfasdf').catch(e => error = e);
if (options.CHROMIUM || options.WEBKIT)
if (isChromium || isWebKit)
expect(error.message).toContain('Cannot navigate to invalid URL');
else
expect(error.message).toContain('Invalid url');
@ -210,14 +210,14 @@ it('should throw if networkidle2 is passed as an option', async ({page, server})
expect(error.message).toContain(`waitUntil: expected one of (load|domcontentloaded|networkidle)`);
});
it('should fail when main resources failed to load', async ({page}) => {
it('should fail when main resources failed to load', async ({page, isChromium, isWebKit}) => {
let error = null;
await page.goto('http://localhost:44123/non-existing-url').catch(e => error = e);
if (options.CHROMIUM)
if (isChromium)
expect(error.message).toContain('net::ERR_CONNECTION_REFUSED');
else if (options.WEBKIT && WIN)
else if (isWebKit && WIN)
expect(error.message).toContain(`Couldn\'t connect to server`);
else if (options.WEBKIT)
else if (isWebKit)
expect(error.message).toContain('Could not connect');
else
expect(error.message).toContain('NS_ERROR_CONNECTION_REFUSED');
@ -300,7 +300,7 @@ it('should disable timeout when its set to 0', async ({page, server}) => {
expect(loaded).toBe(true);
});
it('should fail when replaced by another navigation', async ({page, server}) => {
it('should fail when replaced by another navigation', async ({page, server, isChromium, isWebKit}) => {
let anotherPromise;
server.setRoute('/empty.html', (req, res) => {
anotherPromise = page.goto(server.PREFIX + '/one-style.html');
@ -308,9 +308,9 @@ it('should fail when replaced by another navigation', async ({page, server}) =>
});
const error = await page.goto(server.PREFIX + '/empty.html').catch(e => e);
await anotherPromise;
if (options.CHROMIUM)
if (isChromium)
expect(error.message).toContain('net::ERR_ABORTED');
else if (options.WEBKIT)
else if (isWebKit)
expect(error.message).toContain('cancelled');
else
expect(error.message).toContain('NS_BINDING_ABORTED');
@ -476,7 +476,7 @@ it('should fail when canceled by another navigation', async ({page, server}) =>
expect(error.message).toBeTruthy();
});
it('extraHttpHeaders should be pushed to provisional page', test => {
it('extraHttpHeaders should be pushed to provisional page', (test, parameters) => {
test.flaky('This test is flaky, because we cannot await page.setExtraHTTPHeaders.');
// We need a way to test our implementation by more than just public api.
}, async ({page, server}) => {

View file

@ -52,8 +52,8 @@ it('page.goBack should work with HistoryAPI', async ({page, server}) => {
expect(page.url()).toBe(server.PREFIX + '/first.html');
});
it('page.goBack should work for file urls', test => {
test.fail(options.WEBKIT && MAC);
it('page.goBack should work for file urls', (test, parameters) => {
test.fail(options.WEBKIT(parameters) && MAC);
}, async ({page, server, asset}) => {
// WebKit embedder fails to go back/forward to the file url.
const url1 = url.pathToFileURL(asset('empty.html')).href;

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should intercept', async ({page, server}) => {
let intercepted = false;
@ -183,15 +183,15 @@ it('should be abortable', async ({page, server}) => {
expect(failed).toBe(true);
});
it('should be abortable with custom error codes', async ({page, server}) => {
it('should be abortable with custom error codes', async ({page, server, isWebKit, isFirefox}) => {
await page.route('**/*', route => route.abort('internetdisconnected'));
let failedRequest = null;
page.on('requestfailed', request => failedRequest = request);
await page.goto(server.EMPTY_PAGE).catch(e => {});
expect(failedRequest).toBeTruthy();
if (options.WEBKIT)
if (isWebKit)
expect(failedRequest.failure().errorText).toBe('Request intercepted');
else if (options.FIREFOX)
else if (isFirefox)
expect(failedRequest.failure().errorText).toBe('NS_ERROR_OFFLINE');
else
expect(failedRequest.failure().errorText).toBe('net::ERR_INTERNET_DISCONNECTED');
@ -209,14 +209,14 @@ it('should send referer', async ({page, server}) => {
expect(request.headers['referer']).toBe('http://google.com/');
});
it('should fail navigation when aborting main resource', async ({page, server}) => {
it('should fail navigation when aborting main resource', async ({page, server, isWebKit, isFirefox}) => {
await page.route('**/*', route => route.abort());
let error = null;
await page.goto(server.EMPTY_PAGE).catch(e => error = e);
expect(error).toBeTruthy();
if (options.WEBKIT)
if (isWebKit)
expect(error.message).toContain('Request intercepted');
else if (options.FIREFOX)
else if (isFirefox)
expect(error.message).toContain('NS_ERROR_FAILURE');
else
expect(error.message).toContain('net::ERR_FAILED');

View file

@ -21,10 +21,9 @@ import path from 'path';
import fs from 'fs';
// Firefox headful produces a different image.
const ffheadful = options.FIREFOX && !options.HEADLESS;
describe('page screenshot', suite => {
suite.skip(ffheadful);
describe('page screenshot', (suite, parameters) => {
suite.skip(options.FIREFOX(parameters) && !options.HEADLESS);
}, () => {
it('should work', async ({page, server, golden}) => {
await page.setViewportSize({width: 500, height: 500});
@ -142,8 +141,8 @@ describe('page screenshot', suite => {
await Promise.all(pages.map(page => page.close()));
});
it('should allow transparency', test => {
test.fail(options.FIREFOX);
it('should allow transparency', (test, parameters) => {
test.fail(options.FIREFOX(parameters));
}, async ({page, golden}) => {
await page.setViewportSize({ width: 50, height: 150 });
await page.setContent(`
@ -178,8 +177,8 @@ describe('page screenshot', suite => {
expect(screenshot).toMatchImage(golden('screenshot-clip-odd-size.png'));
});
it('should work with a mobile viewport', test => {
test.skip(options.FIREFOX);
it('should work with a mobile viewport', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, golden}) => {
const context = await browser.newContext({ viewport: { width: 320, height: 480 }, isMobile: true });
const page = await context.newPage();
@ -189,8 +188,8 @@ describe('page screenshot', suite => {
await context.close();
});
it('should work with a mobile viewport and clip', test => {
test.skip(options.FIREFOX);
it('should work with a mobile viewport and clip', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, golden}) => {
const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true});
const page = await context.newPage();
@ -200,8 +199,8 @@ describe('page screenshot', suite => {
await context.close();
});
it('should work with a mobile viewport and fullPage', test => {
test.skip(options.FIREFOX);
it('should work with a mobile viewport and fullPage', (test, parameters) => {
test.skip(options.FIREFOX(parameters));
}, async ({browser, server, golden}) => {
const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true});
const page = await context.newPage();
@ -218,9 +217,9 @@ describe('page screenshot', suite => {
expect(screenshot).toMatchImage(golden('screenshot-canvas.png'), { threshold: 0.3 });
});
it('should work for webgl', test => {
test.fixme(options.FIREFOX);
test.fixme(options.WEBKIT && LINUX);
it('should work for webgl', (test, parameters) => {
test.fixme(options.FIREFOX(parameters));
test.fixme(options.WEBKIT(parameters) && LINUX);
}, async ({page, server, golden}) => {
await page.setViewportSize({width: 640, height: 480});
await page.goto(server.PREFIX + '/screenshots/webgl.html');

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
import type { Route } from '..';
it('should pick up ongoing navigation', async ({page, server}) => {
@ -69,7 +69,7 @@ it('should work with pages that have loaded before being connected to', async ({
expect(popup.url()).toBe(server.EMPTY_PAGE);
});
it('should wait for load state of empty url popup', async ({browser, page}) => {
it('should wait for load state of empty url popup', async ({page, isFirefox}) => {
const [popup, readyState] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(() => {
@ -78,8 +78,8 @@ it('should wait for load state of empty url popup', async ({browser, page}) => {
}),
]);
await popup.waitForLoadState();
expect(readyState).toBe(options.FIREFOX ? 'uninitialized' : 'complete');
expect(await popup.evaluate(() => document.readyState)).toBe(options.FIREFOX ? 'uninitialized' : 'complete');
expect(readyState).toBe(isFirefox ? 'uninitialized' : 'complete');
expect(await popup.evaluate(() => document.readyState)).toBe(isFirefox ? 'uninitialized' : 'complete');
});
it('should wait for load state of about:blank popup ', async ({browser, page}) => {

View file

@ -20,8 +20,8 @@ import fs from 'fs';
import path from 'path';
it('should be able to save file', test => {
test.skip(!(options.HEADLESS && options.CHROMIUM), 'Printing to pdf is currently only supported in headless chromium.');
it('should be able to save file', (test, parameters) => {
test.skip(!(options.HEADLESS && options.CHROMIUM(parameters)), 'Printing to pdf is currently only supported in headless chromium.');
}, async ({page, tmpDir}) => {
const outputFile = path.join(tmpDir, 'output.pdf');
await page.pdf({path: outputFile});
@ -29,8 +29,8 @@ it('should be able to save file', test => {
fs.unlinkSync(outputFile);
});
it('should only have pdf in chromium', test => {
test.skip(options.CHROMIUM);
it('should only have pdf in chromium', (test, parameters) => {
test.skip(options.CHROMIUM(parameters));
}, async ({page}) => {
expect(page.pdf).toBe(undefined);
});

View file

@ -21,8 +21,8 @@ function getPermission(page, name) {
return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name);
}
describe('permissions', suite => {
suite.skip(options.WEBKIT);
describe('permissions', (suite, parameters) => {
suite.skip(options.WEBKIT(parameters));
}, () => {
it('should be prompt by default', async ({page, server, context}) => {
// Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)
@ -101,10 +101,10 @@ describe('permissions', suite => {
expect(await getPermission(page, 'geolocation')).toBe('prompt');
});
it('should trigger permission onchange', test => {
test.fail(options.WEBKIT);
test.fail(options.CHROMIUM && !options.HEADLESS);
test.flaky(options.FIREFOX && LINUX);
it('should trigger permission onchange', (test, parameters) => {
test.fail(options.WEBKIT(parameters));
test.fail(options.CHROMIUM(parameters) && !options.HEADLESS);
test.flaky(options.FIREFOX(parameters) && LINUX);
}, async ({page, server, context}) => {
// TODO: flaky
// - Linux: https://github.com/microsoft/playwright/pull/1790/checks?check_run_id=587327883
@ -147,10 +147,10 @@ describe('permissions', suite => {
await otherContext.close();
});
it('should support clipboard read', test => {
test.fail(options.WEBKIT);
test.fail(options.FIREFOX, 'No such permissions (requires flag) in Firefox');
test.fixme(options.CHROMIUM && !options.HEADLESS);
it('should support clipboard read', (test, parameters) => {
test.fail(options.WEBKIT(parameters));
test.fail(options.FIREFOX(parameters), 'No such permissions (requires flag) in Firefox');
test.fixme(options.CHROMIUM(parameters) && !options.HEADLESS);
}, async ({page, server, context}) => {
await page.goto(server.EMPTY_PAGE);
expect(await getPermission(page, 'clipboard-read')).toBe('prompt');

View file

@ -26,19 +26,25 @@ import { installCoverageHooks } from './coverage';
import { mkdtempAsync, removeFolderAsync } from './utils';
import { fixtures as baseFixtures } from '@playwright/test-runner';
export type PlaywrightWorkerFixtures = {
type PlaywrightParameters = {
browserName: string;
};
type PlaywrightWorkerFixtures = {
asset: (path: string) => string;
defaultBrowserOptions: LaunchOptions;
golden: (path: string) => string;
playwright: typeof import('../index');
browserName: string;
browserType: BrowserType<Browser>;
browser: Browser;
httpService: {server: TestServer, httpsServer: TestServer}
toImpl: (rpcObject: any) => any;
isChromium: boolean;
isFirefox: boolean;
isWebKit: boolean;
};
export type PlaywrightFixtures = {
type PlaywrightFixtures = {
context: BrowserContext;
server: TestServer;
page: Page;
@ -47,8 +53,12 @@ export type PlaywrightFixtures = {
launchPersistent: (options?: Parameters<BrowserType<Browser>['launchPersistentContext']>[1]) => Promise<{context: BrowserContext, page: Page}>;
};
const fixtures = baseFixtures.extend<PlaywrightWorkerFixtures, PlaywrightFixtures>();
const { registerFixture, registerWorkerFixture } = fixtures;
const fixtures = baseFixtures
.declareParameters<PlaywrightParameters>()
.declareWorkerFixtures<PlaywrightWorkerFixtures>()
.declareTestFixtures<PlaywrightFixtures>();
const { defineTestFixture, defineWorkerFixture, defineParameter } = fixtures;
export const playwrightFixtures = fixtures;
export const it = fixtures.it;
export const fit = fixtures.fit;
@ -63,9 +73,9 @@ export const afterAll = fixtures.afterAll;
export const expect = fixtures.expect;
export const options = {
CHROMIUM: fixtures.parameters.browserName === 'chromium',
FIREFOX: fixtures.parameters.browserName === 'firefox',
WEBKIT: fixtures.parameters.browserName === 'webkit',
CHROMIUM: parameters => parameters.browserName === 'chromium',
FIREFOX: parameters => parameters.browserName === 'firefox',
WEBKIT: parameters => parameters.browserName === 'webkit',
HEADLESS: !!valueFromEnv('HEADLESS', true),
WIRE: !!process.env.PWWIRE,
SLOW_MO: valueFromEnv('SLOW_MO', 0),
@ -83,7 +93,7 @@ global['MAC'] = platform === 'darwin';
global['LINUX'] = platform === 'linux';
global['WIN'] = platform === 'win32';
registerWorkerFixture('httpService', async ({parallelIndex}, test) => {
defineWorkerFixture('httpService', async ({parallelIndex}, test) => {
const assetsPath = path.join(__dirname, 'assets');
const cachedPath = path.join(__dirname, 'assets', 'cached');
@ -112,7 +122,7 @@ const getExecutablePath = browserName => {
return process.env.WKPATH;
};
registerWorkerFixture('defaultBrowserOptions', async ({browserName}, test) => {
defineWorkerFixture('defaultBrowserOptions', async ({browserName}, test) => {
const executablePath = getExecutablePath(browserName);
if (executablePath)
@ -125,7 +135,7 @@ registerWorkerFixture('defaultBrowserOptions', async ({browserName}, test) => {
});
});
registerWorkerFixture('playwright', async ({browserName}, test) => {
defineWorkerFixture('playwright', async ({browserName, parallelIndex}, test) => {
const {coverage, uninstall} = installCoverageHooks(browserName);
if (options.WIRE) {
require('../lib/utils/utils').setUnderTest();
@ -163,27 +173,37 @@ registerWorkerFixture('playwright', async ({browserName}, test) => {
async function teardownCoverage() {
uninstall();
const coveragePath = path.join(__dirname, 'coverage-report', fixtures.parameters.parallelIndex + '.json');
const coveragePath = path.join(__dirname, 'coverage-report', parallelIndex + '.json');
const coverageJSON = [...coverage.keys()].filter(key => coverage.get(key));
await fs.promises.mkdir(path.dirname(coveragePath), { recursive: true });
await fs.promises.writeFile(coveragePath, JSON.stringify(coverageJSON, undefined, 2), 'utf8');
}
});
registerWorkerFixture('toImpl', async ({playwright}, test) => {
defineWorkerFixture('toImpl', async ({playwright}, test) => {
await test((playwright as any)._toImpl);
});
registerWorkerFixture('browserType', async ({playwright, browserName}, test) => {
defineWorkerFixture('browserType', async ({playwright, browserName}, test) => {
const browserType = playwright[browserName];
await test(browserType);
});
registerWorkerFixture('browserName', async ({}, test) => {
throw new Error(`Parameter 'browserName' is not specified`);
defineParameter('browserName', 'Browser type name', '');
defineWorkerFixture('isChromium', async ({browserName}, test) => {
await test(browserName === 'chromium');
});
registerWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => {
defineWorkerFixture('isFirefox', async ({browserName}, test) => {
await test(browserName === 'firefox');
});
defineWorkerFixture('isWebKit', async ({browserName}, test) => {
await test(browserName === 'webkit');
});
defineWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => {
const browser = await browserType.launch(defaultBrowserOptions);
await test(browser);
if (browser.contexts().length !== 0) {
@ -193,15 +213,15 @@ registerWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, te
await browser.close();
});
registerWorkerFixture('asset', async ({}, test) => {
defineWorkerFixture('asset', async ({}, test) => {
await test(p => path.join(__dirname, `assets`, p));
});
registerWorkerFixture('golden', async ({browserName}, test) => {
defineWorkerFixture('golden', async ({browserName}, test) => {
await test(p => path.join(browserName, p));
});
registerFixture('context', async ({browser, playwright, toImpl}, runTest, info) => {
defineTestFixture('context', async ({browser, playwright, toImpl}, runTest, info) => {
const context = await browser.newContext();
const { test, config } = info;
if ((playwright as any).__tracer) {
@ -215,7 +235,7 @@ registerFixture('context', async ({browser, playwright, toImpl}, runTest, info)
await context.close();
});
registerFixture('page', async ({context, playwright, toImpl}, runTest, info) => {
defineTestFixture('page', async ({context, playwright, toImpl}, runTest, info) => {
const page = await context.newPage();
await runTest(page);
const { test, config, result } = info;
@ -229,7 +249,7 @@ registerFixture('page', async ({context, playwright, toImpl}, runTest, info) =>
}
});
registerFixture('launchPersistent', async ({tmpDir, defaultBrowserOptions, browserType}, test) => {
defineTestFixture('launchPersistent', async ({tmpDir, defaultBrowserOptions, browserType}, test) => {
let context;
async function launchPersistent(options) {
if (context)
@ -243,17 +263,17 @@ registerFixture('launchPersistent', async ({tmpDir, defaultBrowserOptions, brows
await context.close();
});
registerFixture('server', async ({httpService}, test) => {
defineTestFixture('server', async ({httpService}, test) => {
httpService.server.reset();
await test(httpService.server);
});
registerFixture('httpsServer', async ({httpService}, test) => {
defineTestFixture('httpsServer', async ({httpService}, test) => {
httpService.httpsServer.reset();
await test(httpService.httpsServer);
});
registerFixture('tmpDir', async ({}, test) => {
defineTestFixture('tmpDir', async ({}, test) => {
const tmpDir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-'));
await test(tmpDir);
await removeFolderAsync(tmpDir).catch(e => {});

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('should inherit user agent from browser context', async function({browser, server}) {
const context = await browser.newContext({
@ -210,7 +210,7 @@ it('should expose function from browser context', async function({browser, serve
expect(messages.join('|')).toBe('page|binding');
});
it('should not dispatch binding on a closed page', async function({browser, server}) {
it('should not dispatch binding on a closed page', async function({browser, server, isFirefox}) {
const context = await browser.newContext();
const messages = [];
await context.exposeFunction('add', (a, b) => {
@ -233,7 +233,7 @@ it('should not dispatch binding on a closed page', async function({browser, serv
}),
]);
await context.close();
if (options.FIREFOX)
if (isFirefox)
expect(messages.join('|')).toBe('close');
else
expect(messages.join('|')).toBe('binding|close');

View file

@ -77,8 +77,8 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) =
await browser.close();
});
it('should exclude patterns', test => {
test.flaky(options.CHROMIUM && !options.HEADLESS, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.');
it('should exclude patterns', (test, parameters) => {
test.flaky(options.CHROMIUM(parameters) && !options.HEADLESS, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.');
}, async ({browserType, defaultBrowserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
@ -119,8 +119,8 @@ it('should exclude patterns', test => {
await browser.close();
});
it('should use socks proxy', test => {
test.flaky(MAC && options.WEBKIT, 'Intermittent page.goto: The network connection was lost error on bots');
it('should use socks proxy', (test, parameters) => {
test.flaky(MAC && options.WEBKIT(parameters), 'Intermittent page.goto: The network connection was lost error on bots');
}, async ({ browserType, defaultBrowserOptions, parallelIndex }) => {
const server = socks.createServer((info, accept, deny) => {
let socket;

View file

@ -24,8 +24,8 @@ type ServerFixtures = {
remoteServer: RemoteServer;
stallingRemoteServer: RemoteServer;
};
export const serverFixtures = playwrightFixtures.extend<{}, ServerFixtures>();
const { registerFixture } = serverFixtures;
export const serverFixtures = playwrightFixtures.declareTestFixtures<ServerFixtures>();
const { defineTestFixture } = serverFixtures;
const playwrightPath = path.join(__dirname, '..');
@ -116,14 +116,14 @@ export class RemoteServer {
}
}
registerFixture('remoteServer', async ({browserType, defaultBrowserOptions}, test) => {
defineTestFixture('remoteServer', async ({browserType, defaultBrowserOptions}, test) => {
const remoteServer = new RemoteServer();
await remoteServer._start(browserType, defaultBrowserOptions);
await test(remoteServer);
await remoteServer.close();
});
registerFixture('stallingRemoteServer', async ({browserType, defaultBrowserOptions}, test) => {
defineTestFixture('stallingRemoteServer', async ({browserType, defaultBrowserOptions}, test) => {
const remoteServer = new RemoteServer();
await remoteServer._start(browserType, defaultBrowserOptions, { stallOnClose: true });
await test(remoteServer);

View file

@ -50,8 +50,8 @@ it('should work with status code 422', async ({page, server}) => {
expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!');
});
it('should allow mocking binary responses', test => {
test.skip(options.FIREFOX && !options.HEADLESS, '// Firefox headful produces a different image.');
it('should allow mocking binary responses', (test, parameters) => {
test.skip(options.FIREFOX(parameters) && !options.HEADLESS, '// Firefox headful produces a different image.');
}, async ({page, server, golden}) => {
await page.route('**/*', route => {
const imageBuffer = fs.readFileSync(path.join(__dirname, 'assets', 'pptr.png'));
@ -70,8 +70,8 @@ it('should allow mocking binary responses', test => {
expect(await img.screenshot()).toMatchImage(golden('mock-binary-response.png'));
});
it('should allow mocking svg with charset', test => {
test.skip(options.FIREFOX && !options.HEADLESS, '// Firefox headful produces a different image.');
it('should allow mocking svg with charset', (test, parameters) => {
test.skip(options.FIREFOX(parameters) && !options.HEADLESS, '// Firefox headful produces a different image.');
}, async ({page, server, golden}) => {
// Firefox headful produces a different image.
await page.route('**/*', route => {

View file

@ -24,10 +24,10 @@ import { TestServer } from '../utils/testserver';
type TestState = {
videoPlayer: VideoPlayer;
};
const fixtures = playwrightFixtures.extend<{}, TestState>();
const { it, expect, describe, registerFixture } = fixtures;
const fixtures = playwrightFixtures.declareTestFixtures<TestState>();
const { it, expect, describe, defineTestFixture } = fixtures;
registerFixture('videoPlayer', async ({playwright, context, server}, test) => {
defineTestFixture('videoPlayer', async ({playwright, context, server}, test) => {
// WebKit on Mac & Windows cannot replay webm/vp8 video, is unrelyable
// on Linux (times out) and in Firefox, so we always launch chromium for
// playback.
@ -181,7 +181,7 @@ describe('screencast', suite => {
expectAll(pixels, almostRed);
});
it('should capture navigation', test => {
it('should capture navigation', (test, parameters) => {
test.flaky();
}, async ({page, tmpDir, server, videoPlayer, toImpl}) => {
const videoFile = path.join(tmpDir, 'v.webm');
@ -210,8 +210,8 @@ describe('screencast', suite => {
}
});
it('should capture css transformation', test => {
test.fail(options.WEBKIT && WIN, 'Does not work on WebKit Windows');
it('should capture css transformation', (test, parameters) => {
test.fail(options.WEBKIT(parameters) && WIN, 'Does not work on WebKit Windows');
}, async ({page, tmpDir, server, videoPlayer, toImpl}) => {
const videoFile = path.join(tmpDir, 'v.webm');
// Set viewport equal to screencast frame size to avoid scaling.

View file

@ -15,9 +15,9 @@
* limitations under the License.
*/
import { it, expect, options } from './playwright.fixtures';
import { it, expect } from './playwright.fixtures';
it('query', async ({page}) => {
it('query', async ({page, isWebKit}) => {
await page.setContent(`<div>yo</div><div>ya</div><div>\nye </div>`);
expect(await page.$eval(`text=ya`, e => e.outerHTML)).toBe('<div>ya</div>');
expect(await page.$eval(`text="ya"`, e => e.outerHTML)).toBe('<div>ya</div>');
@ -59,9 +59,9 @@ it('query', async ({page}) => {
expect(await page.$eval(`"x"`, e => e.outerHTML)).toBe('<div>x</div>');
expect(await page.$eval(`'x'`, e => e.outerHTML)).toBe('<div>x</div>');
let error = await page.$(`"`).catch(e => e);
expect(error.message).toContain(options.WEBKIT ? 'SyntaxError' : 'querySelector');
expect(error.message).toContain(isWebKit ? 'SyntaxError' : 'querySelector');
error = await page.$(`'`).catch(e => e);
expect(error.message).toContain(options.WEBKIT ? 'SyntaxError' : 'querySelector');
expect(error.message).toContain(isWebKit ? 'SyntaxError' : 'querySelector');
await page.setContent(`<div> ' </div><div> " </div>`);
expect(await page.$eval(`text="`, e => e.outerHTML)).toBe('<div> " </div>');

View file

@ -14,16 +14,6 @@
* limitations under the License.
*/
declare const before: (f: () => Promise<any>) => void;
declare const after: (f: () => Promise<any>) => void;
declare const matrix: (m: any) => void;
matrix({
'browserName': process.env.BROWSER ? [process.env.BROWSER] : ['chromium', 'webkit', 'firefox'],
});
before(async () => {
});
after(async () => {
});
(global as any).setParameterValues(
'browserName',
process.env.BROWSER ? [process.env.BROWSER] : ['chromium', 'webkit', 'firefox']);

View file

@ -16,7 +16,7 @@
import { it, options } from './playwright.fixtures';
it('should not throw', test => {
it('should not throw', (test, parameters) => {
test.skip(!options.TRACING);
}, async ({page, server, playwright, toImpl}) => {
await page.goto(server.PREFIX + '/snapshot/snapshot-with-css.html');

View file

@ -145,7 +145,7 @@ const utils = module.exports = {
},
});
testRunner.on('testfinished', test => {
testRunner.on('testfinished', (test, parameters) => {
// Do not report tests from COVERAGE testsuite.
// They don't bring much value to us.
if (test.fullName.includes('**API COVERAGE**'))

View file

@ -21,9 +21,9 @@ const Source = require('../../Source');
const mdBuilder = require('../MDBuilder');
const jsBuilder = require('../JSBuilder');
const { fixtures } = require('@playwright/test-runner');
const { registerWorkerFixture, describe, it, expect } = fixtures;
const { defineWorkerFixture, describe, it, expect } = fixtures;
registerWorkerFixture('page', async({}, test) => {
defineWorkerFixture('page', async({}, test) => {
const browser = await playwright.chromium.launch();
const page = await browser.newPage();
await test(page);