mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-02 00:53:32 +03:00
chore: streamline config loader (#29627)
This commit is contained in:
parent
adccd39b01
commit
ee93136132
@ -17,7 +17,7 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { Watcher } from 'playwright/lib/fsWatcher';
|
||||
import { loadConfigFromFile } from 'playwright/lib/common/configLoader';
|
||||
import { loadConfigFromFileRestartIfNeeded } from 'playwright/lib/common/configLoader';
|
||||
import { Runner } from 'playwright/lib/runner/runner';
|
||||
import type { PluginContext } from 'rollup';
|
||||
import { source as injectedSource } from './generated/indexSource';
|
||||
@ -25,7 +25,7 @@ import { createConfig, populateComponentsFromTests, resolveDirs, transformIndexF
|
||||
import type { ComponentRegistry } from './viteUtils';
|
||||
|
||||
export async function runDevServer(configFile: string) {
|
||||
const config = await loadConfigFromFile(configFile);
|
||||
const config = await loadConfigFromFileRestartIfNeeded(configFile);
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
|
@ -26,6 +26,11 @@ import type { ConfigCLIOverrides } from './ipc';
|
||||
import type { FullConfig, FullProject } from '../../types/test';
|
||||
import { setTransformConfig } from '../transform/transform';
|
||||
|
||||
export type ConfigLocation = {
|
||||
resolvedConfigFile?: string;
|
||||
configDir: string;
|
||||
};
|
||||
|
||||
export type FixturesWithLocation = {
|
||||
fixtures: Fixtures;
|
||||
location: Location;
|
||||
@ -58,53 +63,54 @@ export class FullConfigInternal {
|
||||
return (config as any)[configInternalSymbol];
|
||||
}
|
||||
|
||||
constructor(configDir: string, configFile: string | undefined, config: Config, configCLIOverrides: ConfigCLIOverrides) {
|
||||
if (configCLIOverrides.projects && config.projects)
|
||||
constructor(location: ConfigLocation, userConfig: Config, configCLIOverrides: ConfigCLIOverrides) {
|
||||
if (configCLIOverrides.projects && userConfig.projects)
|
||||
throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`);
|
||||
|
||||
const { resolvedConfigFile, configDir } = location;
|
||||
const packageJsonPath = getPackageJsonPath(configDir);
|
||||
const packageJsonDir = packageJsonPath ? path.dirname(packageJsonPath) : undefined;
|
||||
const throwawayArtifactsPath = packageJsonDir || process.cwd();
|
||||
|
||||
this.configDir = configDir;
|
||||
this.configCLIOverrides = configCLIOverrides;
|
||||
this.globalOutputDir = takeFirst(configCLIOverrides.outputDir, pathResolve(configDir, config.outputDir), throwawayArtifactsPath, path.resolve(process.cwd()));
|
||||
this.globalOutputDir = takeFirst(configCLIOverrides.outputDir, pathResolve(configDir, userConfig.outputDir), throwawayArtifactsPath, path.resolve(process.cwd()));
|
||||
this.preserveOutputDir = configCLIOverrides.preserveOutputDir || false;
|
||||
this.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, config.ignoreSnapshots, false);
|
||||
const privateConfiguration = (config as any)['@playwright/test'];
|
||||
this.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, userConfig.ignoreSnapshots, false);
|
||||
const privateConfiguration = (userConfig as any)['@playwright/test'];
|
||||
this.plugins = (privateConfiguration?.plugins || []).map((p: any) => ({ factory: p }));
|
||||
|
||||
this.config = {
|
||||
configFile,
|
||||
rootDir: pathResolve(configDir, config.testDir) || configDir,
|
||||
forbidOnly: takeFirst(configCLIOverrides.forbidOnly, config.forbidOnly, false),
|
||||
fullyParallel: takeFirst(configCLIOverrides.fullyParallel, config.fullyParallel, false),
|
||||
globalSetup: takeFirst(resolveScript(config.globalSetup, configDir), null),
|
||||
globalTeardown: takeFirst(resolveScript(config.globalTeardown, configDir), null),
|
||||
globalTimeout: takeFirst(configCLIOverrides.globalTimeout, config.globalTimeout, 0),
|
||||
grep: takeFirst(config.grep, defaultGrep),
|
||||
grepInvert: takeFirst(config.grepInvert, null),
|
||||
maxFailures: takeFirst(configCLIOverrides.maxFailures, config.maxFailures, 0),
|
||||
metadata: takeFirst(config.metadata, {}),
|
||||
preserveOutput: takeFirst(config.preserveOutput, 'always'),
|
||||
reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(config.reporter, configDir), [[defaultReporter]]),
|
||||
reportSlowTests: takeFirst(config.reportSlowTests, { max: 5, threshold: 15000 }),
|
||||
quiet: takeFirst(configCLIOverrides.quiet, config.quiet, false),
|
||||
configFile: resolvedConfigFile,
|
||||
rootDir: pathResolve(configDir, userConfig.testDir) || configDir,
|
||||
forbidOnly: takeFirst(configCLIOverrides.forbidOnly, userConfig.forbidOnly, false),
|
||||
fullyParallel: takeFirst(configCLIOverrides.fullyParallel, userConfig.fullyParallel, false),
|
||||
globalSetup: takeFirst(resolveScript(userConfig.globalSetup, configDir), null),
|
||||
globalTeardown: takeFirst(resolveScript(userConfig.globalTeardown, configDir), null),
|
||||
globalTimeout: takeFirst(configCLIOverrides.globalTimeout, userConfig.globalTimeout, 0),
|
||||
grep: takeFirst(userConfig.grep, defaultGrep),
|
||||
grepInvert: takeFirst(userConfig.grepInvert, null),
|
||||
maxFailures: takeFirst(configCLIOverrides.maxFailures, userConfig.maxFailures, 0),
|
||||
metadata: takeFirst(userConfig.metadata, {}),
|
||||
preserveOutput: takeFirst(userConfig.preserveOutput, 'always'),
|
||||
reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(userConfig.reporter, configDir), [[defaultReporter]]),
|
||||
reportSlowTests: takeFirst(userConfig.reportSlowTests, { max: 5, threshold: 15000 }),
|
||||
quiet: takeFirst(configCLIOverrides.quiet, userConfig.quiet, false),
|
||||
projects: [],
|
||||
shard: takeFirst(configCLIOverrides.shard, config.shard, null),
|
||||
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, config.updateSnapshots, 'missing'),
|
||||
shard: takeFirst(configCLIOverrides.shard, userConfig.shard, null),
|
||||
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, userConfig.updateSnapshots, 'missing'),
|
||||
version: require('../../package.json').version,
|
||||
workers: 0,
|
||||
webServer: null,
|
||||
};
|
||||
for (const key in config) {
|
||||
for (const key in userConfig) {
|
||||
if (key.startsWith('@'))
|
||||
(this.config as any)[key] = (config as any)[key];
|
||||
(this.config as any)[key] = (userConfig as any)[key];
|
||||
}
|
||||
|
||||
(this.config as any)[configInternalSymbol] = this;
|
||||
|
||||
const workers = takeFirst(configCLIOverrides.workers, config.workers, '50%');
|
||||
const workers = takeFirst(configCLIOverrides.workers, userConfig.workers, '50%');
|
||||
if (typeof workers === 'string') {
|
||||
if (workers.endsWith('%')) {
|
||||
const cpus = os.cpus().length;
|
||||
@ -116,7 +122,7 @@ export class FullConfigInternal {
|
||||
this.config.workers = workers;
|
||||
}
|
||||
|
||||
const webServers = takeFirst(config.webServer, null);
|
||||
const webServers = takeFirst(userConfig.webServer, null);
|
||||
if (Array.isArray(webServers)) { // multiple web server mode
|
||||
// Due to previous choices, this value shows up to the user in globalSetup as part of FullConfig. Arrays are not supported by the old type.
|
||||
this.config.webServer = null;
|
||||
@ -128,13 +134,13 @@ export class FullConfigInternal {
|
||||
this.webServers = [];
|
||||
}
|
||||
|
||||
const projectConfigs = configCLIOverrides.projects || config.projects || [config];
|
||||
this.projects = projectConfigs.map(p => new FullProjectInternal(configDir, config, this, p, this.configCLIOverrides, throwawayArtifactsPath));
|
||||
const projectConfigs = configCLIOverrides.projects || userConfig.projects || [userConfig];
|
||||
this.projects = projectConfigs.map(p => new FullProjectInternal(configDir, userConfig, this, p, this.configCLIOverrides, throwawayArtifactsPath));
|
||||
resolveProjectDependencies(this.projects);
|
||||
this._assignUniqueProjectIds(this.projects);
|
||||
setTransformConfig({
|
||||
babelPlugins: privateConfiguration?.babelPlugins || [],
|
||||
external: config.build?.external || [],
|
||||
external: userConfig.build?.external || [],
|
||||
});
|
||||
this.config.projects = this.projects.map(p => p.project);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import type { ConfigCLIOverrides, SerializedConfig } from './ipc';
|
||||
import { requireOrImport } from '../transform/transform';
|
||||
import type { Config, Project } from '../../types/test';
|
||||
import { errorWithFile, fileIsModule } from '../util';
|
||||
import { setCurrentConfig } from './globals';
|
||||
import type { ConfigLocation } from './config';
|
||||
import { FullConfigInternal } from './config';
|
||||
import { addToCompilationCache } from '../transform/compilationCache';
|
||||
import { initializeEsmLoader, registerESMLoader } from './esmLoaderHost';
|
||||
@ -84,60 +84,34 @@ export const defineConfig = (...configs: any[]) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
export class ConfigLoader {
|
||||
private _configCLIOverrides: ConfigCLIOverrides;
|
||||
private _fullConfig: FullConfigInternal | undefined;
|
||||
export async function deserializeConfig(data: SerializedConfig): Promise<FullConfigInternal> {
|
||||
if (data.compilationCache)
|
||||
addToCompilationCache(data.compilationCache);
|
||||
|
||||
constructor(configCLIOverrides?: ConfigCLIOverrides) {
|
||||
this._configCLIOverrides = configCLIOverrides || {};
|
||||
}
|
||||
|
||||
static async deserialize(data: SerializedConfig): Promise<FullConfigInternal> {
|
||||
if (data.compilationCache)
|
||||
addToCompilationCache(data.compilationCache);
|
||||
|
||||
const loader = new ConfigLoader(data.configCLIOverrides);
|
||||
const config = data.configFile ? await loader.loadConfigFile(data.configFile) : await loader.loadEmptyConfig(data.configDir);
|
||||
await initializeEsmLoader();
|
||||
return config;
|
||||
}
|
||||
|
||||
async loadConfigFile(file: string, ignoreProjectDependencies = false): Promise<FullConfigInternal> {
|
||||
if (this._fullConfig)
|
||||
throw new Error('Cannot load two config files');
|
||||
const config = await requireOrImportDefaultObject(file) as Config;
|
||||
const fullConfig = await this._loadConfig(config, path.dirname(file), file);
|
||||
setCurrentConfig(fullConfig);
|
||||
if (ignoreProjectDependencies) {
|
||||
for (const project of fullConfig.projects) {
|
||||
project.deps = [];
|
||||
project.teardown = undefined;
|
||||
}
|
||||
}
|
||||
this._fullConfig = fullConfig;
|
||||
return fullConfig;
|
||||
}
|
||||
|
||||
async loadEmptyConfig(configDir: string): Promise<FullConfigInternal> {
|
||||
const fullConfig = await this._loadConfig({}, configDir);
|
||||
setCurrentConfig(fullConfig);
|
||||
return fullConfig;
|
||||
}
|
||||
|
||||
private async _loadConfig(config: Config, configDir: string, configFile?: string): Promise<FullConfigInternal> {
|
||||
// 1. Validate data provided in the config file.
|
||||
validateConfig(configFile || '<default config>', config);
|
||||
const fullConfig = new FullConfigInternal(configDir, configFile, config, this._configCLIOverrides);
|
||||
fullConfig.defineConfigWasUsed = !!(config as any)[kDefineConfigWasUsed];
|
||||
return fullConfig;
|
||||
}
|
||||
const config = await loadConfig(data.location, data.configCLIOverrides);
|
||||
await initializeEsmLoader();
|
||||
return config;
|
||||
}
|
||||
|
||||
async function requireOrImportDefaultObject(file: string) {
|
||||
let object = await requireOrImport(file);
|
||||
export async function loadUserConfig(location: ConfigLocation): Promise<Config> {
|
||||
let object = location.resolvedConfigFile ? await requireOrImport(location.resolvedConfigFile) : {};
|
||||
if (object && typeof object === 'object' && ('default' in object))
|
||||
object = object['default'];
|
||||
return object;
|
||||
return object as Config;
|
||||
}
|
||||
|
||||
export async function loadConfig(location: ConfigLocation, overrides?: ConfigCLIOverrides, ignoreProjectDependencies = false): Promise<FullConfigInternal> {
|
||||
const userConfig = await loadUserConfig(location);
|
||||
validateConfig(location.resolvedConfigFile || '<default config>', userConfig);
|
||||
const fullConfig = new FullConfigInternal(location, userConfig, overrides || {});
|
||||
fullConfig.defineConfigWasUsed = !!(userConfig as any)[kDefineConfigWasUsed];
|
||||
if (ignoreProjectDependencies) {
|
||||
for (const project of fullConfig.projects) {
|
||||
project.deps = [];
|
||||
project.teardown = undefined;
|
||||
}
|
||||
}
|
||||
return fullConfig;
|
||||
}
|
||||
|
||||
function validateConfig(file: string, config: Config) {
|
||||
@ -312,7 +286,7 @@ function validateProject(file: string, project: Project, title: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveConfigFile(configFileOrDirectory: string): string | null {
|
||||
export function resolveConfigFile(configFileOrDirectory: string): string | undefined {
|
||||
const resolveConfig = (configFile: string) => {
|
||||
if (fs.existsSync(configFile))
|
||||
return configFile;
|
||||
@ -334,7 +308,7 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null
|
||||
if (configFile)
|
||||
return configFile;
|
||||
// If there is no config, assume this as a root testing directory.
|
||||
return null;
|
||||
return undefined;
|
||||
} else {
|
||||
// When passed a file, it must be a config file.
|
||||
const configFile = resolveConfig(configFileOrDirectory);
|
||||
@ -342,21 +316,24 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadConfigFromFile(configFile: string | undefined, overrides?: ConfigCLIOverrides, ignoreDeps?: boolean): Promise<FullConfigInternal | null> {
|
||||
export async function loadConfigFromFileRestartIfNeeded(configFile: string | undefined, overrides?: ConfigCLIOverrides, ignoreDeps?: boolean): Promise<FullConfigInternal | null> {
|
||||
const configFileOrDirectory = configFile ? path.resolve(process.cwd(), configFile) : process.cwd();
|
||||
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
|
||||
if (restartWithExperimentalTsEsm(resolvedConfigFile))
|
||||
return null;
|
||||
const configLoader = new ConfigLoader(overrides);
|
||||
let config: FullConfigInternal;
|
||||
if (resolvedConfigFile)
|
||||
config = await configLoader.loadConfigFile(resolvedConfigFile, ignoreDeps);
|
||||
else
|
||||
config = await configLoader.loadEmptyConfig(configFileOrDirectory);
|
||||
return config;
|
||||
const location: ConfigLocation = {
|
||||
configDir: resolvedConfigFile ? path.dirname(resolvedConfigFile) : configFileOrDirectory,
|
||||
resolvedConfigFile,
|
||||
};
|
||||
return await loadConfig(location, overrides, ignoreDeps);
|
||||
}
|
||||
|
||||
export function restartWithExperimentalTsEsm(configFile: string | null): boolean {
|
||||
export async function loadEmptyConfigForMergeReports() {
|
||||
// Merge reports is "different" for no good reason. It should not pick up local config from the cwd.
|
||||
return await loadConfig({ configDir: process.cwd() });
|
||||
}
|
||||
|
||||
export function restartWithExperimentalTsEsm(configFile: string | undefined): boolean {
|
||||
const nodeVersion = +process.versions.node.split('.')[0];
|
||||
// New experimental loader is only supported on Node 16+.
|
||||
if (nodeVersion < 16)
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
import type { TestInfoImpl } from '../worker/testInfo';
|
||||
import type { Suite } from './test';
|
||||
import type { FullConfigInternal } from './config';
|
||||
|
||||
let currentTestInfoValue: TestInfoImpl | null = null;
|
||||
export function setCurrentTestInfo(testInfo: TestInfoImpl | null) {
|
||||
@ -61,11 +60,3 @@ export function setIsWorkerProcess() {
|
||||
export function isWorkerProcess() {
|
||||
return _isWorkerProcess;
|
||||
}
|
||||
|
||||
let currentConfigValue: FullConfigInternal | null = null;
|
||||
export function setCurrentConfig(config: FullConfigInternal | null) {
|
||||
currentConfigValue = config;
|
||||
}
|
||||
export function currentConfig(): FullConfigInternal | null {
|
||||
return currentConfigValue;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import util from 'util';
|
||||
import { serializeCompilationCache } from '../transform/compilationCache';
|
||||
import type { FullConfigInternal } from './config';
|
||||
import type { ConfigLocation, FullConfigInternal } from './config';
|
||||
import type { ReporterDescription, TestInfoError, TestStatus } from '../../types/test';
|
||||
|
||||
export type ConfigCLIOverrides = {
|
||||
@ -41,8 +41,7 @@ export type ConfigCLIOverrides = {
|
||||
};
|
||||
|
||||
export type SerializedConfig = {
|
||||
configFile: string | undefined;
|
||||
configDir: string;
|
||||
location: ConfigLocation;
|
||||
configCLIOverrides: ConfigCLIOverrides;
|
||||
compilationCache: any;
|
||||
};
|
||||
@ -138,8 +137,7 @@ export type EnvProducedPayload = [string, string | null][];
|
||||
|
||||
export function serializeConfig(config: FullConfigInternal, passCompilationCache: boolean): SerializedConfig {
|
||||
const result: SerializedConfig = {
|
||||
configFile: config.config.configFile,
|
||||
configDir: config.configDir,
|
||||
location: { configDir: config.configDir, resolvedConfigFile: config.config.configFile },
|
||||
configCLIOverrides: config.configCLIOverrides,
|
||||
compilationCache: passCompilationCache ? serializeCompilationCache() : undefined,
|
||||
};
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import type { SerializedConfig } from '../common/ipc';
|
||||
import { ConfigLoader } from '../common/configLoader';
|
||||
import { deserializeConfig } from '../common/configLoader';
|
||||
import { ProcessRunner } from '../common/process';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { loadTestFile } from '../common/testLoader';
|
||||
@ -36,7 +36,7 @@ export class LoaderMain extends ProcessRunner {
|
||||
|
||||
private _config(): Promise<FullConfigInternal> {
|
||||
if (!this._configPromise)
|
||||
this._configPromise = ConfigLoader.deserialize(this._serializedConfig);
|
||||
this._configPromise = deserializeConfig(this._serializedConfig);
|
||||
return this._configPromise;
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,11 @@ import { stopProfiling, startProfiling, gracefullyProcessExitDoNotHang } from 'p
|
||||
import { serializeError } from './util';
|
||||
import { showHTMLReport } from './reporters/html';
|
||||
import { createMergedReport } from './reporters/merge';
|
||||
import { ConfigLoader, loadConfigFromFile } from './common/configLoader';
|
||||
import { loadConfigFromFileRestartIfNeeded, loadEmptyConfigForMergeReports } from './common/configLoader';
|
||||
import type { ConfigCLIOverrides } from './common/ipc';
|
||||
import type { FullResult, TestError } from '../types/testReporter';
|
||||
import type { FullConfig, TraceMode } from '../types/test';
|
||||
import { builtInReporters, defaultReporter, defaultTimeout } from './common/config';
|
||||
import type { FullConfigInternal } from './common/config';
|
||||
import { program } from 'playwright-core/lib/cli/program';
|
||||
export { program } from 'playwright-core/lib/cli/program';
|
||||
import type { ReporterDescription } from '../types/test';
|
||||
@ -74,7 +73,7 @@ function addClearCacheCommand(program: Command) {
|
||||
command.description('clears build and test caches');
|
||||
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
|
||||
command.action(async opts => {
|
||||
const configInternal = await loadConfigFromFile(opts.config);
|
||||
const configInternal = await loadConfigFromFileRestartIfNeeded(opts.config);
|
||||
if (!configInternal)
|
||||
return;
|
||||
const { config, configDir } = configInternal;
|
||||
@ -154,7 +153,7 @@ Examples:
|
||||
|
||||
async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
await startProfiling();
|
||||
const config = await loadConfigFromFile(opts.config, overridesFromOptions(opts), opts.deps === false);
|
||||
const config = await loadConfigFromFileRestartIfNeeded(opts.config, overridesFromOptions(opts), opts.deps === false);
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
@ -183,7 +182,7 @@ export async function withRunnerAndMutedWrite(configFile: string | undefined, ca
|
||||
const stdoutWrite = process.stdout.write.bind(process.stdout);
|
||||
process.stdout.write = ((a: any, b: any, c: any) => process.stderr.write(a, b, c)) as any;
|
||||
try {
|
||||
const config = await loadConfigFromFile(configFile);
|
||||
const config = await loadConfigFromFileRestartIfNeeded(configFile);
|
||||
if (!config)
|
||||
return;
|
||||
const runner = new Runner(config);
|
||||
@ -209,13 +208,7 @@ async function listTestFiles(opts: { [key: string]: any }) {
|
||||
|
||||
async function mergeReports(reportDir: string | undefined, opts: { [key: string]: any }) {
|
||||
const configFile = opts.config;
|
||||
let config: FullConfigInternal | null;
|
||||
if (configFile) {
|
||||
config = await loadConfigFromFile(configFile);
|
||||
} else {
|
||||
const configLoader = new ConfigLoader();
|
||||
config = await configLoader.loadEmptyConfig(process.cwd());
|
||||
}
|
||||
const config = configFile ? await loadConfigFromFileRestartIfNeeded(configFile) : await loadEmptyConfigForMergeReports();
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
|
@ -16,12 +16,11 @@
|
||||
|
||||
import type http from 'http';
|
||||
import path from 'path';
|
||||
import { ManualPromise, createGuid } from 'playwright-core/lib/utils';
|
||||
import { ManualPromise, createGuid, gracefullyProcessExitDoNotHang } from 'playwright-core/lib/utils';
|
||||
import { WSServer } from 'playwright-core/lib/utils';
|
||||
import type { WebSocket } from 'playwright-core/lib/utilsBundle';
|
||||
import type { FullResult } from 'playwright/types/testReporter';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
import { ConfigLoader, resolveConfigFile, restartWithExperimentalTsEsm } from '../common/configLoader';
|
||||
import { loadConfig, resolveConfigFile, restartWithExperimentalTsEsm } from '../common/configLoader';
|
||||
import { InternalReporter } from '../reporters/internalReporter';
|
||||
import { Multiplexer } from '../reporters/multiplexer';
|
||||
import { createReporters } from './reporters';
|
||||
@ -29,6 +28,7 @@ import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer } from
|
||||
import type { ConfigCLIOverrides } from '../common/ipc';
|
||||
import { Runner } from './runner';
|
||||
import type { FindRelatedTestFilesReport } from './runner';
|
||||
import type { ConfigLocation } from '../common/config';
|
||||
|
||||
type PlaywrightTestOptions = {
|
||||
headed?: boolean,
|
||||
@ -40,11 +40,6 @@ type PlaywrightTestOptions = {
|
||||
connectWsEndpoint?: string;
|
||||
};
|
||||
|
||||
type ConfigPaths = {
|
||||
configFile: string | null;
|
||||
configDir: string;
|
||||
};
|
||||
|
||||
export async function runTestServer(configFile: string | undefined) {
|
||||
process.env.PW_TEST_HTML_REPORT_OPEN = 'never';
|
||||
|
||||
@ -52,8 +47,8 @@ export async function runTestServer(configFile: string | undefined) {
|
||||
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
|
||||
if (restartWithExperimentalTsEsm(resolvedConfigFile))
|
||||
return null;
|
||||
const configPaths: ConfigPaths = {
|
||||
configFile: resolvedConfigFile,
|
||||
const configPaths: ConfigLocation = {
|
||||
resolvedConfigFile,
|
||||
configDir: resolvedConfigFile ? path.dirname(resolvedConfigFile) : configFileOrDirectory
|
||||
};
|
||||
|
||||
@ -77,16 +72,19 @@ export async function runTestServer(configFile: string | undefined) {
|
||||
});
|
||||
const url = await wss.listen(0, 'localhost', '/' + createGuid());
|
||||
// eslint-disable-next-line no-console
|
||||
process.on('exit', () => wss.close().catch(console.error));
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Listening on ${url}`);
|
||||
process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0));
|
||||
}
|
||||
|
||||
class Dispatcher {
|
||||
private _testRun: { run: Promise<FullResult['status']>, stop: ManualPromise<void> } | undefined;
|
||||
private _ws: WebSocket;
|
||||
private _configPaths: ConfigPaths;
|
||||
private _configLocation: ConfigLocation;
|
||||
|
||||
constructor(configPaths: ConfigPaths, ws: WebSocket) {
|
||||
this._configPaths = configPaths;
|
||||
constructor(configLocation: ConfigLocation, ws: WebSocket) {
|
||||
this._configLocation = configLocation;
|
||||
this._ws = ws;
|
||||
|
||||
process.stdout.write = ((chunk: string | Buffer, cb?: Buffer | Function, cb2?: Function) => {
|
||||
@ -190,13 +188,7 @@ class Dispatcher {
|
||||
}
|
||||
|
||||
private async _loadConfig(overrides: ConfigCLIOverrides) {
|
||||
const configLoader = new ConfigLoader(overrides);
|
||||
let config: FullConfigInternal;
|
||||
if (this._configPaths.configFile)
|
||||
config = await configLoader.loadConfigFile(this._configPaths.configFile, false);
|
||||
else
|
||||
config = await configLoader.loadEmptyConfig(this._configPaths.configDir);
|
||||
return config;
|
||||
return await loadConfig(this._configLocation, overrides);
|
||||
}
|
||||
|
||||
private _dispatchEvent(method: string, params: any) {
|
||||
|
@ -18,7 +18,7 @@ import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
import { debugTest, formatLocation, relativeFilePath, serializeError } from '../util';
|
||||
import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc';
|
||||
import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals';
|
||||
import { ConfigLoader } from '../common/configLoader';
|
||||
import { deserializeConfig } from '../common/configLoader';
|
||||
import type { Suite, TestCase } from '../common/test';
|
||||
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||
import { FixtureRunner } from './fixtureRunner';
|
||||
@ -205,7 +205,7 @@ export class WorkerMain extends ProcessRunner {
|
||||
if (this._config)
|
||||
return;
|
||||
|
||||
this._config = await ConfigLoader.deserialize(this._params.config);
|
||||
this._config = await deserializeConfig(this._params.config);
|
||||
this._project = this._config.projects.find(p => p.id === this._params.projectId)!;
|
||||
this._poolBuilder = PoolBuilder.createForWorker(this._project);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user