test: roll to folio@0.4.0-alpha13 (#6570)

This commit is contained in:
Dmitry Gozman 2021-05-15 07:42:35 -07:00 committed by GitHub
parent cff3bd0422
commit 5e84eade85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 59 additions and 99 deletions

6
package-lock.json generated
View File

@ -3483,9 +3483,9 @@
}
},
"folio": {
"version": "0.4.0-alpha11",
"resolved": "https://registry.npmjs.org/folio/-/folio-0.4.0-alpha11.tgz",
"integrity": "sha512-4kXdO+Ndbn++vCbzuMbn8bGqQLQ9J/Vni/1r9UwvirE4HydfxP1PHkvx9qb7wsB2hQbXmPkU5qM0eyGWFKpmog==",
"version": "0.4.0-alpha13",
"resolved": "https://registry.npmjs.org/folio/-/folio-0.4.0-alpha13.tgz",
"integrity": "sha512-ujrTuD4bSY3jNB2QVf5B2JSZFz2PNtNR0LIIbD+o4vCNutU9IAK0vn1WAiM5uLMt47CadAuFEb7260nanrTCcw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",

View File

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

View File

@ -60,12 +60,9 @@ it.describe('device', () => {
await context.close();
});
it('should scroll twice when emulated', async ({server, contextFactory, playwright, contextOptions}) => {
it('should scroll twice when emulated', async ({server, contextFactory, playwright}) => {
const device = playwright.devices['iPhone 6'];
const context = await contextFactory({
...contextOptions,
...device,
});
const context = await contextFactory(device);
const page = await context.newPage();
await page.setContent(`
<meta name="viewport" content="width=device-width, user-scalable=no" />
@ -81,14 +78,11 @@ it.describe('device', () => {
await context.close();
});
it('should reset scroll top after a navigation', async ({server, contextFactory, playwright, contextOptions, browserName}) => {
it('should reset scroll top after a navigation', async ({server, contextFactory, playwright, browserName}) => {
it.skip(browserName === 'webkit');
const device = playwright.devices['iPhone 6'];
const context = await contextFactory({
...contextOptions,
...device,
});
const context = await contextFactory(device);
const page = await context.newPage();
await page.goto(server.PREFIX + '/input/scrollable.html');
await page.evaluate(() => window.scroll(0, 100));
@ -98,14 +92,11 @@ it.describe('device', () => {
await context.close();
});
it('should scroll to a precise position with mobile scale', async ({server, contextFactory, playwright, contextOptions, browserName}) => {
it('should scroll to a precise position with mobile scale', async ({server, contextFactory, playwright, browserName}) => {
it.skip(browserName === 'webkit');
const device = playwright.devices['iPhone 6'];
const context = await contextFactory({
...contextOptions,
...device,
});
const context = await contextFactory(device);
const page = await context.newPage();
await page.goto(server.PREFIX + '/input/scrollable.html');
expect(await page.evaluate(() => document.body.scrollHeight)).toBeGreaterThan(1000);
@ -114,12 +105,9 @@ it.describe('device', () => {
await context.close();
});
it('should emulate viewport and screen size', async ({server, contextFactory, playwright, contextOptions}) => {
it('should emulate viewport and screen size', async ({server, contextFactory, playwright}) => {
const device = playwright.devices['iPhone 12'];
const context = await contextFactory({
...contextOptions,
...device,
});
const context = await contextFactory(device);
const page = await context.newPage();
await page.setContent(`<meta name="viewport" content="width=device-width, user-scalable=no" />`);
@ -136,12 +124,9 @@ it.describe('device', () => {
await context.close();
});
it('should emulate viewport without screen size', async ({server, contextFactory, playwright, contextOptions}) => {
it('should emulate viewport without screen size', async ({server, contextFactory, playwright}) => {
const device = playwright.devices['iPhone 6'];
const context = await contextFactory({
...contextOptions,
...device,
});
const context = await contextFactory(device);
const page = await context.newPage();
await page.setContent(`<meta name="viewport" content="width=device-width, user-scalable=no" />`);

View File

@ -16,7 +16,7 @@
import { browserTest as it, expect } from './config/browserTest';
it.useOptions({ launchOptions: { proxy: { server: 'per-context' } } });
it.useOptions({ proxy: { server: 'per-context' } });
it('should throw for missing global proxy on Chromium Windows', async ({ browserName, platform, browserType, browserOptions, server }) => {
it.skip(browserName !== 'chromium' || platform !== 'win32');

View File

@ -16,7 +16,7 @@
import { contextTest as it, expect } from '../config/browserTest';
it.useOptions({ launchOptions: { args: ['--site-per-process'] } });
it.useOptions({ args: ['--site-per-process'] });
it('should report oopif frames', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html');

View File

@ -42,11 +42,9 @@ class AndroidPageEnv extends AndroidEnv {
}
}
type AllOptions = PlaywrightEnvOptions & CommonOptions;
const outputDir = path.join(__dirname, '..', '..', 'test-results');
const testDir = path.join(__dirname, '..');
const config: folio.Config<AllOptions> = {
const config: folio.Config<PlaywrightEnvOptions & CommonOptions> = {
testDir,
snapshotDir: '__snapshots__',
outputDir,
@ -66,6 +64,7 @@ config.projects.push({
name: 'android',
options: {
loopback: '10.0.2.2',
mode: 'default',
browserName: 'chromium',
},
testDir: path.join(testDir, 'android'),
@ -75,6 +74,7 @@ config.projects.push({
name: 'android',
options: {
loopback: '10.0.2.2',
mode: 'default',
browserName: 'chromium',
},
testDir: path.join(testDir, 'page'),

View File

@ -26,17 +26,17 @@ import { PlaywrightClient } from '../../lib/remote/playwrightClient';
export type BrowserName = 'chromium' | 'firefox' | 'webkit';
type Mode = 'default' | 'driver' | 'service';
type BaseWorkerArgs = {
type BaseOptions = {
mode: Mode;
browserName: BrowserName;
channel?: string;
video?: boolean;
headless?: boolean;
};
type BaseWorkerArgs = {
platform: 'win32' | 'darwin' | 'linux';
video: boolean | undefined;
headless: boolean | undefined;
playwright: typeof import('../../index');
toImpl: (rpcObject: any) => any;
browserName: BrowserName;
channel: string | undefined;
isWindows: boolean;
isMac: boolean;
isLinux: boolean;
@ -100,17 +100,8 @@ class DefaultMode {
}
}
type BaseOptions = {
mode?: Mode;
browserName?: BrowserName;
channel?: string;
video?: boolean;
headless?: boolean;
};
class BaseEnv {
private _mode: DriverMode | ServiceMode | DefaultMode;
private _browserName: BrowserName;
private _options: BaseOptions;
private _playwright: typeof import('../../index');
@ -120,36 +111,30 @@ class BaseEnv {
async beforeAll(options: BaseOptions, workerInfo: folio.WorkerInfo): Promise<BaseWorkerArgs> {
this._options = options;
this._browserName = options.browserName || 'chromium';
this._mode = {
default: new DefaultMode(),
service: new ServiceMode(),
driver: new DriverMode(),
}[this._options.mode || 'default'];
}[this._options.mode];
require('../../lib/utils/utils').setUnderTest();
this._playwright = await this._mode.setup(workerInfo);
return {
playwright: this._playwright,
browserName: this._browserName,
channel: this._options.channel,
isWindows: process.platform === 'win32',
isMac: process.platform === 'darwin',
isLinux: process.platform === 'linux',
headless: this._options.headless,
video: this._options.video,
mode: this._options.mode || 'default',
platform: process.platform as ('win32' | 'darwin' | 'linux'),
toImpl: (this._playwright as any)._toImpl,
};
}
async beforeEach({}, testInfo: folio.TestInfo) {
testInfo.snapshotPathSegment = this._browserName;
testInfo.data = { browserName: this._browserName };
testInfo.snapshotPathSegment = this._options.browserName;
testInfo.data = { browserName: this._options.browserName };
if (!this._options.headless)
testInfo.data.headful = true;
if ((this._options.mode || 'default') !== 'default')
testInfo.data.mode = this._options.mode || 'default';
if (this._options.mode !== 'default')
testInfo.data.mode = this._options.mode;
if (this._options.video)
testInfo.data.video = true;
return {};
@ -265,6 +250,6 @@ class CoverageEnv {
}
export type CommonOptions = BaseOptions & ServerOptions & CoverageOptions;
export type CommonArgs = BaseWorkerArgs & ServerWorkerArgs;
export type CommonArgs = CommonOptions & BaseWorkerArgs & ServerWorkerArgs;
export const baseTest = folio.test.extend(new CoverageEnv()).extend(new ServerEnv()).extend(new BaseEnv());

View File

@ -32,10 +32,8 @@ type PlaywrightTestArgs = {
startRemoteServer: (options?: RemoteServerOptions) => Promise<RemoteServer>;
};
export type PlaywrightEnvOptions = {
launchOptions?: LaunchOptions;
traceDir?: string;
};
export type PlaywrightEnvOptions = LaunchOptions;
const kLaunchOptionNames = ['args', 'channel', 'chromiumSandbox', 'devtools', 'downloadsPath', 'env', 'executablePath', 'firefoxUserPrefs', 'handleSIGHUP', 'handleSIGINT', 'handleSIGTERM', 'headless', 'ignoreDefaultArgs', 'logger', 'proxy', 'slowMo', 'timeout', 'traceDir'];
type PlaywrightWorkerArgs = {
browserType: BrowserType;
@ -50,18 +48,15 @@ class PlaywrightEnv {
private _remoteServer: RemoteServer | undefined;
hasBeforeAllOptions(options: PlaywrightEnvOptions) {
return 'launchOptions' in options || 'traceDir' in options;
return kLaunchOptionNames.some(key => key in options);
}
async beforeAll(args: CommonArgs & PlaywrightEnvOptions, workerInfo: folio.WorkerInfo): Promise<PlaywrightWorkerArgs> {
this._browserType = args.playwright[args.browserName];
this._browserOptions = {
traceDir: args.traceDir,
channel: args.channel,
headless: args.headless,
handleSIGINT: false,
...args.launchOptions,
} as any;
...args,
};
return {
browserType: this._browserType,
browserOptions: this._browserOptions,
@ -126,9 +121,7 @@ type BrowserTestArgs = {
contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>;
};
type BrowserTestOptions = {
contextOptions?: BrowserContextOptions;
};
type BrowserTestOptions = BrowserContextOptions;
class BrowserEnv {
private _browser: Browser | undefined;
@ -149,7 +142,7 @@ class BrowserEnv {
const contextOptions = {
recordVideo: options.video ? { dir: testInfo.outputPath('') } : undefined,
_debugName: debugName,
...options.contextOptions,
...options,
} as BrowserContextOptions;
testInfo.data.browserVersion = this._browserVersion;
@ -163,8 +156,8 @@ class BrowserEnv {
return {
browser: this._browser,
browserVersion: this._browserVersion,
contextOptions,
contextFactory,
contextOptions,
};
}

View File

@ -30,21 +30,16 @@ const getExecutablePath = (browserName: BrowserName) => {
return process.env.WKPATH;
};
type AllOptions = PlaywrightEnvOptions & CommonOptions;
class PageEnv {
private _browser: Browser
private _browserVersion: string;
private _browserMajorVersion: number;
private _context: BrowserContext | undefined;
async beforeAll(args: AllOptions & CommonArgs, workerInfo: folio.WorkerInfo) {
async beforeAll(args: PlaywrightEnvOptions & CommonArgs, workerInfo: folio.WorkerInfo) {
this._browser = await args.playwright[args.browserName].launch({
...args.launchOptions,
traceDir: args.traceDir,
channel: args.channel,
headless: args.headless,
handleSIGINT: false,
...args,
} as any);
this._browserVersion = this._browser.version();
this._browserMajorVersion = Number(this._browserVersion.split('.')[0]);
@ -55,6 +50,7 @@ class PageEnv {
testInfo.data.browserVersion = this._browserVersion;
this._context = await this._browser.newContext({
recordVideo: args.video ? { dir: testInfo.outputPath('') } : undefined,
...args,
});
const page = await this._context.newPage();
return {
@ -78,14 +74,14 @@ class PageEnv {
}
}
const mode = folio.registerCLIOption('mode', 'Transport mode: default, driver or service').value as ('default' | 'driver' | 'service' | undefined);
const mode = (folio.registerCLIOption('mode', 'Transport mode: default, driver or service').value || 'default') as ('default' | 'driver' | 'service');
const headed = folio.registerCLIOption('headed', 'Run tests in headed mode (default: headless)', { type: 'boolean' }).value || !!process.env.HEADFUL;
const channel = folio.registerCLIOption('channel', 'Browser channel (default: no channel)').value;
const video = !!folio.registerCLIOption('video', 'Record videos for all tests', { type: 'boolean' }).value;
const outputDir = path.join(__dirname, '..', '..', 'test-results');
const testDir = path.join(__dirname, '..');
const config: folio.Config<AllOptions> = {
const config: folio.Config<CommonOptions & PlaywrightEnvOptions> = {
testDir,
snapshotDir: '__snapshots__',
outputDir,
@ -118,10 +114,8 @@ for (const browserName of browserNames) {
headless: !headed,
channel,
video,
executablePath,
traceDir: process.env.PWTRACE ? path.join(outputDir, 'trace') : undefined,
launchOptions: {
executablePath,
},
coverageName: browserName,
},
define: { test: pageTest, env: new PageEnv() },

View File

@ -36,11 +36,9 @@ class ElectronPageEnv extends ElectronEnv {
}
}
type AllOptions = PlaywrightEnvOptions & CommonOptions;
const outputDir = path.join(__dirname, '..', '..', 'test-results');
const testDir = path.join(__dirname, '..');
const config: folio.Config<AllOptions> = {
const config: folio.Config<PlaywrightEnvOptions & CommonOptions> = {
testDir,
snapshotDir: '__snapshots__',
outputDir,
@ -59,6 +57,7 @@ const config: folio.Config<AllOptions> = {
config.projects.push({
name: 'electron',
options: {
mode: 'default',
browserName: 'chromium',
coverageName: 'electron',
},
@ -68,6 +67,7 @@ config.projects.push({
config.projects.push({
name: 'electron',
options: {
mode: 'default',
browserName: 'chromium',
coverageName: 'electron',
},

View File

@ -44,8 +44,13 @@ export class RemoteServer {
this._didExit = false;
this._browserType = browserType;
const launchOptions = {
...browserOptions,
// Copy options to prevent a large JSON string when launching subprocess.
// Otherwise, we get `Error: spawn ENAMETOOLONG` on Windows.
const launchOptions: LaunchOptions = {
args: browserOptions.args,
headless: browserOptions.headless,
channel: browserOptions.channel,
traceDir: browserOptions.traceDir,
handleSIGINT: true,
handleSIGTERM: true,
handleSIGHUP: true,

View File

@ -27,7 +27,6 @@ type CLITestArgs = {
recorderPageGetter: () => Promise<Page>;
openRecorder: () => Promise<Recorder>;
runCLI: (args: string[]) => CLIMock;
executablePath: string | undefined;
};
export const test = contextTest.extend({
@ -35,7 +34,7 @@ export const test = contextTest.extend({
process.env.PWTEST_RECORDER_PORT = String(10907 + workerInfo.workerIndex);
},
async beforeEach({ page, context, toImpl, browserName, channel, headless, mode, launchOptions: { executablePath } }, testInfo: folio.TestInfo): Promise<CLITestArgs> {
async beforeEach({ page, context, toImpl, browserName, channel, headless, mode, executablePath }, testInfo: folio.TestInfo): Promise<CLITestArgs> {
testInfo.skip(mode === 'service');
const recorderPageGetter = async () => {
while (!toImpl(context).recorderAppForTest)
@ -55,7 +54,6 @@ export const test = contextTest.extend({
return new Recorder(page, await recorderPageGetter());
},
recorderPageGetter,
executablePath
};
},
@ -180,7 +178,7 @@ class CLIMock {
private waitForCallback: () => void;
exited: Promise<void>;
constructor(browserName: string, channel: string | undefined, headless: boolean | undefined, args: string[], executablePath?: string) {
constructor(browserName: string, channel: string | undefined, headless: boolean | undefined, args: string[], executablePath: string | undefined) {
this.data = '';
const nodeArgs = [
path.join(__dirname, '..', '..', 'lib', 'cli', 'cli.js'),

View File

@ -18,7 +18,7 @@ import { contextTest as it, expect } from './config/browserTest';
import { ElementHandle } from '../index';
import type { ServerResponse } from 'http';
it.useOptions({ contextOptions: { hasTouch: true } });
it.useOptions({ hasTouch: true });
it('should send all of the correct events', async ({ page }) => {
await page.setContent(`