test: roll to folio@0.4.0-alpha6 (#6366)

This commit is contained in:
Dmitry Gozman 2021-04-30 13:26:13 -07:00 committed by GitHub
parent 29164a625f
commit de21a94b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 178 additions and 281 deletions

6
package-lock.json generated
View File

@ -8140,9 +8140,9 @@
}
},
"folio": {
"version": "0.4.0-alpha4",
"resolved": "https://registry.npmjs.org/folio/-/folio-0.4.0-alpha4.tgz",
"integrity": "sha512-/M8DQEPg2H6HuBgcCN8A5xa/s7wS5Dsu9F0jUHXv6dft+qvgMQY9TWi998EWZ7jn7SxakBnpLRUPbrLFiyIK0g==",
"version": "0.4.0-alpha6",
"resolved": "https://registry.npmjs.org/folio/-/folio-0.4.0-alpha6.tgz",
"integrity": "sha512-UzL9iFvumPbcsrfObkQX0AbGUNGRzgFY+IyRluHlVzhF2aaa5jEoq/ZPDNPgJwDBvKdyO026+qQ2rNzHv5KnaA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",

View File

@ -87,7 +87,7 @@
"eslint-plugin-notice": "^0.9.10",
"eslint-plugin-react-hooks": "^4.2.0",
"file-loader": "^6.1.0",
"folio": "=0.4.0-alpha4",
"folio": "=0.4.0-alpha6",
"formidable": "^1.2.2",
"html-webpack-plugin": "^4.4.1",
"ncp": "^2.0.0",

View File

@ -18,9 +18,7 @@
import { browserTest as it, expect } from './config/browserTest';
it.describe('device', () => {
it.beforeEach(async ({browserName}) => {
it.skip(browserName === 'firefox');
});
it.skip(({ browserName }) => browserName === 'firefox');
it('should work', async ({playwright, browser, server}) => {
const iPhone = playwright.devices['iPhone 6'];

View File

@ -18,9 +18,8 @@ import { browserTest as it, expect } from './config/browserTest';
import type { Browser } from '../index';
let browser: Browser;
it.beforeEach(async ({ browserType, browserOptions }) => {
if (!browser)
browser = await browserType.launch({ ...browserOptions, proxy: { server: 'per-context' } });
it.beforeAll(async ({ browserType, browserOptions }) => {
browser = await browserType.launch({ ...browserOptions, proxy: { server: 'per-context' } });
});
it.afterAll(async () => {
await browser.close();

View File

@ -18,9 +18,7 @@
import { browserTest as it, expect } from './config/browserTest';
it.describe('mobile viewport', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(browserName === 'firefox');
});
it.skip(({ browserName }) => browserName === 'firefox');
it('should support mobile emulation', async ({playwright, browser, server}) => {
const iPhone = playwright.devices['iPhone 6'];

View File

@ -19,10 +19,8 @@ import { test as it, expect } from './config/pageTest';
import { browserTest } from './config/browserTest';
import { verifyViewport } from './config/utils';
it.beforeEach(async ({ isElectron, isAndroid }) => {
it.skip(isAndroid, 'Default viewport is null');
it.skip(isElectron, 'Default viewport is null');
});
it.skip(({ isAndroid }) => isAndroid, 'Default viewport is null');
it.skip(({ isElectron }) => isElectron, 'Default viewport is null');
it('should get the proper default viewport size', async ({page, server}) => {
await verifyViewport(page, 1280, 720);

View File

@ -18,9 +18,7 @@
import { playwrightTest as it, expect } from './config/browserTest';
it.describe('launch server', () => {
it.beforeEach(async ({ mode}) => {
it.skip(mode !== 'default');
});
it.skip(({ mode}) => mode !== 'default');
it('should work', async ({browserType, browserOptions}) => {
const browserServer = await browserType.launchServer(browserOptions);

View File

@ -20,11 +20,9 @@ import { playwrightTest } from '../config/browserTest';
import http from 'http';
pageTest.describe('chromium', () => {
pageTest.beforeEach(async ({ browserName, isElectron, isAndroid }) => {
pageTest.skip(browserName !== 'chromium');
pageTest.skip(isAndroid);
pageTest.skip(isElectron);
});
pageTest.skip(({ browserName }) => browserName !== 'chromium');
pageTest.skip(({ isAndroid }) => isAndroid);
pageTest.skip(({ isElectron }) => isElectron);
pageTest('should create a worker from a service worker', async ({page, server}) => {
const [worker] = await Promise.all([
@ -85,9 +83,7 @@ pageTest.describe('chromium', () => {
});
playwrightTest.describe('chromium', () => {
playwrightTest.beforeEach(async ({ browserName }) => {
playwrightTest.skip(browserName !== 'chromium');
});
playwrightTest.skip(({ browserName }) => browserName !== 'chromium');
playwrightTest('should close service worker together with the context', async ({browserType, browserOptions, server}) => {
const browser = await browserType.launch(browserOptions);

View File

@ -17,9 +17,7 @@
import { test as it, expect } from '../config/pageTest';
it.describe('CSS Coverage', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(browserName !== 'chromium');
});
it.skip(({ browserName }) => browserName !== 'chromium');
it('should work', async function({page, server}) {
await page.coverage.startCSSCoverage();

View File

@ -17,10 +17,8 @@
import { test as it, expect } from '../config/pageTest';
it.describe('JS Coverage', () => {
it.beforeEach(async ({ browserName, isElectron }) => {
it.skip(browserName !== 'chromium');
it.fixme(isElectron);
});
it.skip(({ browserName }) => browserName !== 'chromium');
it.fixme(({ isElectron }) => isElectron);
it('should work', async function({page, server}) {
await page.coverage.startJSCoverage();

View File

@ -16,9 +16,7 @@
import { playwrightTest as it, expect } from '../config/browserTest';
it.beforeEach(async ({ browserName }) => {
it.skip(browserName !== 'chromium');
});
it.skip(({ browserName }) => browserName !== 'chromium');
it('should throw with remote-debugging-pipe argument', async ({browserType, browserOptions, mode}) => {
it.skip(mode !== 'default');

View File

@ -14,41 +14,42 @@
* limitations under the License.
*/
import { playwrightTest as it, expect } from '../config/browserTest';
import type { Browser, Page } from '../../index';
import { playwrightTest, expect } from '../config/browserTest';
import type { Page } from '../../index';
const it = playwrightTest.extend({
async beforeAll({ browserType, browserOptions, browserName }) {
const browser = await browserType.launch({
...browserOptions,
args: browserName === 'chromium' ? (browserOptions.args || []).concat(['--site-per-process']) : browserOptions.args,
});
this.browser = browser;
return { browser };
},
async beforeEach() {
const page = await this.browser.newPage() as Page;
this.page = page;
return { page };
},
async afterEach() {
await this.page.close();
},
async afterAll() {
await this.browser.close();
},
});
it.describe('oopif', () => {
let browser: Browser;
let page: Page;
it.skip(({ browserName }) => browserName !== 'chromium');
it.beforeEach(async ({ browserName, browserType, browserOptions }) => {
it.skip(browserName !== 'chromium');
if (!browser) {
browser = await browserType.launch({
...browserOptions,
args: (browserOptions.args || []).concat(['--site-per-process'])
});
}
page = await browser.newPage();
});
it.afterEach(async () => {
await page.close();
});
it.afterAll(async () => {
await browser.close();
});
it('should report oopif frames', async function({server}) {
it('should report oopif frames', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(await countOOPIFs(browser)).toBe(1);
expect(page.frames().length).toBe(2);
expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
});
it('should handle oopif detach', async function({server}) {
it('should handle oopif detach', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(await countOOPIFs(browser)).toBe(1);
expect(page.frames().length).toBe(2);
@ -61,7 +62,7 @@ it.describe('oopif', () => {
expect(detachedFrame).toBe(frame);
});
it('should handle remote -> local -> remote transitions', async function({server}) {
it('should handle remote -> local -> remote transitions', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2);
expect(await countOOPIFs(browser)).toBe(1);
@ -80,7 +81,7 @@ it.describe('oopif', () => {
expect(await countOOPIFs(browser)).toBe(1);
});
it('should get the proper viewport', async ({server}) => {
it('should get the proper viewport', async ({page, browser, server}) => {
it.fixme();
expect(page.viewportSize()).toEqual({width: 1280, height: 720});
@ -101,7 +102,7 @@ it.describe('oopif', () => {
expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(false);
});
it('should expose function', async ({server}) => {
it('should expose function', async ({page, browser, server}) => {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2);
expect(await countOOPIFs(browser)).toBe(1);
@ -113,7 +114,7 @@ it.describe('oopif', () => {
expect(result).toBe(36);
});
it('should emulate media', async ({server}) => {
it('should emulate media', async ({page, browser, server}) => {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2);
expect(await countOOPIFs(browser)).toBe(1);
@ -123,7 +124,7 @@ it.describe('oopif', () => {
expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
});
it('should emulate offline', async ({server}) => {
it('should emulate offline', async ({page, browser, server}) => {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2);
expect(await countOOPIFs(browser)).toBe(1);
@ -133,7 +134,7 @@ it.describe('oopif', () => {
expect(await oopif.evaluate(() => navigator.onLine)).toBe(false);
});
it('should support context options', async ({server, playwright}) => {
it('should support context options', async ({browser, server, playwright}) => {
const iPhone = playwright.devices['iPhone 6'];
const context = await browser.newContext({ ...iPhone, timezoneId: 'America/Jamaica', locale: 'fr-CH', userAgent: 'UA' });
const page = await context.newPage();
@ -155,7 +156,7 @@ it.describe('oopif', () => {
await context.close();
});
it('should respect route', async ({server}) => {
it('should respect route', async ({page, browser, server}) => {
let intercepted = false;
await page.route('**/digits/0.png', route => {
intercepted = true;
@ -167,7 +168,7 @@ it.describe('oopif', () => {
expect(intercepted).toBe(true);
});
it('should take screenshot', async ({server}) => {
it('should take screenshot', async ({page, browser, server}) => {
await page.setViewportSize({width: 500, height: 500});
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2);
@ -175,13 +176,13 @@ it.describe('oopif', () => {
expect(await page.screenshot()).toMatchSnapshot('screenshot-oopif.png', { threshold: 0.3 });
});
it('should load oopif iframes with subresources and route', async function({server}) {
it('should load oopif iframes with subresources and route', async function({page, browser, server}) {
await page.route('**/*', route => route.continue());
await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(await countOOPIFs(browser)).toBe(1);
});
it('should report main requests', async function({server}) {
it('should report main requests', async function({page, browser, server}) {
const requestFrames = [];
page.on('request', r => requestFrames.push(r.frame()));
const finishedFrames = [];
@ -219,7 +220,7 @@ it.describe('oopif', () => {
expect(finishedFrames[2]).toBe(grandChild);
});
it('should support exposeFunction', async function({server}) {
it('should support exposeFunction', async function({page, browser, server}) {
await page.context().exposeFunction('dec', a => a - 1);
await page.exposeFunction('inc', a => a + 1);
await page.goto(server.PREFIX + '/dynamic-oopif.html');
@ -231,7 +232,7 @@ it.describe('oopif', () => {
expect(await page.frames()[1].evaluate(() => window['dec'](4))).toBe(3);
});
it('should support addInitScript', async function({server}) {
it('should support addInitScript', async function({page, browser, server}) {
await page.context().addInitScript(() => window['bar'] = 17);
await page.addInitScript(() => window['foo'] = 42);
await page.goto(server.PREFIX + '/dynamic-oopif.html');
@ -243,7 +244,7 @@ it.describe('oopif', () => {
expect(await page.frames()[1].evaluate(() => window['bar'])).toBe(17);
});
// @see https://github.com/microsoft/playwright/issues/1240
it('should click a button when it overlays oopif', async function({server}) {
it('should click a button when it overlays oopif', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/button-overlay-oopif.html');
expect(await countOOPIFs(browser)).toBe(1);
await page.click('button');
@ -275,7 +276,7 @@ it.describe('oopif', () => {
await browser.close();
});
it('ElementHandle.boundingBox() should work', async function({server}) {
it('ElementHandle.boundingBox() should work', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
await page.$eval('iframe', iframe => {
iframe.style.width = '500px';
@ -298,7 +299,7 @@ it.describe('oopif', () => {
expect(await handle2.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
});
it('should click', async function({server}) {
it('should click', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');
await page.$eval('iframe', iframe => {
iframe.style.width = '500px';

View File

@ -18,9 +18,7 @@ import { test as it, expect } from '../config/pageTest';
import { browserTest } from '../config/browserTest';
it.describe('session', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(browserName !== 'chromium');
});
it.skip(({ browserName }) => browserName !== 'chromium');
it('should work', async function({page}) {
const client = await page.context().newCDPSession(page);
@ -95,9 +93,7 @@ it.describe('session', () => {
});
browserTest.describe('session', () => {
browserTest.beforeEach(async ({ browserName }) => {
browserTest.skip(browserName !== 'chromium');
});
browserTest.skip(({ browserName }) => browserName !== 'chromium');
browserTest('should not break page.close()', async function({browser}) {
const context = await browser.newContext();

View File

@ -19,9 +19,7 @@ import fs from 'fs';
import path from 'path';
it.describe('tracing', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(browserName !== 'chromium');
});
it.skip(({ browserName }) => browserName !== 'chromium');
it('should output a trace', async ({browser, server}, testInfo) => {
const page = await browser.newPage();

View File

@ -18,10 +18,8 @@ import { cliTest as test, expect } from '../config/cliTest';
import * as http from 'http';
test.describe('cli codegen', () => {
test.beforeEach(async ({ mode, browserName, headful }) => {
test.skip(mode !== 'default');
test.fixme(browserName === 'firefox' && headful, 'Focus is off');
});
test.skip(({ mode }) => mode !== 'default');
test.fixme(({ browserName, headful }) => browserName === 'firefox' && headful, 'Focus is off');
test('should click', async ({ page, openRecorder }) => {
const recorder = await openRecorder();

View File

@ -19,9 +19,7 @@ import * as http from 'http';
import * as url from 'url';
test.describe('cli codegen', () => {
test.beforeEach(async ({ mode }) => {
test.skip(mode !== 'default');
});
test.skip(({ mode }) => mode !== 'default');
test('should contain open page', async ({ openRecorder }) => {
const recorder = await openRecorder();

View File

@ -51,7 +51,7 @@ class AndroidPageEnv extends AndroidEnv {
async beforeEach(args: any, testInfo: folio.TestInfo) {
const result = await super.beforeEach(args, testInfo);
const page = await this._context!.newPage();
return { ...result, browserVersion: this._browserVersion, browserMajorVersion: this._browserMajorVersion, page };
return { ...result, browserVersion: this._browserVersion, browserMajorVersion: this._browserMajorVersion, page, isAndroid: true, isElectron: false };
}
async afterEach({}, testInfo: folio.TestInfo) {
@ -64,7 +64,7 @@ const envConfig = {
tag: 'android',
options: {
mode: 'default' as const,
engine: 'android' as const,
browserName: 'chromium' as const,
loopback: '10.0.2.2',
}
};

View File

@ -15,7 +15,7 @@
*/
import type { AndroidDevice } from '../../index';
import { CommonWorkerArgs, test as baseTest } from './baseTest';
import { CommonArgs, baseTest } from './baseTest';
import * as folio from 'folio';
export { expect } from 'folio';
@ -28,7 +28,7 @@ export class AndroidEnv {
protected _browserVersion: string;
protected _browserMajorVersion: number;
async beforeAll(args: CommonWorkerArgs, workerInfo: folio.WorkerInfo) {
async beforeAll(args: CommonArgs, workerInfo: folio.WorkerInfo) {
this._device = (await args.playwright._android.devices())[0];
await this._device.shell('am force-stop org.chromium.webview_shell');
await this._device.shell('am force-stop com.android.chrome');

View File

@ -26,7 +26,7 @@ import { PlaywrightClient } from '../../lib/remote/playwrightClient';
export type BrowserName = 'chromium' | 'firefox' | 'webkit';
type Mode = 'default' | 'driver' | 'service';
type BaseTestArgs = {
type BaseWorkerArgs = {
mode: Mode;
platform: 'win32' | 'darwin' | 'linux';
video: boolean;
@ -40,22 +40,14 @@ type BaseTestArgs = {
isChromium: boolean;
isFirefox: boolean;
isWebKit: boolean;
isAndroid: boolean;
isElectron: boolean;
isWindows: boolean;
isMac: boolean;
isLinux: boolean;
};
type BaseWorkerArgs = {
playwright: typeof import('../../index');
browserName: BrowserName;
channel: string | undefined;
};
type BaseOptions = {
mode: Mode;
engine: 'chromium' | 'firefox' | 'webkit' | 'android' | 'electron';
browserName: BrowserName;
channel?: string;
video?: boolean;
headful?: boolean;
@ -128,10 +120,6 @@ class BaseEnv {
return {} as any;
}
private _browserName(): BrowserName {
return (this._options.engine === 'android' || this._options.engine === 'electron') ? 'chromium' : this._options.engine;
}
async beforeAll(options: BaseOptions, workerInfo: folio.WorkerInfo): Promise<BaseWorkerArgs> {
this._options = options;
this._mode = {
@ -143,32 +131,11 @@ class BaseEnv {
this._playwright = await this._mode.setup(workerInfo);
return {
playwright: this._playwright,
browserName: this._browserName(),
channel: this._options.channel,
};
}
async beforeEach({}, testInfo: folio.TestInfo): Promise<BaseTestArgs> {
const browserName = this._browserName();
testInfo.snapshotPathSegment = browserName;
testInfo.data = {
browserName,
};
if (this._options.headful)
testInfo.data.headful = true;
if (this._options.mode !== 'default')
testInfo.data.mode = this._options.mode;
if (this._options.video)
testInfo.data.video = true;
return {
playwright: this._playwright,
browserName,
browserName: this._options.browserName,
browserChannel: this._options.channel,
isChromium: browserName === 'chromium',
isFirefox: browserName === 'firefox',
isWebKit: browserName === 'webkit',
isAndroid: this._options.engine === 'android',
isElectron: this._options.engine === 'electron',
isChromium: this._options.browserName === 'chromium',
isFirefox: this._options.browserName === 'firefox',
isWebKit: this._options.browserName === 'webkit',
isWindows: process.platform === 'win32',
isMac: process.platform === 'darwin',
isLinux: process.platform === 'linux',
@ -180,12 +147,24 @@ class BaseEnv {
};
}
async beforeEach({}, testInfo: folio.TestInfo) {
testInfo.snapshotPathSegment = this._options.browserName;
testInfo.data = { browserName: this._options.browserName };
if (this._options.headful)
testInfo.data.headful = true;
if (this._options.mode !== 'default')
testInfo.data.mode = this._options.mode;
if (this._options.video)
testInfo.data.video = true;
return {};
}
async afterAll({}, workerInfo: folio.WorkerInfo) {
await this._mode.teardown();
}
}
type ServerTestArgs = {
type ServerWorkerArgs = {
asset: (path: string) => string;
socksPort: number;
server: TestServer;
@ -237,12 +216,6 @@ class ServerEnv {
this._socksPort = port + 2;
this._socksServer.listen(this._socksPort, 'localhost');
this._socksServer.useAuth(socks.auth.None());
return {};
}
async beforeEach({}, testInfo: folio.TestInfo): Promise<ServerTestArgs> {
this._server.reset();
this._httpsServer.reset();
return {
asset: (p: string) => path.join(__dirname, '..', 'assets', ...p.split('/')),
server: this._server,
@ -251,6 +224,12 @@ class ServerEnv {
};
}
async beforeEach({}, testInfo: folio.TestInfo) {
this._server.reset();
this._httpsServer.reset();
return {};
}
async afterAll({}, workerInfo: folio.WorkerInfo) {
await Promise.all([
this._server.stop(),
@ -290,7 +269,6 @@ class CoverageEnv {
}
export type CommonOptions = BaseOptions;
export type CommonTestArgs = BaseTestArgs & ServerTestArgs;
export type CommonWorkerArgs = BaseWorkerArgs;
export type CommonArgs = BaseWorkerArgs & ServerWorkerArgs;
export const test = folio.test.extend(new CoverageEnv()).extend(new ServerEnv()).extend(new BaseEnv());
export const baseTest = folio.test.extend(new CoverageEnv()).extend(new ServerEnv()).extend(new BaseEnv());

View File

@ -22,13 +22,11 @@ import * as fs from 'fs';
import * as os from 'os';
import * as util from 'util';
import { RemoteServer, RemoteServerOptions } from './remoteServer';
import { CommonOptions, CommonTestArgs, CommonWorkerArgs, test as baseTest } from './baseTest';
import { CommonArgs, baseTest } from './baseTest';
const mkdtempAsync = util.promisify(fs.mkdtemp);
type PlaywrightTestArgs = {
browserType: BrowserType;
browserOptions: LaunchOptions;
createUserDataDir: () => Promise<string>;
launchPersistent: (options?: Parameters<BrowserType['launchPersistentContext']>[1]) => Promise<{ context: BrowserContext, page: Page }>;
startRemoteServer: (options?: RemoteServerOptions) => Promise<RemoteServer>;
@ -39,7 +37,7 @@ type PlaywrightEnvOptions = {
traceDir?: string;
};
type PlaywrightEnvWorkerArgs = {
type PlaywrightWorkerArgs = {
browserType: BrowserType;
browserOptions: LaunchOptions;
};
@ -55,12 +53,12 @@ class PlaywrightEnv {
return {};
}
async beforeAll(args: CommonWorkerArgs & PlaywrightEnvOptions & CommonOptions, workerInfo: folio.WorkerInfo): Promise<PlaywrightEnvWorkerArgs> {
async beforeAll(args: CommonArgs & PlaywrightEnvOptions, workerInfo: folio.WorkerInfo): Promise<PlaywrightWorkerArgs> {
this._browserType = args.playwright[args.browserName];
this._browserOptions = {
...args.launchOptions,
_traceDir: args.traceDir,
channel: args.channel,
channel: args.browserChannel,
headless: !args.headful,
handleSIGINT: false,
} as any;
@ -101,8 +99,6 @@ class PlaywrightEnv {
async beforeEach({}, testInfo: folio.TestInfo): Promise<PlaywrightTestArgs> {
return {
browserType: this._browserType,
browserOptions: this._browserOptions,
createUserDataDir: this._createUserDataDir.bind(this),
launchPersistent: this._launchPersistent.bind(this),
startRemoteServer: this._startRemoteServer.bind(this),
@ -123,13 +119,6 @@ class PlaywrightEnv {
}
}
export const playwrightTest = baseTest.extend(new PlaywrightEnv());
export const slowPlaywrightTest = baseTest.extend(new PlaywrightEnv());
type BrowserEnvOptions = {
contextOptions?: BrowserContextOptions;
};
type BrowserTestArgs = {
browser: Browser;
browserVersion: string;
@ -139,25 +128,19 @@ type BrowserTestArgs = {
class BrowserEnv {
private _browser: Browser | undefined;
private _contextOptions: BrowserContextOptions;
private _contexts: BrowserContext[] = [];
protected _browserVersion: string;
optionsType(): BrowserEnvOptions {
return {};
}
async beforeAll(args: PlaywrightEnvWorkerArgs, workerInfo: folio.WorkerInfo) {
async beforeAll(args: PlaywrightWorkerArgs, workerInfo: folio.WorkerInfo) {
this._browser = await args.browserType.launch(args.browserOptions);
this._browserVersion = this._browser.version();
}
async beforeEach(options: CommonTestArgs, testInfo: folio.TestInfo): Promise<BrowserTestArgs> {
async beforeEach(options: CommonArgs, testInfo: folio.TestInfo): Promise<BrowserTestArgs> {
const debugName = path.relative(testInfo.config.outputDir, testInfo.outputDir).replace(/[\/\\]/g, '-');
const contextOptions = {
recordVideo: options.video ? { dir: testInfo.outputPath('') } : undefined,
_debugName: debugName,
...this._contextOptions,
} as BrowserContextOptions;
testInfo.data.browserVersion = this._browserVersion;
@ -171,7 +154,7 @@ class BrowserEnv {
return {
browser: this._browser,
browserVersion: this._browserVersion,
contextOptions: this._contextOptions as BrowserContextOptions,
contextOptions,
contextFactory,
};
}
@ -189,25 +172,18 @@ class BrowserEnv {
}
}
export const browserTest = playwrightTest.extend(new BrowserEnv());
export const slowBrowserTest = slowPlaywrightTest.extend(new BrowserEnv());
type ContextTestArgs = {
context: BrowserContext;
page: Page;
};
class ContextEnv {
async beforeEach(args: BrowserTestArgs, testInfo: folio.TestInfo): Promise<ContextTestArgs> {
async beforeEach(args: BrowserTestArgs, testInfo: folio.TestInfo) {
const context = await args.contextFactory();
const page = await context.newPage();
return {
context,
page,
};
return { context, page };
}
}
export const playwrightTest = baseTest.extend(new PlaywrightEnv());
export const slowPlaywrightTest = baseTest.extend(new PlaywrightEnv());
export const browserTest = playwrightTest.extend(new BrowserEnv());
export const slowBrowserTest = slowPlaywrightTest.extend(new BrowserEnv());
export const contextTest = browserTest.extend(new ContextEnv());
export const tracingTest = baseTest.extend(new PlaywrightEnv()).extend(new BrowserEnv()).extend(new ContextEnv());

View File

@ -18,7 +18,7 @@ import * as folio from 'folio';
import * as path from 'path';
import { playwrightTest, slowPlaywrightTest, contextTest, tracingTest } from './browserTest';
import { test as pageTest } from './pageTest';
import { BrowserName, CommonTestArgs, CommonWorkerArgs } from './baseTest';
import { BrowserName, CommonArgs } from './baseTest';
import type { Browser, BrowserContext } from '../../index';
const config: folio.Config = {
@ -59,11 +59,11 @@ class PageEnv {
private _browserMajorVersion: number;
private _context: BrowserContext | undefined;
async beforeAll(args: AllOptions & CommonWorkerArgs, workerInfo: folio.WorkerInfo) {
async beforeAll(args: AllOptions & CommonArgs, workerInfo: folio.WorkerInfo) {
this._browser = await args.playwright[args.browserName].launch({
...args.launchOptions,
_traceDir: args.traceDir,
channel: args.channel,
channel: args.browserChannel,
headless: !args.headful,
handleSIGINT: false,
} as any);
@ -72,14 +72,20 @@ class PageEnv {
return {};
}
async beforeEach(args: AllOptions & CommonTestArgs, testInfo: folio.TestInfo) {
async beforeEach(args: CommonArgs, testInfo: folio.TestInfo) {
testInfo.data.browserVersion = this._browserVersion;
this._context = await this._browser.newContext({
recordVideo: args.video ? { dir: testInfo.outputPath('') } : undefined,
...args.contextOptions,
});
const page = await this._context.newPage();
return { context: this._context, page, browserVersion: this._browserVersion, browserMajorVersion: this._browserMajorVersion };
return {
context: this._context,
page,
browserVersion: this._browserVersion,
browserMajorVersion: this._browserMajorVersion,
isAndroid: false,
isElectron: false,
};
}
async afterEach({}) {
@ -102,7 +108,7 @@ for (const browserName of browsers) {
const envConfig = {
options: {
mode,
engine: browserName,
browserName,
headful: !!process.env.HEADFUL,
channel: process.env.PWTEST_CHANNEL as any,
video: !!process.env.PWTEST_VIDEO,

View File

@ -48,6 +48,8 @@ class ElectronPageEnv extends ElectronEnv {
browserVersion: this._browserVersion,
browserMajorVersion: this._browserMajorVersion,
page,
isAndroid: false,
isElectron: true,
};
}
}
@ -56,7 +58,7 @@ const envConfig = {
tag: 'electron',
options: {
mode: 'default' as const,
engine: 'electron' as const,
browserName: 'chromium' as const,
coverageName: 'electron'
}
};

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { CommonTestArgs, test as baseTest } from './baseTest';
import { baseTest, CommonArgs } from './baseTest';
import { ElectronApplication, Page } from '../../index';
import * as folio from 'folio';
import * as path from 'path';
@ -57,7 +57,7 @@ export class ElectronEnv {
return {};
}
async beforeEach(args: CommonTestArgs, testInfo: folio.TestInfo): Promise<ElectronTestArgs> {
async beforeEach(args: CommonArgs, testInfo: folio.TestInfo): Promise<ElectronTestArgs> {
this._electronApp = await args.playwright._electron.launch({
args: [path.join(__dirname, 'electron-app.js')],
});

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { test as baseTest } from './baseTest';
import { baseTest } from './baseTest';
import type { Page } from '../../index';
export { expect } from 'folio';
@ -23,6 +23,8 @@ export type PageTestArgs = {
browserVersion: string;
browserMajorVersion: number;
page: Page;
isAndroid: boolean;
isElectron: boolean;
};
export const test = baseTest.declare<PageTestArgs>();

View File

@ -18,9 +18,7 @@
import { test as it, expect } from './config/pageTest';
import { browserTest } from './config/browserTest';
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it.skip(({ isAndroid }) => isAndroid);
it('should work', async ({ page, server, browserName, headful }) => {
it.fail(browserName === 'firefox' && headful);

View File

@ -23,10 +23,8 @@ import path from 'path';
import fs from 'fs';
it.describe('element screenshot', () => {
it.beforeEach(async ({ browserName, headful, isAndroid }) => {
it.skip(browserName === 'firefox' && headful);
it.skip(isAndroid, 'Different dpr. Remove after using 1x scale for screenshots.');
});
it.skip(({ browserName, headful }) => browserName === 'firefox' && headful);
it.skip(({ isAndroid }) => isAndroid, 'Different dpr. Remove after using 1x scale for screenshots.');
it('should work', async ({page, server}) => {
await page.setViewportSize({width: 500, height: 500});
@ -277,10 +275,7 @@ it.describe('element screenshot', () => {
});
browserTest.describe('element sceenshot', () => {
browserTest.beforeEach(async ({ browserName, headful, isAndroid }) => {
browserTest.skip(browserName === 'firefox' && headful);
browserTest.skip(isAndroid, 'Different dpr. Remove after using 1x scale for screenshots.');
});
browserTest.skip(({ browserName, headful }) => browserName === 'firefox' && headful);
browserTest('should work with a mobile viewport', async ({browser, server, browserName}) => {
browserTest.skip(browserName === 'firefox');

View File

@ -16,9 +16,7 @@
import { test as it, expect } from './config/pageTest';
it.beforeEach(async ({ isAndroid }) => {
it.fixme(isAndroid, 'Post data does not work');
});
it.fixme(({ isAndroid }) => isAndroid, 'Post data does not work');
it('should return correct postData buffer for utf-8 body', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);

View File

@ -28,9 +28,7 @@ function initServer(server: TestServer): string[] {
return messages;
}
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid, 'Too flaky on Android');
});
it.skip(({ isAndroid }) => isAndroid, 'Too flaky on Android');
it('should await navigation when clicking anchor', async ({page, server}) => {
const messages = initServer(server);

View File

@ -19,10 +19,8 @@ import { test as it, expect } from './config/pageTest';
import { attachFrame } from './config/utils';
it.describe('Drag and drop', () => {
it.beforeEach(async ({ browserName, isAndroid }) => {
it.skip(isAndroid);
it.fixme(browserName === 'chromium');
});
it.skip(({ isAndroid }) => isAndroid);
it.fixme(({ browserName }) => browserName === 'chromium');
it('should work', async ({page, server}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
@ -74,9 +72,7 @@ it.describe('Drag and drop', () => {
});
it.describe('iframe', () => {
it.beforeEach(async () => {
it.fixme('implement dragging with iframes');
});
it.fixme('implement dragging with iframes');
it('should drag into an iframe', async ({server, page, isFirefox}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
@ -158,13 +154,13 @@ it.describe('Drag and drop', () => {
window['dropped'] = false;
document.querySelector('div').addEventListener('dragstart', event => {
event.dataTransfer.effectAllowed = effectAllowed;
event.dataTransfer.effectAllowed = effectAllowed as any;
event.dataTransfer.setData('text/plain', 'drag data');
});
const dropTarget: HTMLElement = document.querySelector('drop-target');
dropTarget.addEventListener('dragover', event => {
event.dataTransfer.dropEffect = dropEffect;
event.dataTransfer.dropEffect = dropEffect as any;
event.preventDefault();
});
dropTarget.addEventListener('drop', event => {

View File

@ -19,9 +19,7 @@ import { test as it, expect } from './config/pageTest';
import { browserTest } from './config/browserTest';
import { attachFrame } from './config/utils';
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it.skip(({ isAndroid }) => isAndroid);
it('should emulate type', async ({page}) => {
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);

View File

@ -17,9 +17,7 @@
import { test, expect } from './config/pageTest';
test.describe('non-stalling evaluate', () => {
test.beforeEach(async ({mode}) => {
test.skip(mode !== 'default');
});
test.skip(({mode}) => mode !== 'default');
test('should work', async ({page, server, toImpl}) => {
await page.goto(server.EMPTY_PAGE);

View File

@ -18,9 +18,7 @@
import { test as it, expect } from './config/pageTest';
import { attachFrame } from './config/utils';
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it.skip(({ isAndroid }) => isAndroid);
it('should type into a textarea', async ({page}) => {
await page.evaluate(() => {

View File

@ -97,9 +97,7 @@ it('should amend method on main request', async ({page, server}) => {
});
it.describe('', () => {
it.beforeEach(async ({ isAndroid }) => {
it.fixme(isAndroid, 'Post data does not work');
});
it.fixme(({ isAndroid }) => isAndroid, 'Post data does not work');
it('should amend post data', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);

View File

@ -23,10 +23,8 @@ import fs from 'fs';
import { PNG } from 'pngjs';
it.describe('page screenshot', () => {
it.beforeEach(async ({ browserName, headful, isAndroid }) => {
it.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
it.skip(isAndroid, 'Different viewport');
});
it.skip(({ browserName, headful }) => browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
it.skip(({ isAndroid }) => isAndroid, 'Different viewport');
it('should work', async ({page, server}) => {
await page.setViewportSize({width: 500, height: 500});
@ -279,10 +277,7 @@ it.describe('page screenshot', () => {
});
browserTest.describe('page screenshot', () => {
browserTest.beforeEach(async ({ browserName, headful, isAndroid }) => {
browserTest.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
browserTest.skip(isAndroid, 'Different viewport');
});
browserTest.skip(({ browserName, headful }) => browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
browserTest('should run in parallel in multiple pages', async ({server, contextFactory}) => {
const context = await contextFactory();

View File

@ -18,9 +18,7 @@ import { Page } from '../index';
import { cliTest as it, expect } from './config/cliTest';
it.describe('pause', () => {
it.beforeEach(async ({ mode }) => {
it.skip(mode !== 'default');
});
it.skip(({ mode }) => mode !== 'default');
it.afterEach(async ({ recorderPageGetter }) => {
try {

View File

@ -22,9 +22,7 @@ function getPermission(page, name) {
}
it.describe('permissions', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(browserName === 'webkit', 'Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)');
});
it.skip(({ browserName }) => browserName === 'webkit', 'Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)');
it('should be prompt by default', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);

View File

@ -22,9 +22,10 @@ async function generate(pageOrFrame: Page | Frame, target: string): Promise<stri
}
it.describe('selector generator', () => {
it.beforeEach(async ({ mode, context }) => {
it.skip(({ mode }) => mode !== 'default');
it.beforeEach(async ({ context }) => {
await (context as any)._enableRecorder({ language: 'javascript' });
it.skip(mode !== 'default');
});
it('should prefer button over inner span', async ({ page }) => {

View File

@ -30,9 +30,7 @@ test('should close the browser when the node process closes', async ({startRemot
});
test.describe('signals', () => {
test.beforeEach(async ({platform, headful}) => {
test.skip(platform === 'win32' || headful);
});
test.skip(({platform, headful}) => platform === 'win32' || headful);
test('should report browser close signal', async ({startRemoteServer, server}) => {
const remoteServer = await startRemoteServer({ url: server.EMPTY_PAGE });

View File

@ -46,9 +46,7 @@ async function checkPageSlowMo(toImpl, page, task) {
}
it.describe('slowMo', () => {
it.beforeEach(async ({ mode }) => {
it.skip(mode !== 'default');
});
it.skip(({ mode }) => mode !== 'default');
it('Page SlowMo $$eval', async ({page, toImpl}) => {
await checkPageSlowMo(toImpl, page, () => page.$$eval('button', () => void 0));

View File

@ -24,9 +24,9 @@ it.describe('snapshots', () => {
let httpServer: any;
let snapshotPort: number;
it.beforeEach(async ({ mode, toImpl, context }, testInfo) => {
it.skip(mode !== 'default');
it.skip(({ mode }) => mode !== 'default');
it.beforeEach(async ({ toImpl, context }, testInfo) => {
snapshotter = new InMemorySnapshotter(toImpl(context));
await snapshotter.initialize();
httpServer = new HttpServer();

View File

@ -14,23 +14,21 @@
* limitations under the License.
*/
import { browserTest as it, expect } from './config/browserTest';
import { ElementHandle, Page } from '../index';
import { browserTest, expect } from './config/browserTest';
import { ElementHandle } from '../index';
import type { ServerResponse } from 'http';
let page: Page;
it.beforeEach(async ({browser}) => {
page = await browser.newPage({
hasTouch: true
});
const it = browserTest.extend({
async beforeEach({ browser }) {
this.page = await browser.newPage({ hasTouch: true });
return { page: this.page };
},
async afterEach() {
await this.page.close();
}
});
it.afterEach(async () => {
await page.close();
});
it('should send all of the correct events', async ({}) => {
it('should send all of the correct events', async ({ page }) => {
await page.setContent(`
<div id="a" style="background: lightblue; width: 50px; height: 50px">a</div>
<div id="b" style="background: pink; width: 50px; height: 50px">b</div>
@ -50,7 +48,7 @@ it('should send all of the correct events', async ({}) => {
]);
});
it('trial run should not tap', async ({}) => {
it('trial run should not tap', async ({ page }) => {
await page.setContent(`
<div id="a" style="background: lightblue; width: 50px; height: 50px">a</div>
<div id="b" style="background: pink; width: 50px; height: 50px">b</div>
@ -61,7 +59,7 @@ it('trial run should not tap', async ({}) => {
expect(await eventsHandle.jsonValue()).toEqual([]);
});
it('should not send mouse events touchstart is canceled', async ({}) => {
it('should not send mouse events touchstart is canceled', async ({ page }) => {
await page.setContent(`<div style="width: 50px; height: 50px; background: red">`);
await page.evaluate(() => {
// touchstart is not cancelable unless passive is false
@ -77,7 +75,7 @@ it('should not send mouse events touchstart is canceled', async ({}) => {
]);
});
it('should not send mouse events when touchend is canceled', async ({}) => {
it('should not send mouse events when touchend is canceled', async ({ page }) => {
await page.setContent(`<div style="width: 50px; height: 50px; background: red">`);
await page.evaluate(() => {
document.addEventListener('touchend', t => t.preventDefault());
@ -92,7 +90,7 @@ it('should not send mouse events when touchend is canceled', async ({}) => {
]);
});
it('should wait for a navigation caused by a tap', async ({server}) => {
it('should wait for a navigation caused by a tap', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.setContent(`
<a href="/intercept-this.html">link</a>;
@ -115,7 +113,7 @@ it('should wait for a navigation caused by a tap', async ({server}) => {
expect(resolved).toBe(true);
});
it('should work with modifiers', async ({}) => {
it('should work with modifiers', async ({ page }) => {
await page.setContent('hello world');
const altKeyPromise = page.evaluate(() => new Promise(resolve => {
document.addEventListener('touchstart', event => {
@ -130,7 +128,7 @@ it('should work with modifiers', async ({}) => {
expect(await altKeyPromise).toBe(true);
});
it('should send well formed touch points', async ({}) => {
it('should send well formed touch points', async ({ page }) => {
const promises = Promise.all([
page.evaluate(() => new Promise(resolve => {
document.addEventListener('touchstart', event => {
@ -182,7 +180,7 @@ it('should send well formed touch points', async ({}) => {
expect(touchend).toEqual([]);
});
it('should wait until an element is visible to tap it', async ({}) => {
it('should wait until an element is visible to tap it', async ({ page }) => {
const div = await page.evaluateHandle(() => {
const button = document.createElement('button');
button.textContent = 'not clicked';

View File

@ -18,9 +18,7 @@
import { test as it, expect } from './config/pageTest';
import { Server as WebSocketServer } from 'ws';
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it.skip(({ isAndroid }) => isAndroid);
it('should work', async ({ page, server }) => {
const value = await page.evaluate(port => {