chore: remove default config from cli (#13832)

This commit is contained in:
Pavel Feldman 2022-04-28 15:49:36 -08:00 committed by GitHub
parent 4984878411
commit 18bff137ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 46 deletions

View file

@ -17,6 +17,7 @@
import * as crypto from 'crypto';
import type stream from 'stream';
import * as URL from 'url';
import v8 from 'v8';
type NameValue = {
name: string,
@ -214,3 +215,7 @@ export function streamToString(stream: stream.Readable): Promise<string> {
}
export const isLikelyNpxGlobal = () => process.argv.length >= 2 && process.argv[1].includes('_npx');
export function deepCopy<T>(obj: T): T {
return v8.deserialize(v8.serialize(obj));
}

View file

@ -20,18 +20,12 @@ import type { Command } from 'playwright-core/lib/utilsBundle';
import fs from 'fs';
import url from 'url';
import path from 'path';
import os from 'os';
import type { Config } from './types';
import type { BuiltInReporter } from './runner';
import { Runner, builtInReporters, kDefaultConfigFiles } from './runner';
import { stopProfiling, startProfiling } from './profiler';
import type { FilePatternFilter } from './util';
import { showHTMLReport } from './reporters/html';
import { hostPlatform } from 'playwright-core/lib/utils/hostPlatform';
import { fileIsModule } from './loader';
const defaultTimeout = 30000;
const defaultReporter: BuiltInReporter = process.env.CI ? 'dot' : 'list';
import { baseFullConfig, defaultTimeout, fileIsModule } from './loader';
export function addTestCommand(program: Command) {
const command = program.command('test [test-filter...]');
@ -51,7 +45,7 @@ export function addTestCommand(program: Command) {
command.option('--output <dir>', `Folder for output artifacts (default: "test-results")`);
command.option('--quiet', `Suppress stdio`);
command.option('--repeat-each <N>', `Run each test N times (default: 1)`);
command.option('--reporter <reporter>', `Reporter to use, comma-separated, can be ${builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${defaultReporter}")`);
command.option('--reporter <reporter>', `Reporter to use, comma-separated, can be ${builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${baseFullConfig.reporter[0]}")`);
command.option('--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`);
command.option('--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`);
command.option('--project <project-name...>', `Only run tests from the specified list of projects (default: run all projects)`);
@ -108,24 +102,13 @@ Examples:
async function runTests(args: string[], opts: { [key: string]: any }) {
await startProfiling();
const cpus = os.cpus().length;
const workers = hostPlatform.startsWith('mac') && hostPlatform.endsWith('arm64') ? cpus : Math.ceil(cpus / 2);
const defaultConfig: Config = {
preserveOutput: 'always',
reporter: [ [defaultReporter] ],
reportSlowTests: { max: 5, threshold: 15000 },
timeout: defaultTimeout,
updateSnapshots: 'missing',
workers,
};
const overrides = overridesFromOptions(opts);
if (opts.browser) {
const browserOpt = opts.browser.toLowerCase();
if (!['all', 'chromium', 'firefox', 'webkit'].includes(browserOpt))
throw new Error(`Unsupported browser "${opts.browser}", must be one of "all", "chromium", "firefox" or "webkit"`);
const browserNames = browserOpt === 'all' ? ['chromium', 'firefox', 'webkit'] : [browserOpt];
defaultConfig.projects = browserNames.map(browserName => {
overrides.projects = browserNames.map(browserName => {
return {
name: browserName,
use: { browserName },
@ -133,7 +116,6 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
});
}
const overrides = overridesFromOptions(opts);
if (opts.headed || opts.debug)
overrides.use = { headless: false };
if (opts.debug) {
@ -149,7 +131,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
if (restartWithExperimentalTsEsm(resolvedConfigFile))
return;
const runner = new Runner(overrides, { defaultConfig });
const runner = new Runner(overrides);
const config = resolvedConfigFile ? await runner.loadConfigFromResolvedFile(resolvedConfigFile) : await runner.loadEmptyConfig(configFileOrDirectory);
if (('projects' in config) && opts.browser)
throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`);
@ -185,7 +167,7 @@ async function listTestFiles(opts: { [key: string]: any }) {
if (restartWithExperimentalTsEsm(resolvedConfigFile))
return;
const runner = new Runner({}, { defaultConfig: {} });
const runner = new Runner();
await runner.loadConfigFromResolvedFile(resolvedConfigFile);
const report = await runner.listTestFiles(resolvedConfigFile, opts.project);
write(JSON.stringify(report), () => {

View file

@ -18,7 +18,6 @@ import type { TestError } from '../types/testReporter';
import type { Config, TestStatus } from './types';
export type SerializedLoaderData = {
defaultConfig: Config;
overrides: Config;
configFile: { file: string } | { configDir: string };
};

View file

@ -24,34 +24,36 @@ import type { SerializedLoaderData } from './ipc';
import * as path from 'path';
import * as url from 'url';
import * as fs from 'fs';
import * as os from 'os';
import { ProjectImpl } from './project';
import type { BuiltInReporter } from './runner';
import type { Reporter } from '../types/testReporter';
import { builtInReporters } from './runner';
import { isRegExp } from 'playwright-core/lib/utils';
import { deepCopy, isRegExp } from 'playwright-core/lib/utils';
import { serializeError } from './util';
import { _legacyWebServer } from './plugins/webServerPlugin';
import { hostPlatform } from 'playwright-core/lib/utils/hostPlatform';
export const defaultTimeout = 30000;
// To allow multiple loaders in the same process without clearing require cache,
// we make these maps global.
const cachedFileSuites = new Map<string, Suite>();
export class Loader {
private _defaultConfig: Config;
private _configOverrides: Config;
private _fullConfig: FullConfigInternal;
private _configDir: string = '';
private _configFile: string | undefined;
private _projects: ProjectImpl[] = [];
constructor(defaultConfig: Config, configOverrides: Config) {
this._defaultConfig = defaultConfig;
this._configOverrides = configOverrides;
constructor(configOverrides?: Config) {
this._configOverrides = configOverrides || {};
this._fullConfig = { ...baseFullConfig };
}
static async deserialize(data: SerializedLoaderData): Promise<Loader> {
const loader = new Loader(data.defaultConfig, data.overrides);
const loader = new Loader(data.overrides);
if ('file' in data.configFile)
await loader.loadConfigFile(data.configFile.file);
else
@ -62,11 +64,12 @@ export class Loader {
async loadConfigFile(file: string): Promise<Config> {
if (this._configFile)
throw new Error('Cannot load two config files');
let config = await this._requireOrImport(file);
let config = await this._requireOrImport(file) as Config;
if (config && typeof config === 'object' && ('default' in config))
config = config['default'];
config = (config as any)['default'];
this._configFile = file;
const rawConfig = { ...config };
const rawConfig = deepCopy({ ...config, plugins: [] });
rawConfig.plugins = config.plugins?.slice() || [] as any;
await this._processConfigObject(config, path.dirname(file));
return rawConfig;
}
@ -108,9 +111,6 @@ export class Loader {
if (config.webServer)
config.webServer.cwd = config.webServer.cwd ? path.resolve(configDir, config.webServer.cwd) : configDir;
const configUse = mergeObjects(this._defaultConfig.use, config.use);
config = mergeObjects(mergeObjects(this._defaultConfig, config), { use: configUse });
this._fullConfig._configDir = configDir;
this._fullConfig.rootDir = config.testDir || this._configDir;
this._fullConfig._globalOutputDir = takeFirst(config.outputDir, throwawayArtifactsPath, baseFullConfig._globalOutputDir);
@ -132,7 +132,7 @@ export class Loader {
this._fullConfig.webServer = takeFirst(this._configOverrides.webServer, config.webServer, baseFullConfig.webServer);
this._fullConfig._plugins = takeFirst(this._configOverrides.plugins, config.plugins, baseFullConfig._plugins);
const projects: Project[] = ('projects' in config) && config.projects !== undefined ? config.projects : [config];
const projects: Project[] = this._configOverrides.projects || config.projects || [config];
for (const project of projects)
this._addProject(config, project, throwawayArtifactsPath);
this._fullConfig.projects = this._projects.map(p => p.config);
@ -210,7 +210,6 @@ export class Loader {
serialize(): SerializedLoaderData {
return {
defaultConfig: this._defaultConfig,
configFile: this._configFile ? { file: this._configFile } : { configDir: this._configDir },
overrides: this._configOverrides,
};
@ -248,7 +247,7 @@ export class Loader {
_screenshotsDir: screenshotsDir,
testIgnore: takeFirst(this._configOverrides.testIgnore, projectConfig.testIgnore, config.testIgnore, []),
testMatch: takeFirst(this._configOverrides.testMatch, projectConfig.testMatch, config.testMatch, '**/?(*.)@(spec|test).*'),
timeout: takeFirst(this._configOverrides.timeout, projectConfig.timeout, config.timeout, 10000),
timeout: takeFirst(this._configOverrides.timeout, projectConfig.timeout, config.timeout, defaultTimeout),
use: mergeObjects(mergeObjects(config.use, projectConfig.use), this._configOverrides.use),
};
this._projects.push(new ProjectImpl(fullProject, this._projects.length));
@ -467,7 +466,10 @@ function validateProject(file: string, project: Project, title: string) {
}
}
const baseFullConfig: FullConfigInternal = {
const cpus = os.cpus().length;
const workers = hostPlatform.startsWith('mac') && hostPlatform.endsWith('arm64') ? cpus : Math.ceil(cpus / 2);
export const baseFullConfig: FullConfigInternal = {
forbidOnly: false,
fullyParallel: false,
globalSetup: null,
@ -478,14 +480,14 @@ const baseFullConfig: FullConfigInternal = {
maxFailures: 0,
preserveOutput: 'always',
projects: [],
reporter: [ ['list'] ],
reportSlowTests: null,
reporter: [ [process.env.CI ? 'dot' : 'list'] ],
reportSlowTests: { max: 5, threshold: 15000 },
rootDir: path.resolve(process.cwd()),
quiet: false,
shard: null,
updateSnapshots: 'missing',
version: require('../package.json').version,
workers: 1,
workers,
webServer: null,
_globalOutputDir: path.resolve(process.cwd()),
_configDir: '',

View file

@ -60,8 +60,8 @@ export class Runner {
private _reporter!: Reporter;
private _globalInfo: GlobalInfoImpl;
constructor(configOverrides: Config, options: { defaultConfig?: Config } = {}) {
this._loader = new Loader(options.defaultConfig || {}, configOverrides);
constructor(configOverrides?: Config) {
this._loader = new Loader(configOverrides);
this._globalInfo = new GlobalInfoImpl(this._loader.fullConfig());
}