mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: minimize configLoader use (#20431)
This commit is contained in:
parent
bb01d99458
commit
b91bb1af9a
@ -25,9 +25,8 @@ import { experimentalLoaderOption, fileIsModule } from './util';
|
||||
import type { TestFileFilter } from './util';
|
||||
import { createTitleMatcher } from './util';
|
||||
import { showHTMLReport } from './reporters/html';
|
||||
import { baseFullConfig, defaultTimeout, kDefaultConfigFiles, resolveConfigFile } from './common/configLoader';
|
||||
import { baseFullConfig, builtInReporters, ConfigLoader, defaultTimeout, kDefaultConfigFiles, resolveConfigFile } from './common/configLoader';
|
||||
import type { TraceMode } from './common/types';
|
||||
import { builtInReporters } from './runner/reporters';
|
||||
import type { ConfigCLIOverrides } from './common/ipc';
|
||||
|
||||
export function addTestCommands(program: Command) {
|
||||
@ -151,11 +150,12 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
if (restartWithExperimentalTsEsm(resolvedConfigFile))
|
||||
return;
|
||||
|
||||
const runner = new Runner(overrides);
|
||||
const configLoader = new ConfigLoader(overrides);
|
||||
const runner = new Runner(configLoader.fullConfig());
|
||||
if (resolvedConfigFile)
|
||||
await runner.loadConfigFromResolvedFile(resolvedConfigFile);
|
||||
await configLoader.loadConfigFile(resolvedConfigFile);
|
||||
else
|
||||
await runner.loadEmptyConfig(configFileOrDirectory);
|
||||
await configLoader.loadEmptyConfig(configFileOrDirectory);
|
||||
|
||||
const testFileFilters: TestFileFilter[] = args.map(arg => {
|
||||
const match = /^(.*?):(\d+):?(\d+)?$/.exec(arg);
|
||||
@ -193,8 +193,9 @@ async function listTestFiles(opts: { [key: string]: any }) {
|
||||
if (restartWithExperimentalTsEsm(resolvedConfigFile))
|
||||
return;
|
||||
|
||||
const runner = new Runner();
|
||||
await runner.loadConfigFromResolvedFile(resolvedConfigFile);
|
||||
const configLoader = new ConfigLoader();
|
||||
const runner = new Runner(configLoader.fullConfig());
|
||||
await configLoader.loadConfigFile(resolvedConfigFile);
|
||||
const report = await runner.listTestFiles(opts.project);
|
||||
write(JSON.stringify(report), () => {
|
||||
process.exit(0);
|
||||
|
||||
@ -6,6 +6,3 @@
|
||||
|
||||
[transform.ts]
|
||||
../third_party/tsconfig-loader.ts
|
||||
|
||||
[configLoader.ts]
|
||||
../runner/reporters.ts
|
||||
@ -18,9 +18,7 @@ import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { isRegExp } from 'playwright-core/lib/utils';
|
||||
import type { Reporter } from '../../types/testReporter';
|
||||
import type { ConfigCLIOverrides, SerializedConfig } from './ipc';
|
||||
import { builtInReporters, toReporters } from '../runner/reporters';
|
||||
import { requireOrImport } from './transform';
|
||||
import type { Config, FullConfigInternal, FullProjectInternal, Project, ReporterDescription } from './types';
|
||||
import { errorWithFile, getPackageJsonPath, mergeObjects } from '../util';
|
||||
@ -28,14 +26,11 @@ import { errorWithFile, getPackageJsonPath, mergeObjects } from '../util';
|
||||
export const defaultTimeout = 30000;
|
||||
|
||||
export class ConfigLoader {
|
||||
private _configCLIOverrides: ConfigCLIOverrides;
|
||||
private _fullConfig: FullConfigInternal;
|
||||
private _configDir: string = '';
|
||||
private _configFile: string | undefined;
|
||||
|
||||
constructor(configCLIOverrides?: ConfigCLIOverrides) {
|
||||
this._configCLIOverrides = configCLIOverrides || {};
|
||||
this._fullConfig = { ...baseFullConfig };
|
||||
this._fullConfig._configCLIOverrides = configCLIOverrides || {};
|
||||
}
|
||||
|
||||
static async deserialize(data: SerializedConfig): Promise<ConfigLoader> {
|
||||
@ -48,11 +43,10 @@ export class ConfigLoader {
|
||||
}
|
||||
|
||||
async loadConfigFile(file: string): Promise<FullConfigInternal> {
|
||||
if (this._configFile)
|
||||
if (this._fullConfig.configFile)
|
||||
throw new Error('Cannot load two config files');
|
||||
const config = await this._requireOrImportDefaultObject(file) as Config;
|
||||
this._configFile = file;
|
||||
await this._processConfigObject(config, path.dirname(file));
|
||||
const config = await requireOrImportDefaultObject(file) as Config;
|
||||
await this._processConfigObject(config, path.dirname(file), file);
|
||||
return this._fullConfig;
|
||||
}
|
||||
|
||||
@ -61,35 +55,35 @@ export class ConfigLoader {
|
||||
return {};
|
||||
}
|
||||
|
||||
private async _processConfigObject(config: Config, configDir: string) {
|
||||
private async _processConfigObject(config: Config, configDir: string, configFile?: string) {
|
||||
// 1. Validate data provided in the config file.
|
||||
validateConfig(this._configFile || '<default config>', config);
|
||||
validateConfig(configFile || '<default config>', config);
|
||||
|
||||
// 2. Override settings from CLI.
|
||||
config.forbidOnly = takeFirst(this._configCLIOverrides.forbidOnly, config.forbidOnly);
|
||||
config.fullyParallel = takeFirst(this._configCLIOverrides.fullyParallel, config.fullyParallel);
|
||||
config.globalTimeout = takeFirst(this._configCLIOverrides.globalTimeout, config.globalTimeout);
|
||||
config.maxFailures = takeFirst(this._configCLIOverrides.maxFailures, config.maxFailures);
|
||||
config.outputDir = takeFirst(this._configCLIOverrides.outputDir, config.outputDir);
|
||||
config.quiet = takeFirst(this._configCLIOverrides.quiet, config.quiet);
|
||||
config.repeatEach = takeFirst(this._configCLIOverrides.repeatEach, config.repeatEach);
|
||||
config.retries = takeFirst(this._configCLIOverrides.retries, config.retries);
|
||||
if (this._configCLIOverrides.reporter)
|
||||
config.reporter = toReporters(this._configCLIOverrides.reporter as any);
|
||||
config.shard = takeFirst(this._configCLIOverrides.shard, config.shard);
|
||||
config.timeout = takeFirst(this._configCLIOverrides.timeout, config.timeout);
|
||||
config.updateSnapshots = takeFirst(this._configCLIOverrides.updateSnapshots, config.updateSnapshots);
|
||||
config.ignoreSnapshots = takeFirst(this._configCLIOverrides.ignoreSnapshots, config.ignoreSnapshots);
|
||||
if (this._configCLIOverrides.projects && config.projects)
|
||||
const configCLIOverrides = this._fullConfig._configCLIOverrides;
|
||||
config.forbidOnly = takeFirst(configCLIOverrides.forbidOnly, config.forbidOnly);
|
||||
config.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, config.fullyParallel);
|
||||
config.globalTimeout = takeFirst(configCLIOverrides.globalTimeout, config.globalTimeout);
|
||||
config.maxFailures = takeFirst(configCLIOverrides.maxFailures, config.maxFailures);
|
||||
config.outputDir = takeFirst(configCLIOverrides.outputDir, config.outputDir);
|
||||
config.quiet = takeFirst(configCLIOverrides.quiet, config.quiet);
|
||||
config.repeatEach = takeFirst(configCLIOverrides.repeatEach, config.repeatEach);
|
||||
config.retries = takeFirst(configCLIOverrides.retries, config.retries);
|
||||
if (configCLIOverrides.reporter)
|
||||
config.reporter = toReporters(configCLIOverrides.reporter as any);
|
||||
config.shard = takeFirst(configCLIOverrides.shard, config.shard);
|
||||
config.timeout = takeFirst(configCLIOverrides.timeout, config.timeout);
|
||||
config.updateSnapshots = takeFirst(configCLIOverrides.updateSnapshots, config.updateSnapshots);
|
||||
config.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, config.ignoreSnapshots);
|
||||
if (configCLIOverrides.projects && config.projects)
|
||||
throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`);
|
||||
config.projects = takeFirst(this._configCLIOverrides.projects, config.projects as any);
|
||||
config.workers = takeFirst(this._configCLIOverrides.workers, config.workers);
|
||||
config.use = mergeObjects(config.use, this._configCLIOverrides.use);
|
||||
config.projects = takeFirst(configCLIOverrides.projects, config.projects as any);
|
||||
config.workers = takeFirst(configCLIOverrides.workers, config.workers);
|
||||
config.use = mergeObjects(config.use, configCLIOverrides.use);
|
||||
for (const project of config.projects || [])
|
||||
this._applyCLIOverridesToProject(project);
|
||||
|
||||
// 3. Resolve config.
|
||||
this._configDir = configDir;
|
||||
const packageJsonPath = getPackageJsonPath(configDir);
|
||||
const packageJsonDir = packageJsonPath ? path.dirname(packageJsonPath) : undefined;
|
||||
const throwawayArtifactsPath = packageJsonDir || process.cwd();
|
||||
@ -109,8 +103,8 @@ export class ConfigLoader {
|
||||
|
||||
this._fullConfig._configDir = configDir;
|
||||
this._fullConfig._storeDir = path.resolve(configDir, '.playwright-store');
|
||||
this._fullConfig.configFile = this._configFile;
|
||||
this._fullConfig.rootDir = config.testDir || this._configDir;
|
||||
this._fullConfig.configFile = configFile;
|
||||
this._fullConfig.rootDir = config.testDir || configDir;
|
||||
this._fullConfig._globalOutputDir = takeFirst(config.outputDir, throwawayArtifactsPath, baseFullConfig._globalOutputDir);
|
||||
this._fullConfig.forbidOnly = takeFirst(config.forbidOnly, baseFullConfig.forbidOnly);
|
||||
this._fullConfig.fullyParallel = takeFirst(config.fullyParallel, baseFullConfig.fullyParallel);
|
||||
@ -169,46 +163,30 @@ export class ConfigLoader {
|
||||
}
|
||||
}
|
||||
|
||||
async loadGlobalHook(file: string): Promise<(config: FullConfigInternal) => any> {
|
||||
return this._requireOrImportDefaultFunction(path.resolve(this._fullConfig.rootDir, file), false);
|
||||
}
|
||||
|
||||
async loadReporter(file: string): Promise<new (arg?: any) => Reporter> {
|
||||
return this._requireOrImportDefaultFunction(path.resolve(this._fullConfig.rootDir, file), true);
|
||||
}
|
||||
|
||||
fullConfig(): FullConfigInternal {
|
||||
return this._fullConfig;
|
||||
}
|
||||
|
||||
serializedConfig(): SerializedConfig {
|
||||
const result: SerializedConfig = {
|
||||
configFile: this._configFile,
|
||||
configDir: this._configDir,
|
||||
configCLIOverrides: this._configCLIOverrides,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
private _applyCLIOverridesToProject(projectConfig: Project) {
|
||||
projectConfig.fullyParallel = takeFirst(this._configCLIOverrides.fullyParallel, projectConfig.fullyParallel);
|
||||
projectConfig.outputDir = takeFirst(this._configCLIOverrides.outputDir, projectConfig.outputDir);
|
||||
projectConfig.repeatEach = takeFirst(this._configCLIOverrides.repeatEach, projectConfig.repeatEach);
|
||||
projectConfig.retries = takeFirst(this._configCLIOverrides.retries, projectConfig.retries);
|
||||
projectConfig.timeout = takeFirst(this._configCLIOverrides.timeout, projectConfig.timeout);
|
||||
projectConfig.use = mergeObjects(projectConfig.use, this._configCLIOverrides.use);
|
||||
const configCLIOverrides = this._fullConfig._configCLIOverrides;
|
||||
projectConfig.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, projectConfig.fullyParallel);
|
||||
projectConfig.outputDir = takeFirst(configCLIOverrides.outputDir, projectConfig.outputDir);
|
||||
projectConfig.repeatEach = takeFirst(configCLIOverrides.repeatEach, projectConfig.repeatEach);
|
||||
projectConfig.retries = takeFirst(configCLIOverrides.retries, projectConfig.retries);
|
||||
projectConfig.timeout = takeFirst(configCLIOverrides.timeout, projectConfig.timeout);
|
||||
projectConfig.use = mergeObjects(projectConfig.use, configCLIOverrides.use);
|
||||
}
|
||||
|
||||
private _resolveProject(config: Config, fullConfig: FullConfigInternal, projectConfig: Project, throwawayArtifactsPath: string): FullProjectInternal {
|
||||
// Resolve all config dirs relative to configDir.
|
||||
if (projectConfig.testDir !== undefined)
|
||||
projectConfig.testDir = path.resolve(this._configDir, projectConfig.testDir);
|
||||
projectConfig.testDir = path.resolve(fullConfig._configDir, projectConfig.testDir);
|
||||
if (projectConfig.outputDir !== undefined)
|
||||
projectConfig.outputDir = path.resolve(this._configDir, projectConfig.outputDir);
|
||||
projectConfig.outputDir = path.resolve(fullConfig._configDir, projectConfig.outputDir);
|
||||
if (projectConfig.snapshotDir !== undefined)
|
||||
projectConfig.snapshotDir = path.resolve(this._configDir, projectConfig.snapshotDir);
|
||||
projectConfig.snapshotDir = path.resolve(fullConfig._configDir, projectConfig.snapshotDir);
|
||||
|
||||
const testDir = takeFirst(projectConfig.testDir, config.testDir, this._configDir);
|
||||
const testDir = takeFirst(projectConfig.testDir, config.testDir, fullConfig._configDir);
|
||||
const respectGitIgnore = !projectConfig.testDir && !config.testDir;
|
||||
|
||||
const outputDir = takeFirst(projectConfig.outputDir, config.outputDir, path.join(throwawayArtifactsPath, 'test-results'));
|
||||
@ -239,22 +217,13 @@ export class ConfigLoader {
|
||||
use: mergeObjects(config.use, projectConfig.use),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async _requireOrImportDefaultFunction(file: string, expectConstructor: boolean) {
|
||||
let func = await requireOrImport(file);
|
||||
if (func && typeof func === 'object' && ('default' in func))
|
||||
func = func['default'];
|
||||
if (typeof func !== 'function')
|
||||
throw errorWithFile(file, `file must export a single ${expectConstructor ? 'class' : 'function'}.`);
|
||||
return func;
|
||||
}
|
||||
|
||||
private async _requireOrImportDefaultObject(file: string) {
|
||||
let object = await requireOrImport(file);
|
||||
if (object && typeof object === 'object' && ('default' in object))
|
||||
object = object['default'];
|
||||
return object;
|
||||
}
|
||||
async function requireOrImportDefaultObject(file: string) {
|
||||
let object = await requireOrImport(file);
|
||||
if (object && typeof object === 'object' && ('default' in object))
|
||||
object = object['default'];
|
||||
return object;
|
||||
}
|
||||
|
||||
function takeFirst<T>(...args: (T | undefined)[]): T {
|
||||
@ -462,6 +431,7 @@ export const baseFullConfig: FullConfigInternal = {
|
||||
_webServers: [],
|
||||
_globalOutputDir: path.resolve(process.cwd()),
|
||||
_configDir: '',
|
||||
_configCLIOverrides: {},
|
||||
_storeDir: '',
|
||||
_maxConcurrentTestGroups: 0,
|
||||
_ignoreSnapshots: false,
|
||||
@ -513,3 +483,14 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null
|
||||
return configFile!;
|
||||
}
|
||||
}
|
||||
|
||||
export const builtInReporters = ['list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html'] as const;
|
||||
export type BuiltInReporter = typeof builtInReporters[number];
|
||||
|
||||
export function toReporters(reporters: BuiltInReporter | ReporterDescription[] | undefined): ReporterDescription[] | undefined {
|
||||
if (!reporters)
|
||||
return;
|
||||
if (typeof reporters === 'string')
|
||||
return [[reporters]];
|
||||
return reporters;
|
||||
}
|
||||
|
||||
@ -32,3 +32,13 @@ export function setCurrentlyLoadingFileSuite(suite: Suite | undefined) {
|
||||
export function currentlyLoadingFileSuite() {
|
||||
return currentFileSuite;
|
||||
}
|
||||
|
||||
export function currentExpectTimeout(options: { timeout?: number }) {
|
||||
const testInfo = currentTestInfo();
|
||||
if (options.timeout !== undefined)
|
||||
return options.timeout;
|
||||
let defaultExpectTimeout = testInfo?.project._expect?.timeout;
|
||||
if (typeof defaultExpectTimeout === 'undefined')
|
||||
defaultExpectTimeout = 5000;
|
||||
return defaultExpectTimeout;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { TestInfoError, TestStatus } from './types';
|
||||
import type { FullConfigInternal, TestInfoError, TestStatus } from './types';
|
||||
|
||||
export type ConfigCLIOverrides = {
|
||||
forbidOnly?: boolean;
|
||||
@ -120,3 +120,12 @@ export type TestOutputPayload = {
|
||||
export type TeardownErrorsPayload = {
|
||||
fatalErrors: TestInfoError[];
|
||||
};
|
||||
|
||||
export function serializeConfig(config: FullConfigInternal): SerializedConfig {
|
||||
const result: SerializedConfig = {
|
||||
configFile: config.configFile,
|
||||
configDir: config._configDir,
|
||||
configCLIOverrides: config._configCLIOverrides,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
import type { Fixtures, TestInfoError, Project } from '../../types/test';
|
||||
import type { Location } from '../../types/testReporter';
|
||||
import type { ConfigCLIOverrides } from './ipc';
|
||||
import type { FullConfig as FullConfigPublic, FullProject as FullProjectPublic } from './types';
|
||||
export * from '../../types/test';
|
||||
export type { Location } from '../../types/testReporter';
|
||||
@ -44,6 +45,7 @@ export interface TestStepInternal {
|
||||
export interface FullConfigInternal extends FullConfigPublic {
|
||||
_globalOutputDir: string;
|
||||
_configDir: string;
|
||||
_configCLIOverrides: ConfigCLIOverrides;
|
||||
_storeDir: string;
|
||||
_maxConcurrentTestGroups: number;
|
||||
_ignoreSnapshots: boolean;
|
||||
|
||||
@ -19,26 +19,27 @@ import { ConfigLoader } from '../common/configLoader';
|
||||
import { ProcessRunner } from '../common/process';
|
||||
import { loadTestFilesInProcess } from '../common/testLoader';
|
||||
import type { LoadError } from '../common/fixtures';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
|
||||
export class LoaderMain extends ProcessRunner {
|
||||
private _config: SerializedConfig;
|
||||
private _configLoaderPromise: Promise<ConfigLoader> | undefined;
|
||||
private _serializedConfig: SerializedConfig;
|
||||
private _configPromise: Promise<FullConfigInternal> | undefined;
|
||||
|
||||
constructor(config: SerializedConfig) {
|
||||
constructor(serializedConfig: SerializedConfig) {
|
||||
super();
|
||||
this._config = config;
|
||||
this._serializedConfig = serializedConfig;
|
||||
}
|
||||
|
||||
private _configLoader(): Promise<ConfigLoader> {
|
||||
if (!this._configLoaderPromise)
|
||||
this._configLoaderPromise = ConfigLoader.deserialize(this._config);
|
||||
return this._configLoaderPromise;
|
||||
private _config(): Promise<FullConfigInternal> {
|
||||
if (!this._configPromise)
|
||||
this._configPromise = ConfigLoader.deserialize(this._serializedConfig).then(configLoader => configLoader.fullConfig());
|
||||
return this._configPromise;
|
||||
}
|
||||
|
||||
async loadTestFiles(params: { files: string[] }) {
|
||||
const loadErrors: LoadError[] = [];
|
||||
const configLoader = await this._configLoader();
|
||||
const rootSuite = await loadTestFilesInProcess(configLoader.fullConfig(), params.files, loadErrors);
|
||||
const config = await this._config();
|
||||
const rootSuite = await loadTestFilesInProcess(config, params.files, loadErrors);
|
||||
return { rootSuite: rootSuite._deepSerialize(), loadErrors };
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +42,8 @@ import {
|
||||
} from './matchers';
|
||||
import { toMatchSnapshot, toHaveScreenshot } from './toMatchSnapshot';
|
||||
import type { Expect } from '../common/types';
|
||||
import { currentTestInfo } from '../common/globals';
|
||||
import { serializeError, captureStackTrace, currentExpectTimeout } from '../util';
|
||||
import { currentTestInfo, currentExpectTimeout } from '../common/globals';
|
||||
import { serializeError, captureStackTrace } from '../util';
|
||||
import {
|
||||
expect as expectLibrary,
|
||||
INVERTED_COLOR,
|
||||
|
||||
@ -16,8 +16,9 @@
|
||||
|
||||
import type { Expect } from '../common/types';
|
||||
import type { ParsedStackTrace } from '../util';
|
||||
import { expectTypes, callLogText, currentExpectTimeout, captureStackTrace } from '../util';
|
||||
import { expectTypes, callLogText, captureStackTrace } from '../util';
|
||||
import { matcherHint } from './matcherHint';
|
||||
import { currentExpectTimeout } from '../common/globals';
|
||||
|
||||
export async function toBeTruthy(
|
||||
this: ReturnType<Expect['getState']>,
|
||||
|
||||
@ -16,10 +16,11 @@
|
||||
|
||||
import type { Expect } from '../common/types';
|
||||
import { expectTypes } from '../util';
|
||||
import { callLogText, currentExpectTimeout } from '../util';
|
||||
import { callLogText } from '../util';
|
||||
import type { ParsedStackTrace } from 'playwright-core/lib/utils';
|
||||
import { captureStackTrace } from 'playwright-core/lib/utils';
|
||||
import { matcherHint } from './matcherHint';
|
||||
import { currentExpectTimeout } from '../common/globals';
|
||||
|
||||
// Omit colon and one or more spaces, so can call getLabelPrinter.
|
||||
const EXPECTED_LABEL = 'Expected';
|
||||
|
||||
@ -18,13 +18,13 @@ import type { Locator, Page } from 'playwright-core';
|
||||
import type { Page as PageEx } from 'playwright-core/lib/client/page';
|
||||
import type { Locator as LocatorEx } from 'playwright-core/lib/client/locator';
|
||||
import type { Expect } from '../common/types';
|
||||
import { currentTestInfo } from '../common/globals';
|
||||
import { currentTestInfo, currentExpectTimeout } from '../common/globals';
|
||||
import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils';
|
||||
import { getComparator } from 'playwright-core/lib/utils';
|
||||
import type { PageScreenshotOptions } from 'playwright-core/types/types';
|
||||
import {
|
||||
addSuffixToFilePath, serializeError, sanitizeForFilePath,
|
||||
trimLongString, callLogText, currentExpectTimeout,
|
||||
trimLongString, callLogText,
|
||||
expectTypes, captureStackTrace } from '../util';
|
||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||
import fs from 'fs';
|
||||
|
||||
@ -19,12 +19,13 @@ import type { ExpectedTextValue } from '@protocol/channels';
|
||||
import { isRegExp, isString } from 'playwright-core/lib/utils';
|
||||
import type { Expect } from '../common/types';
|
||||
import type { ParsedStackTrace } from '../util';
|
||||
import { expectTypes, callLogText, currentExpectTimeout, captureStackTrace } from '../util';
|
||||
import { expectTypes, callLogText, captureStackTrace } from '../util';
|
||||
import {
|
||||
printReceivedStringContainExpectedResult,
|
||||
printReceivedStringContainExpectedSubstring
|
||||
} from './expect';
|
||||
import { matcherHint } from './matcherHint';
|
||||
import { currentExpectTimeout } from '../common/globals';
|
||||
|
||||
export async function toMatchText(
|
||||
this: ReturnType<Expect['getState']>,
|
||||
|
||||
@ -15,14 +15,15 @@
|
||||
*/
|
||||
|
||||
import type { TestBeginPayload, TestEndPayload, DonePayload, TestOutputPayload, StepBeginPayload, StepEndPayload, TeardownErrorsPayload, RunPayload, SerializedConfig } from '../common/ipc';
|
||||
import { serializeConfig } from '../common/ipc';
|
||||
import type { TestResult, Reporter, TestStep, TestError } from '../../types/testReporter';
|
||||
import type { Suite } from '../common/test';
|
||||
import type { ConfigLoader } from '../common/configLoader';
|
||||
import type { ProcessExitData } from './processHost';
|
||||
import type { TestCase } from '../common/test';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
||||
import { WorkerHost } from './workerHost';
|
||||
import type { TestGroup } from './testGroups';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
|
||||
type TestResultData = {
|
||||
result: TestResult;
|
||||
@ -42,13 +43,13 @@ export class Dispatcher {
|
||||
private _isStopped = false;
|
||||
|
||||
private _testById = new Map<string, TestData>();
|
||||
private _configLoader: ConfigLoader;
|
||||
private _config: FullConfigInternal;
|
||||
private _reporter: Reporter;
|
||||
private _hasWorkerErrors = false;
|
||||
private _failureCount = 0;
|
||||
|
||||
constructor(configLoader: ConfigLoader, testGroups: TestGroup[], reporter: Reporter) {
|
||||
this._configLoader = configLoader;
|
||||
constructor(config: FullConfigInternal, testGroups: TestGroup[], reporter: Reporter) {
|
||||
this._config = config;
|
||||
this._reporter = reporter;
|
||||
this._queue = testGroups;
|
||||
for (const group of testGroups) {
|
||||
@ -125,7 +126,7 @@ export class Dispatcher {
|
||||
|
||||
// 2. Start the worker if it is down.
|
||||
if (!worker) {
|
||||
worker = this._createWorker(job, index, this._configLoader.serializedConfig());
|
||||
worker = this._createWorker(job, index, serializeConfig(this._config));
|
||||
this._workerSlots[index].worker = worker;
|
||||
worker.on('exit', () => this._workerSlots[index].worker = undefined);
|
||||
await worker.start();
|
||||
@ -169,7 +170,7 @@ export class Dispatcher {
|
||||
async run() {
|
||||
this._workerSlots = [];
|
||||
// 1. Allocate workers.
|
||||
for (let i = 0; i < this._configLoader.fullConfig().workers; i++)
|
||||
for (let i = 0; i < this._config.workers; i++)
|
||||
this._workerSlots.push({ busy: false });
|
||||
// 2. Schedule enough jobs.
|
||||
for (let i = 0; i < this._workerSlots.length; i++)
|
||||
@ -488,7 +489,7 @@ export class Dispatcher {
|
||||
}
|
||||
|
||||
private _hasReachedMaxFailures() {
|
||||
const maxFailures = this._configLoader.fullConfig().maxFailures;
|
||||
const maxFailures = this._config.maxFailures;
|
||||
return maxFailures > 0 && this._failureCount >= maxFailures;
|
||||
}
|
||||
|
||||
@ -496,7 +497,7 @@ export class Dispatcher {
|
||||
if (result.status !== 'skipped' && result.status !== test.expectedStatus)
|
||||
++this._failureCount;
|
||||
this._reporter.onTestEnd?.(test, result);
|
||||
const maxFailures = this._configLoader.fullConfig().maxFailures;
|
||||
const maxFailures = this._config.maxFailures;
|
||||
if (maxFailures && this._failureCount === maxFailures)
|
||||
this.stop().catch(e => {});
|
||||
}
|
||||
|
||||
@ -15,8 +15,7 @@
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import type { TestError } from '../../types/testReporter';
|
||||
import type { ConfigLoader } from '../common/configLoader';
|
||||
import type { Reporter, TestError } from '../../types/testReporter';
|
||||
import type { LoadError } from '../common/fixtures';
|
||||
import { LoaderHost } from './loaderHost';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
@ -24,9 +23,12 @@ import { createRootSuite, filterOnly, filterSuite } from '../common/suiteUtils';
|
||||
import type { Suite, TestCase } from '../common/test';
|
||||
import { loadTestFilesInProcess } from '../common/testLoader';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import { errorWithFile } from '../util';
|
||||
import type { Matcher, TestFileFilter } from '../util';
|
||||
import { createFileMatcher } from '../util';
|
||||
import { collectFilesForProjects, collectProjects } from './projectUtils';
|
||||
import { requireOrImport } from '../common/transform';
|
||||
import { serializeConfig } from '../common/ipc';
|
||||
|
||||
type LoadOptions = {
|
||||
listOnly: boolean;
|
||||
@ -36,8 +38,7 @@ type LoadOptions = {
|
||||
passWithNoTests?: boolean;
|
||||
};
|
||||
|
||||
export async function loadAllTests(configLoader: ConfigLoader, reporter: Multiplexer, options: LoadOptions, errors: TestError[]): Promise<Suite> {
|
||||
const config = configLoader.fullConfig();
|
||||
export async function loadAllTests(config: FullConfigInternal, reporter: Multiplexer, options: LoadOptions, errors: TestError[]): Promise<Suite> {
|
||||
const projects = collectProjects(config, options.projectFilter);
|
||||
const filesByProject = await collectFilesForProjects(projects, options.testFileFilters);
|
||||
const allTestFiles = new Set<string>();
|
||||
@ -45,7 +46,7 @@ export async function loadAllTests(configLoader: ConfigLoader, reporter: Multipl
|
||||
files.forEach(file => allTestFiles.add(file));
|
||||
|
||||
// Load all tests.
|
||||
const preprocessRoot = await loadTests(configLoader, reporter, allTestFiles, errors);
|
||||
const preprocessRoot = await loadTests(config, reporter, allTestFiles, errors);
|
||||
|
||||
// Complain about duplicate titles.
|
||||
errors.push(...createDuplicateTitlesErrors(config, preprocessRoot));
|
||||
@ -67,10 +68,10 @@ export async function loadAllTests(configLoader: ConfigLoader, reporter: Multipl
|
||||
return await createRootSuite(preprocessRoot, options.testTitleMatcher, filesByProject);
|
||||
}
|
||||
|
||||
async function loadTests(configLoader: ConfigLoader, reporter: Multiplexer, testFiles: Set<string>, errors: TestError[]): Promise<Suite> {
|
||||
async function loadTests(config: FullConfigInternal, reporter: Multiplexer, testFiles: Set<string>, errors: TestError[]): Promise<Suite> {
|
||||
if (process.env.PW_TEST_OOP_LOADER) {
|
||||
const loaderHost = new LoaderHost();
|
||||
await loaderHost.start(configLoader.serializedConfig());
|
||||
await loaderHost.start(serializeConfig(config));
|
||||
try {
|
||||
return await loaderHost.loadTestFiles([...testFiles], reporter);
|
||||
} finally {
|
||||
@ -79,7 +80,7 @@ async function loadTests(configLoader: ConfigLoader, reporter: Multiplexer, test
|
||||
}
|
||||
const loadErrors: LoadError[] = [];
|
||||
try {
|
||||
return await loadTestFilesInProcess(configLoader.fullConfig(), [...testFiles], loadErrors);
|
||||
return await loadTestFilesInProcess(config, [...testFiles], loadErrors);
|
||||
} finally {
|
||||
errors.push(...loadErrors);
|
||||
}
|
||||
@ -140,3 +141,20 @@ function buildItemLocation(rootDir: string, testOrSuite: Suite | TestCase) {
|
||||
return '';
|
||||
return `${path.relative(rootDir, testOrSuite.location.file)}:${testOrSuite.location.line}`;
|
||||
}
|
||||
|
||||
async function requireOrImportDefaultFunction(file: string, expectConstructor: boolean) {
|
||||
let func = await requireOrImport(file);
|
||||
if (func && typeof func === 'object' && ('default' in func))
|
||||
func = func['default'];
|
||||
if (typeof func !== 'function')
|
||||
throw errorWithFile(file, `file must export a single ${expectConstructor ? 'class' : 'function'}.`);
|
||||
return func;
|
||||
}
|
||||
|
||||
export function loadGlobalHook(config: FullConfigInternal, file: string): Promise<(config: FullConfigInternal) => any> {
|
||||
return requireOrImportDefaultFunction(path.resolve(config.rootDir, file), false);
|
||||
}
|
||||
|
||||
export function loadReporter(config: FullConfigInternal, file: string): Promise<new (arg?: any) => Reporter> {
|
||||
return requireOrImportDefaultFunction(path.resolve(config.rootDir, file), true);
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
import path from 'path';
|
||||
import type { Reporter, TestError } from '../../types/testReporter';
|
||||
import type { ConfigLoader } from '../common/configLoader';
|
||||
import { formatError } from '../reporters/base';
|
||||
import DotReporter from '../reporters/dot';
|
||||
import EmptyReporter from '../reporters/empty';
|
||||
@ -28,9 +27,11 @@ import LineReporter from '../reporters/line';
|
||||
import ListReporter from '../reporters/list';
|
||||
import { Multiplexer } from '../reporters/multiplexer';
|
||||
import type { Suite } from '../common/test';
|
||||
import type { FullConfigInternal, ReporterDescription } from '../common/types';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import { loadReporter } from './loadUtils';
|
||||
import type { BuiltInReporter } from '../common/configLoader';
|
||||
|
||||
export async function createReporter(configLoader: ConfigLoader, list: boolean) {
|
||||
export async function createReporter(config: FullConfigInternal, list: boolean) {
|
||||
const defaultReporters: {[key in BuiltInReporter]: new(arg: any) => Reporter} = {
|
||||
dot: list ? ListModeReporter : DotReporter,
|
||||
line: list ? ListModeReporter : LineReporter,
|
||||
@ -42,17 +43,17 @@ export async function createReporter(configLoader: ConfigLoader, list: boolean)
|
||||
html: HtmlReporter,
|
||||
};
|
||||
const reporters: Reporter[] = [];
|
||||
for (const r of configLoader.fullConfig().reporter) {
|
||||
for (const r of config.reporter) {
|
||||
const [name, arg] = r;
|
||||
if (name in defaultReporters) {
|
||||
reporters.push(new defaultReporters[name as keyof typeof defaultReporters](arg));
|
||||
} else {
|
||||
const reporterConstructor = await configLoader.loadReporter(name);
|
||||
const reporterConstructor = await loadReporter(config, name);
|
||||
reporters.push(new reporterConstructor(arg));
|
||||
}
|
||||
}
|
||||
if (process.env.PW_TEST_REPORTER) {
|
||||
const reporterConstructor = await configLoader.loadReporter(process.env.PW_TEST_REPORTER);
|
||||
const reporterConstructor = await loadReporter(config, process.env.PW_TEST_REPORTER);
|
||||
reporters.push(new reporterConstructor());
|
||||
}
|
||||
|
||||
@ -98,14 +99,3 @@ export class ListModeReporter implements Reporter {
|
||||
console.error('\n' + formatError(this.config, error, false).message);
|
||||
}
|
||||
}
|
||||
|
||||
export function toReporters(reporters: BuiltInReporter | ReporterDescription[] | undefined): ReporterDescription[] | undefined {
|
||||
if (!reporters)
|
||||
return;
|
||||
if (typeof reporters === 'string')
|
||||
return [[reporters]];
|
||||
return reporters;
|
||||
}
|
||||
|
||||
export const builtInReporters = ['list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html'] as const;
|
||||
export type BuiltInReporter = typeof builtInReporters[number];
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
|
||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||
import type { FullResult } from '../../types/testReporter';
|
||||
import { ConfigLoader } from '../common/configLoader';
|
||||
import type { TestRunnerPlugin } from '../plugins';
|
||||
import { setRunnerToAddPluginsTo } from '../plugins';
|
||||
import { dockerPlugin } from '../plugins/dockerPlugin';
|
||||
@ -26,9 +25,8 @@ import { collectFilesForProjects, collectProjects } from './projectUtils';
|
||||
import { createReporter } from './reporters';
|
||||
import { createTaskRunner } from './tasks';
|
||||
import type { TaskRunnerState } from './tasks';
|
||||
import type { Config, FullConfigInternal } from '../common/types';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import type { Matcher, TestFileFilter } from '../util';
|
||||
import type { ConfigCLIOverrides } from '../common/ipc';
|
||||
|
||||
export type RunOptions = {
|
||||
listOnly: boolean;
|
||||
@ -39,11 +37,11 @@ export type RunOptions = {
|
||||
};
|
||||
|
||||
export class Runner {
|
||||
private _configLoader: ConfigLoader;
|
||||
private _config: FullConfigInternal;
|
||||
private _plugins: TestRunnerPlugin[] = [];
|
||||
|
||||
constructor(configCLIOverrides?: ConfigCLIOverrides) {
|
||||
this._configLoader = new ConfigLoader(configCLIOverrides);
|
||||
constructor(config: FullConfigInternal) {
|
||||
this._config = config;
|
||||
setRunnerToAddPluginsTo(this);
|
||||
}
|
||||
|
||||
@ -51,16 +49,8 @@ export class Runner {
|
||||
this._plugins.push(plugin);
|
||||
}
|
||||
|
||||
async loadConfigFromResolvedFile(resolvedConfigFile: string): Promise<FullConfigInternal> {
|
||||
return await this._configLoader.loadConfigFile(resolvedConfigFile);
|
||||
}
|
||||
|
||||
loadEmptyConfig(configFileOrDirectory: string): Promise<Config> {
|
||||
return this._configLoader.loadEmptyConfig(configFileOrDirectory);
|
||||
}
|
||||
|
||||
async listTestFiles(projectNames: string[] | undefined): Promise<any> {
|
||||
const projects = collectProjects(this._configLoader.fullConfig(), projectNames);
|
||||
const projects = collectProjects(this._config, projectNames);
|
||||
const filesByProject = await collectFilesForProjects(projects, []);
|
||||
const report: any = {
|
||||
projects: []
|
||||
@ -75,7 +65,7 @@ export class Runner {
|
||||
}
|
||||
|
||||
async runAllTests(options: RunOptions): Promise<FullResult['status']> {
|
||||
const config = this._configLoader.fullConfig();
|
||||
const config = this._config;
|
||||
const deadline = config.globalTimeout ? monotonicTime() + config.globalTimeout : 0;
|
||||
|
||||
// Legacy webServer support.
|
||||
@ -83,12 +73,11 @@ export class Runner {
|
||||
// Docker support.
|
||||
this._plugins.push(dockerPlugin);
|
||||
|
||||
const reporter = await createReporter(this._configLoader, options.listOnly);
|
||||
const reporter = await createReporter(config, options.listOnly);
|
||||
const taskRunner = createTaskRunner(config, reporter, this._plugins, options);
|
||||
|
||||
const context: TaskRunnerState = {
|
||||
config,
|
||||
configLoader: this._configLoader,
|
||||
options,
|
||||
reporter,
|
||||
};
|
||||
|
||||
@ -18,7 +18,6 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { promisify } from 'util';
|
||||
import { colors, rimraf } from 'playwright-core/lib/utilsBundle';
|
||||
import type { ConfigLoader } from '../common/configLoader';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { TestRunnerPlugin } from '../plugins';
|
||||
import type { Multiplexer } from '../reporters/multiplexer';
|
||||
@ -28,7 +27,7 @@ import type { Task } from './taskRunner';
|
||||
import { TaskRunner } from './taskRunner';
|
||||
import type { Suite } from '../common/test';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import { loadAllTests } from './loadUtils';
|
||||
import { loadAllTests, loadGlobalHook } from './loadUtils';
|
||||
import type { Matcher, TestFileFilter } from '../util';
|
||||
|
||||
const removeFolderAsync = promisify(rimraf);
|
||||
@ -46,7 +45,6 @@ export type TaskRunnerState = {
|
||||
options: TaskRunnerOptions;
|
||||
reporter: Multiplexer;
|
||||
config: FullConfigInternal;
|
||||
configLoader: ConfigLoader;
|
||||
rootSuite?: Suite;
|
||||
testGroups?: TestGroup[];
|
||||
dispatcher?: Dispatcher;
|
||||
@ -90,10 +88,10 @@ export function createPluginSetupTask(plugin: TestRunnerPlugin): Task<TaskRunner
|
||||
}
|
||||
|
||||
export function createGlobalSetupTask(): Task<TaskRunnerState> {
|
||||
return async ({ config, configLoader }) => {
|
||||
const setupHook = config.globalSetup ? await configLoader.loadGlobalHook(config.globalSetup) : undefined;
|
||||
const teardownHook = config.globalTeardown ? await configLoader.loadGlobalHook(config.globalTeardown) : undefined;
|
||||
const globalSetupResult = setupHook ? await setupHook(configLoader.fullConfig()) : undefined;
|
||||
return async ({ config }) => {
|
||||
const setupHook = config.globalSetup ? await loadGlobalHook(config, config.globalSetup) : undefined;
|
||||
const teardownHook = config.globalTeardown ? await loadGlobalHook(config, config.globalTeardown) : undefined;
|
||||
const globalSetupResult = setupHook ? await setupHook(config) : undefined;
|
||||
return async () => {
|
||||
if (typeof globalSetupResult === 'function')
|
||||
await globalSetupResult();
|
||||
@ -104,7 +102,7 @@ export function createGlobalSetupTask(): Task<TaskRunnerState> {
|
||||
|
||||
export function createSetupWorkersTask(): Task<TaskRunnerState> {
|
||||
return async params => {
|
||||
const { config, configLoader, testGroups, reporter } = params;
|
||||
const { config, testGroups, reporter } = params;
|
||||
if (config._ignoreSnapshots) {
|
||||
reporter.onStdOut(colors.dim([
|
||||
'NOTE: running with "ignoreSnapshots" option. All of the following asserts are silently ignored:',
|
||||
@ -114,7 +112,7 @@ export function createSetupWorkersTask(): Task<TaskRunnerState> {
|
||||
].join('\n')));
|
||||
}
|
||||
|
||||
const dispatcher = new Dispatcher(configLoader, testGroups!, reporter);
|
||||
const dispatcher = new Dispatcher(config, testGroups!, reporter);
|
||||
params.dispatcher = dispatcher;
|
||||
return async () => {
|
||||
await dispatcher.stop();
|
||||
@ -123,8 +121,7 @@ export function createSetupWorkersTask(): Task<TaskRunnerState> {
|
||||
}
|
||||
|
||||
export function createRemoveOutputDirsTask(): Task<TaskRunnerState> {
|
||||
return async ({ options, configLoader }) => {
|
||||
const config = configLoader.fullConfig();
|
||||
return async ({ config, options }) => {
|
||||
const outputDirs = new Set<string>();
|
||||
for (const p of config.projects) {
|
||||
if (!options.projectFilter || options.projectFilter.includes(p.name))
|
||||
@ -147,8 +144,8 @@ export function createRemoveOutputDirsTask(): Task<TaskRunnerState> {
|
||||
|
||||
function createLoadTask(): Task<TaskRunnerState> {
|
||||
return async (context, errors) => {
|
||||
const { config, reporter, options, configLoader } = context;
|
||||
const rootSuite = await loadAllTests(configLoader, reporter, options, errors);
|
||||
const { config, reporter, options } = context;
|
||||
const rootSuite = await loadAllTests(config, reporter, options, errors);
|
||||
const testGroups = options.listOnly ? [] : createTestGroups(rootSuite.suites, config.workers);
|
||||
|
||||
context.rootSuite = rootSuite;
|
||||
|
||||
@ -23,7 +23,6 @@ import { colors, debug, minimatch } from 'playwright-core/lib/utilsBundle';
|
||||
import type { TestInfoError, Location } from './common/types';
|
||||
import { calculateSha1, isRegExp, isString, captureStackTrace as coreCaptureStackTrace } from 'playwright-core/lib/utils';
|
||||
import { isInternalFileName } from 'playwright-core/lib/utils';
|
||||
import { currentTestInfo } from './common/globals';
|
||||
import type { ParsedStackTrace } from 'playwright-core/lib/utils';
|
||||
|
||||
export type { ParsedStackTrace };
|
||||
@ -31,7 +30,7 @@ export type { ParsedStackTrace };
|
||||
const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core'));
|
||||
const EXPECT_PATH = require.resolve('./common/expectBundle');
|
||||
const EXPECT_PATH_IMPL = require.resolve('./common/expectBundleImpl');
|
||||
const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '../..');
|
||||
const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..');
|
||||
|
||||
function filterStackTrace(e: Error) {
|
||||
if (process.env.PWDEBUGIMPL)
|
||||
@ -243,16 +242,6 @@ Call log:
|
||||
`;
|
||||
}
|
||||
|
||||
export function currentExpectTimeout(options: { timeout?: number }) {
|
||||
const testInfo = currentTestInfo();
|
||||
if (options.timeout !== undefined)
|
||||
return options.timeout;
|
||||
let defaultExpectTimeout = testInfo?.project._expect?.timeout;
|
||||
if (typeof defaultExpectTimeout === 'undefined')
|
||||
defaultExpectTimeout = 5000;
|
||||
return defaultExpectTimeout;
|
||||
}
|
||||
|
||||
const folderToPackageJsonPath = new Map<string, string>();
|
||||
|
||||
export function getPackageJsonPath(folderPath: string): string {
|
||||
|
||||
@ -21,7 +21,7 @@ import type { TestBeginPayload, TestEndPayload, RunPayload, DonePayload, WorkerI
|
||||
import { setCurrentTestInfo } from '../common/globals';
|
||||
import { ConfigLoader } from '../common/configLoader';
|
||||
import type { Suite, TestCase } from '../common/test';
|
||||
import type { Annotation, FullProjectInternal, TestInfoError } from '../common/types';
|
||||
import type { Annotation, FullConfigInternal, FullProjectInternal, TestInfoError } from '../common/types';
|
||||
import { FixtureRunner } from '../common/fixtures';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
||||
import { TestInfoImpl } from '../common/testInfo';
|
||||
@ -36,7 +36,7 @@ const removeFolderAsync = util.promisify(rimraf);
|
||||
|
||||
export class WorkerMain extends ProcessRunner {
|
||||
private _params: WorkerInitParams;
|
||||
private _configLoader!: ConfigLoader;
|
||||
private _config!: FullConfigInternal;
|
||||
private _testLoader!: TestLoader;
|
||||
private _project!: FullProjectInternal;
|
||||
private _poolBuilder!: PoolBuilder;
|
||||
@ -190,12 +190,13 @@ export class WorkerMain extends ProcessRunner {
|
||||
}
|
||||
|
||||
private async _loadIfNeeded() {
|
||||
if (this._configLoader)
|
||||
if (this._config)
|
||||
return;
|
||||
|
||||
this._configLoader = await ConfigLoader.deserialize(this._params.config);
|
||||
this._testLoader = new TestLoader(this._configLoader.fullConfig());
|
||||
this._project = this._configLoader.fullConfig().projects.find(p => p._id === this._params.projectId)!;
|
||||
const configLoader = await ConfigLoader.deserialize(this._params.config);
|
||||
this._config = configLoader.fullConfig();
|
||||
this._testLoader = new TestLoader(this._config);
|
||||
this._project = this._config.projects.find(p => p._id === this._params.projectId)!;
|
||||
this._poolBuilder = PoolBuilder.createForWorker(this._project);
|
||||
}
|
||||
|
||||
@ -251,7 +252,7 @@ export class WorkerMain extends ProcessRunner {
|
||||
}
|
||||
|
||||
private async _runTest(test: TestCase, retry: number, nextTest: TestCase | undefined) {
|
||||
const testInfo = new TestInfoImpl(this._configLoader.fullConfig(), this._project, this._params, test, retry,
|
||||
const testInfo = new TestInfoImpl(this._config, this._project, this._params, test, retry,
|
||||
stepBeginPayload => this.dispatchEvent('stepBegin', stepBeginPayload),
|
||||
stepEndPayload => this.dispatchEvent('stepEnd', stepEndPayload));
|
||||
|
||||
@ -485,8 +486,8 @@ export class WorkerMain extends ProcessRunner {
|
||||
setCurrentTestInfo(null);
|
||||
this.dispatchEvent('testEnd', buildTestEndPayload(testInfo));
|
||||
|
||||
const preserveOutput = this._configLoader.fullConfig().preserveOutput === 'always' ||
|
||||
(this._configLoader.fullConfig().preserveOutput === 'failures-only' && testInfo._isFailure());
|
||||
const preserveOutput = this._config.preserveOutput === 'always' ||
|
||||
(this._config.preserveOutput === 'failures-only' && testInfo._isFailure());
|
||||
if (!preserveOutput)
|
||||
await removeFolderAsync(testInfo.outputDir).catch(e => {});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user