mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: fix oop loading, prepare to watch (#20618)
This commit is contained in:
parent
adab7a817e
commit
ffb719385b
@ -159,7 +159,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
configLoader.ignoreProjectDependencies();
|
||||
|
||||
const config = configLoader.fullConfig();
|
||||
config._internal.testFileFilters = args.map(arg => {
|
||||
config._internal.cliFileFilters = args.map(arg => {
|
||||
const match = /^(.*?):(\d+):?(\d+)?$/.exec(arg);
|
||||
return {
|
||||
re: forceRegExp(match ? match[1] : arg),
|
||||
@ -169,9 +169,9 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
});
|
||||
const grepMatcher = opts.grep ? createTitleMatcher(forceRegExp(opts.grep)) : () => true;
|
||||
const grepInvertMatcher = opts.grepInvert ? createTitleMatcher(forceRegExp(opts.grepInvert)) : () => false;
|
||||
config._internal.testTitleMatcher = (title: string) => !grepInvertMatcher(title) && grepMatcher(title);
|
||||
config._internal.cliTitleMatcher = (title: string) => !grepInvertMatcher(title) && grepMatcher(title);
|
||||
config._internal.listOnly = !!opts.list;
|
||||
config._internal.projectFilter = opts.project || undefined;
|
||||
config._internal.cliProjectFilter = opts.project || undefined;
|
||||
config._internal.passWithNoTests = !!opts.passWithNoTests;
|
||||
|
||||
const runner = new Runner(config);
|
||||
|
||||
@ -94,7 +94,12 @@ export function serializeCompilationCache(): any {
|
||||
};
|
||||
}
|
||||
|
||||
export function initializeCompilationCache(payload: any) {
|
||||
export function clearCompilationCache() {
|
||||
sourceMaps.clear();
|
||||
memoryCache.clear();
|
||||
}
|
||||
|
||||
export function addToCompilationCache(payload: any) {
|
||||
for (const entry of payload.sourceMaps)
|
||||
sourceMaps.set(entry[0], entry[1]);
|
||||
for (const entry of payload.memoryCache)
|
||||
|
||||
@ -450,8 +450,8 @@ export const baseFullConfig: FullConfigInternal = {
|
||||
maxConcurrentTestGroups: 0,
|
||||
ignoreSnapshots: false,
|
||||
plugins: [],
|
||||
testTitleMatcher: () => true,
|
||||
testFileFilters: [],
|
||||
cliTitleMatcher: () => true,
|
||||
cliFileFilters: [],
|
||||
listOnly: false,
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,9 +50,9 @@ type ConfigInternal = {
|
||||
webServers: Exclude<FullConfigPublic['webServer'], null>[];
|
||||
plugins: TestRunnerPluginRegistration[];
|
||||
listOnly: boolean;
|
||||
testFileFilters: TestFileFilter[];
|
||||
testTitleMatcher: Matcher;
|
||||
projectFilter?: string[];
|
||||
cliFileFilters: TestFileFilter[];
|
||||
cliTitleMatcher: Matcher;
|
||||
cliProjectFilter?: string[];
|
||||
passWithNoTests?: boolean;
|
||||
};
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import { ProcessRunner } from '../common/process';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import { loadTestFile } from '../common/testLoader';
|
||||
import type { TestError } from '../../reporter';
|
||||
import { addToCompilationCache, serializeCompilationCache } from '../common/compilationCache';
|
||||
|
||||
export class LoaderMain extends ProcessRunner {
|
||||
private _serializedConfig: SerializedConfig;
|
||||
@ -27,6 +28,7 @@ export class LoaderMain extends ProcessRunner {
|
||||
|
||||
constructor(serializedConfig: SerializedConfig) {
|
||||
super();
|
||||
addToCompilationCache(serializedConfig.compilationCache);
|
||||
this._serializedConfig = serializedConfig;
|
||||
}
|
||||
|
||||
@ -39,8 +41,12 @@ export class LoaderMain extends ProcessRunner {
|
||||
async loadTestFile(params: { file: string }) {
|
||||
const testErrors: TestError[] = [];
|
||||
const config = await this._config();
|
||||
const rootSuite = await loadTestFile(params.file, config.rootDir, testErrors);
|
||||
return { rootSuite: rootSuite._deepSerialize(), testErrors };
|
||||
const fileSuite = await loadTestFile(params.file, config.rootDir, testErrors);
|
||||
return { fileSuite: fileSuite._deepSerialize(), testErrors };
|
||||
}
|
||||
|
||||
async serializeCompilationCache() {
|
||||
return serializeCompilationCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,15 +21,15 @@ import type { LoaderHost } from './loaderHost';
|
||||
import { Suite } from '../common/test';
|
||||
import type { TestCase } from '../common/test';
|
||||
import type { FullConfigInternal, FullProjectInternal } from '../common/types';
|
||||
import { createFileMatcherFromFilters, createTitleMatcher, errorWithFile } from '../util';
|
||||
import { createTitleMatcher, errorWithFile } from '../util';
|
||||
import type { Matcher, TestFileFilter } from '../util';
|
||||
import { buildProjectsClosure, collectFilesForProject, filterProjects } from './projectUtils';
|
||||
import { requireOrImport } from '../common/transform';
|
||||
import { buildFileSuiteForProject, filterByFocusedLine, filterOnly, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
||||
import { filterForShard } from './testGroups';
|
||||
|
||||
export async function loadAllTests(config: FullConfigInternal, errors: TestError[]): Promise<Suite> {
|
||||
const projects = filterProjects(config.projects, config._internal.projectFilter);
|
||||
export async function loadAllTests(config: FullConfigInternal, projectsToIgnore: Set<FullProjectInternal>, fileMatcher: Matcher, errors: TestError[]): Promise<Suite> {
|
||||
const projects = filterProjects(config.projects, config._internal.cliProjectFilter);
|
||||
|
||||
let filesToRunByProject = new Map<FullProjectInternal, string[]>();
|
||||
let topLevelProjects: FullProjectInternal[];
|
||||
@ -41,14 +41,15 @@ export async function loadAllTests(config: FullConfigInternal, errors: TestError
|
||||
// First collect all files for the projects in the command line, don't apply any file filters.
|
||||
const allFilesForProject = new Map<FullProjectInternal, string[]>();
|
||||
for (const project of projects) {
|
||||
if (projectsToIgnore.has(project))
|
||||
continue;
|
||||
const files = await collectFilesForProject(project, fsCache);
|
||||
allFilesForProject.set(project, files);
|
||||
}
|
||||
|
||||
// Filter files based on the file filters, eliminate the empty projects.
|
||||
const commandLineFileMatcher = config._internal.testFileFilters.length ? createFileMatcherFromFilters(config._internal.testFileFilters) : null;
|
||||
for (const [project, files] of allFilesForProject) {
|
||||
const filteredFiles = commandLineFileMatcher ? files.filter(commandLineFileMatcher) : files;
|
||||
const filteredFiles = files.filter(fileMatcher);
|
||||
if (filteredFiles.length)
|
||||
filesToRunByProject.set(project, filteredFiles);
|
||||
}
|
||||
@ -67,6 +68,9 @@ export async function loadAllTests(config: FullConfigInternal, errors: TestError
|
||||
topLevelProjects = filteredProjectClosure.filter(p => p._internal.type === 'top-level');
|
||||
dependencyProjects = filteredProjectClosure.filter(p => p._internal.type === 'dependency');
|
||||
|
||||
topLevelProjects = topLevelProjects.filter(p => !projectsToIgnore.has(p));
|
||||
dependencyProjects = dependencyProjects.filter(p => !projectsToIgnore.has(p));
|
||||
|
||||
// (Re-)add all files for dependent projects, disregard filters.
|
||||
for (const project of dependencyProjects) {
|
||||
const files = allFilesForProject.get(project) || await collectFilesForProject(project, fsCache);
|
||||
@ -113,7 +117,7 @@ export async function loadAllTests(config: FullConfigInternal, errors: TestError
|
||||
|
||||
// Prepend the projects that are dependencies.
|
||||
for (const project of dependencyProjects) {
|
||||
const projectSuite = await createProjectSuite(fileSuits, project, { testFileFilters: [], testTitleMatcher: undefined }, filesToRunByProject.get(project)!);
|
||||
const projectSuite = await createProjectSuite(fileSuits, project, { cliFileFilters: [], cliTitleMatcher: undefined }, filesToRunByProject.get(project)!);
|
||||
if (projectSuite)
|
||||
rootSuite._prependSuite(projectSuite);
|
||||
}
|
||||
@ -121,7 +125,7 @@ export async function loadAllTests(config: FullConfigInternal, errors: TestError
|
||||
return rootSuite;
|
||||
}
|
||||
|
||||
async function createProjectSuite(fileSuits: Suite[], project: FullProjectInternal, options: { testFileFilters: TestFileFilter[], testTitleMatcher?: Matcher }, files: string[]): Promise<Suite | null> {
|
||||
async function createProjectSuite(fileSuits: Suite[], project: FullProjectInternal, options: { cliFileFilters: TestFileFilter[], cliTitleMatcher?: Matcher }, files: string[]): Promise<Suite | null> {
|
||||
const fileSuitesMap = new Map<string, Suite>();
|
||||
for (const fileSuite of fileSuits)
|
||||
fileSuitesMap.set(fileSuite._requireFile, fileSuite);
|
||||
@ -140,7 +144,7 @@ async function createProjectSuite(fileSuits: Suite[], project: FullProjectIntern
|
||||
}
|
||||
}
|
||||
// Filter tests to respect line/column filter.
|
||||
filterByFocusedLine(projectSuite, options.testFileFilters);
|
||||
filterByFocusedLine(projectSuite, options.cliFileFilters);
|
||||
|
||||
const grepMatcher = createTitleMatcher(project.grep);
|
||||
const grepInvertMatcher = project.grepInvert ? createTitleMatcher(project.grepInvert) : null;
|
||||
@ -149,7 +153,7 @@ async function createProjectSuite(fileSuits: Suite[], project: FullProjectIntern
|
||||
const grepTitle = test.titlePath().join(' ');
|
||||
if (grepInvertMatcher?.(grepTitle))
|
||||
return false;
|
||||
return grepMatcher(grepTitle) && (!options.testTitleMatcher || options.testTitleMatcher(grepTitle));
|
||||
return grepMatcher(grepTitle) && (!options.cliTitleMatcher || options.cliTitleMatcher(grepTitle));
|
||||
};
|
||||
|
||||
if (filterTestsRemoveEmptySuites(projectSuite, titleMatcher))
|
||||
|
||||
@ -22,6 +22,7 @@ import { loadTestFile } from '../common/testLoader';
|
||||
import type { LoadError } from '../common/fixtures';
|
||||
import type { FullConfigInternal } from '../common/types';
|
||||
import { PoolBuilder } from '../common/poolBuilder';
|
||||
import { addToCompilationCache } from '../common/compilationCache';
|
||||
|
||||
export abstract class LoaderHost {
|
||||
protected _config: FullConfigInternal;
|
||||
@ -56,18 +57,20 @@ export class OutOfProcessLoaderHost extends LoaderHost {
|
||||
|
||||
constructor(config: FullConfigInternal) {
|
||||
super(config);
|
||||
this._processHost = new ProcessHost(require.resolve('../loaderMain.js'), 'loader');
|
||||
this._processHost = new ProcessHost(require.resolve('../loader/loaderMain.js'), 'loader');
|
||||
this._startPromise = this._processHost.startRunner(serializeConfig(config), true, {});
|
||||
}
|
||||
|
||||
async doLoadTestFile(file: string, loadErrors: LoadError[]): Promise<Suite> {
|
||||
await this._startPromise;
|
||||
const result = await this._processHost.sendMessage({ method: 'loadTestFile', params: { file } }) as any;
|
||||
loadErrors.push(...result.loadErrors);
|
||||
loadErrors.push(...result.testErrors);
|
||||
return Suite._deepParse(result.fileSuite);
|
||||
}
|
||||
|
||||
override async stop() {
|
||||
const result = await this._processHost.sendMessage({ method: 'serializeCompilationCache' }) as any;
|
||||
addToCompilationCache(result);
|
||||
await this._processHost.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ import { TaskRunner } from './taskRunner';
|
||||
import type { Suite } from '../common/test';
|
||||
import type { FullConfigInternal, FullProjectInternal } from '../common/types';
|
||||
import { loadAllTests, loadGlobalHook } from './loadUtils';
|
||||
import { createFileMatcherFromFilters } from '../util';
|
||||
import type { Matcher } from '../util';
|
||||
|
||||
const removeFolderAsync = promisify(rimraf);
|
||||
const readDirAsync = promisify(fs.readdir);
|
||||
@ -106,7 +108,7 @@ function createRemoveOutputDirsTask(): Task<TaskRunnerState> {
|
||||
return async ({ config }) => {
|
||||
const outputDirs = new Set<string>();
|
||||
for (const p of config.projects) {
|
||||
if (!config._internal.projectFilter || config._internal.projectFilter.includes(p.name))
|
||||
if (!config._internal.cliProjectFilter || config._internal.cliProjectFilter.includes(p.name))
|
||||
outputDirs.add(p.outputDir);
|
||||
}
|
||||
|
||||
@ -124,10 +126,12 @@ function createRemoveOutputDirsTask(): Task<TaskRunnerState> {
|
||||
};
|
||||
}
|
||||
|
||||
function createLoadTask(): Task<TaskRunnerState> {
|
||||
function createLoadTask(projectsToIgnore = new Set<FullProjectInternal>(), additionalFileMatcher?: Matcher): Task<TaskRunnerState> {
|
||||
return async (context, errors) => {
|
||||
const { config } = context;
|
||||
context.rootSuite = await loadAllTests(config, errors);
|
||||
const cliMatcher = config._internal.cliFileFilters.length ? createFileMatcherFromFilters(config._internal.cliFileFilters) : () => true;
|
||||
const fileMatcher = (value: string) => cliMatcher(value) && (additionalFileMatcher ? additionalFileMatcher(value) : true);
|
||||
context.rootSuite = await loadAllTests(config, projectsToIgnore, fileMatcher, errors);
|
||||
// Fail when no tests.
|
||||
if (!context.rootSuite.allTests().length && !config._internal.passWithNoTests && !config.shard)
|
||||
throw new Error(`No tests found`);
|
||||
|
||||
@ -31,7 +31,7 @@ import { ProcessRunner } from '../common/process';
|
||||
import { loadTestFile } from '../common/testLoader';
|
||||
import { buildFileSuiteForProject, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
||||
import { PoolBuilder } from '../common/poolBuilder';
|
||||
import { initializeCompilationCache } from '../common/compilationCache';
|
||||
import { addToCompilationCache } from '../common/compilationCache';
|
||||
|
||||
const removeFolderAsync = util.promisify(rimraf);
|
||||
|
||||
@ -67,7 +67,7 @@ export class WorkerMain extends ProcessRunner {
|
||||
process.env.TEST_WORKER_INDEX = String(params.workerIndex);
|
||||
process.env.TEST_PARALLEL_INDEX = String(params.parallelIndex);
|
||||
setIsWorkerProcess();
|
||||
initializeCompilationCache(params.config.compilationCache);
|
||||
addToCompilationCache(params.config.compilationCache);
|
||||
|
||||
this._params = params;
|
||||
this._fixtureRunner = new FixtureRunner();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user