chore: remove FullProjectInternal.from (#22280)

This commit is contained in:
Pavel Feldman 2023-04-07 19:12:20 -07:00 committed by GitHub
parent 1efa8de526
commit 635a2dac16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 39 additions and 23 deletions

View file

@ -153,10 +153,6 @@ export class FullProjectInternal {
id = ''; id = '';
deps: FullProjectInternal[] = []; deps: FullProjectInternal[] = [];
static from(project: FullProject): FullProjectInternal {
return (project as any)[projectInternalSymbol];
}
constructor(configDir: string, config: Config, fullConfig: FullConfigInternal, projectConfig: Project, configCLIOverrides: ConfigCLIOverrides, throwawayArtifactsPath: string) { constructor(configDir: string, config: Config, fullConfig: FullConfigInternal, projectConfig: Project, configCLIOverrides: ConfigCLIOverrides, throwawayArtifactsPath: string) {
this.fullConfig = fullConfig; this.fullConfig = fullConfig;
const testDir = takeFirst(pathResolve(configDir, projectConfig.testDir), pathResolve(configDir, config.testDir), fullConfig.configDir); const testDir = takeFirst(pathResolve(configDir, projectConfig.testDir), pathResolve(configDir, config.testDir), fullConfig.configDir);

View file

@ -16,7 +16,6 @@
import type { TestInfoImpl } from '../worker/testInfo'; import type { TestInfoImpl } from '../worker/testInfo';
import type { Suite } from './test'; import type { Suite } from './test';
import { FullProjectInternal } from './config';
import type { FullConfigInternal } from './config'; import type { FullConfigInternal } from './config';
let currentTestInfoValue: TestInfoImpl | null = null; let currentTestInfoValue: TestInfoImpl | null = null;
@ -39,7 +38,7 @@ export function currentExpectTimeout(options: { timeout?: number }) {
const testInfo = currentTestInfo(); const testInfo = currentTestInfo();
if (options.timeout !== undefined) if (options.timeout !== undefined)
return options.timeout; return options.timeout;
let defaultExpectTimeout = testInfo?.project ? FullProjectInternal.from(testInfo.project).expect?.timeout : undefined; let defaultExpectTimeout = testInfo?._projectInternal?.expect?.timeout;
if (typeof defaultExpectTimeout === 'undefined') if (typeof defaultExpectTimeout === 'undefined')
defaultExpectTimeout = 5000; defaultExpectTimeout = 5000;
return defaultExpectTimeout; return defaultExpectTimeout;

View file

@ -51,7 +51,7 @@ export class Suite extends Base implements SuitePrivate {
_staticAnnotations: Annotation[] = []; _staticAnnotations: Annotation[] = [];
_modifiers: Modifier[] = []; _modifiers: Modifier[] = [];
_parallelMode: 'default' | 'serial' | 'parallel' = 'default'; _parallelMode: 'default' | 'serial' | 'parallel' = 'default';
_projectConfig: FullProjectInternal | undefined; _fullProject: FullProjectInternal | undefined;
_fileId: string | undefined; _fileId: string | undefined;
readonly _type: 'root' | 'project' | 'file' | 'describe'; readonly _type: 'root' | 'project' | 'file' | 'describe';
@ -194,12 +194,12 @@ export class Suite extends Base implements SuitePrivate {
const suite = Suite._parse(data); const suite = Suite._parse(data);
suite._use = this._use.slice(); suite._use = this._use.slice();
suite._hooks = this._hooks.slice(); suite._hooks = this._hooks.slice();
suite._projectConfig = this._projectConfig; suite._fullProject = this._fullProject;
return suite; return suite;
} }
project(): FullProject | undefined { project(): FullProject | undefined {
return this._projectConfig?.project || this.parent?.project(); return this._fullProject?.project || this.parent?.project();
} }
} }

View file

@ -21,7 +21,7 @@ import type { FullConfig, TestCase, Suite, TestResult, TestError, FullResult, Te
import type { SuitePrivate } from '../../types/reporterPrivate'; import type { SuitePrivate } from '../../types/reporterPrivate';
import { codeFrameColumns } from '../common/babelBundle'; import { codeFrameColumns } from '../common/babelBundle';
import { monotonicTime } from 'playwright-core/lib/utils'; import { monotonicTime } from 'playwright-core/lib/utils';
import type { FullProject } from '../../types/test';
export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' }; export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' };
export const kOutputSymbol = Symbol('output'); export const kOutputSymbol = Symbol('output');
@ -523,6 +523,23 @@ function fitToWidth(line: string, width: number, prefix?: string): string {
return taken.reverse().join(''); return taken.reverse().join('');
} }
export function uniqueProjectIds(projects: FullProject[]): Map<FullProject, string> {
const usedNames = new Set<string>();
const result = new Map<FullProject, string>();
for (const p of projects) {
const name = p.name || '';
for (let i = 0; i < projects.length; ++i) {
const candidate = name + (i ? i : '');
if (usedNames.has(candidate))
continue;
result.set(p, candidate);
usedNames.add(candidate);
break;
}
}
return result;
}
function belongsToNodeModules(file: string) { function belongsToNodeModules(file: string) {
return file.includes(`${path.sep}node_modules${path.sep}`); return file.includes(`${path.sep}node_modules${path.sep}`);
} }

View file

@ -17,10 +17,10 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, FullResult, Location, Reporter, JSONReport, JSONReportSuite, JSONReportSpec, JSONReportTest, JSONReportTestResult, JSONReportTestStep, JSONReportError } from '../../types/testReporter'; import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, FullResult, Location, Reporter, JSONReport, JSONReportSuite, JSONReportSpec, JSONReportTest, JSONReportTestResult, JSONReportTestStep, JSONReportError } from '../../types/testReporter';
import { formatError, prepareErrorStack } from './base'; import { formatError, prepareErrorStack, uniqueProjectIds } from './base';
import { MultiMap } from 'playwright-core/lib/utils'; import { MultiMap } from 'playwright-core/lib/utils';
import { assert } from 'playwright-core/lib/utils'; import { assert } from 'playwright-core/lib/utils';
import { FullProjectInternal } from '../common/config'; import type { FullProject } from '../../types/test';
export function toPosixPath(aPath: string): string { export function toPosixPath(aPath: string): string {
return aPath.split(path.sep).join(path.posix.sep); return aPath.split(path.sep).join(path.posix.sep);
@ -54,6 +54,7 @@ class JSONReporter implements Reporter {
} }
private _serializeReport(): JSONReport { private _serializeReport(): JSONReport {
const projectIds = uniqueProjectIds(this.config.projects);
return { return {
config: { config: {
...removePrivateFields(this.config), ...removePrivateFields(this.config),
@ -64,7 +65,7 @@ class JSONReporter implements Reporter {
repeatEach: project.repeatEach, repeatEach: project.repeatEach,
retries: project.retries, retries: project.retries,
metadata: project.metadata, metadata: project.metadata,
id: FullProjectInternal.from(project).id, id: projectIds.get(project)!,
name: project.name, name: project.name,
testDir: toPosixPath(project.testDir), testDir: toPosixPath(project.testDir),
testIgnore: serializePatterns(project.testIgnore), testIgnore: serializePatterns(project.testIgnore),
@ -73,15 +74,15 @@ class JSONReporter implements Reporter {
}; };
}) })
}, },
suites: this._mergeSuites(this.suite.suites), suites: this._mergeSuites(this.suite.suites, projectIds),
errors: this._errors errors: this._errors
}; };
} }
private _mergeSuites(suites: Suite[]): JSONReportSuite[] { private _mergeSuites(suites: Suite[], projectIds: Map<FullProject, string>): JSONReportSuite[] {
const fileSuites = new MultiMap<string, JSONReportSuite>(); const fileSuites = new MultiMap<string, JSONReportSuite>();
for (const projectSuite of suites) { for (const projectSuite of suites) {
const projectId = FullProjectInternal.from(projectSuite.project()!).id; const projectId = projectIds.get(projectSuite.project()!)!;
const projectName = projectSuite.project()!.name; const projectName = projectSuite.project()!.name;
for (const fileSuite of projectSuite.suites) { for (const fileSuite of projectSuite.suites) {
const file = fileSuite.location!.file; const file = fileSuite.location!.file;

View file

@ -18,10 +18,12 @@ import type { FullConfig, FullResult, Reporter, TestError, TestResult, TestStep,
import type { Suite, TestCase } from '../common/test'; import type { Suite, TestCase } from '../common/test';
import type { JsonConfig, JsonProject, JsonSuite, JsonTestCase, JsonTestEnd, JsonTestResultEnd, JsonTestResultStart, JsonTestStepEnd, JsonTestStepStart } from '../isomorphic/teleReceiver'; import type { JsonConfig, JsonProject, JsonSuite, JsonTestCase, JsonTestEnd, JsonTestResultEnd, JsonTestResultStart, JsonTestStepEnd, JsonTestStepStart } from '../isomorphic/teleReceiver';
import type { SuitePrivate } from '../../types/reporterPrivate'; import type { SuitePrivate } from '../../types/reporterPrivate';
import { FullConfigInternal, FullProjectInternal } from '../common/config'; import { FullConfigInternal } from '../common/config';
import { createGuid } from 'playwright-core/lib/utils'; import { createGuid } from 'playwright-core/lib/utils';
import { serializeRegexPatterns } from '../isomorphic/teleReceiver'; import { serializeRegexPatterns } from '../isomorphic/teleReceiver';
import path from 'path'; import path from 'path';
import type { FullProject } from '../../types/test';
import { uniqueProjectIds } from './base';
export class TeleReporterEmitter implements Reporter { export class TeleReporterEmitter implements Reporter {
private _messageSink: (message: any) => void; private _messageSink: (message: any) => void;
@ -34,8 +36,9 @@ export class TeleReporterEmitter implements Reporter {
onBegin(config: FullConfig, suite: Suite) { onBegin(config: FullConfig, suite: Suite) {
this._rootDir = config.rootDir; this._rootDir = config.rootDir;
const projects: any[] = []; const projects: any[] = [];
const projectIds = uniqueProjectIds(config.projects);
for (const projectSuite of suite.suites) { for (const projectSuite of suite.suites) {
const report = this._serializeProject(projectSuite); const report = this._serializeProject(projectSuite, projectIds);
projects.push(report); projects.push(report);
} }
this._messageSink({ method: 'onBegin', params: { config: this._serializeConfig(config), projects } }); this._messageSink({ method: 'onBegin', params: { config: this._serializeConfig(config), projects } });
@ -128,10 +131,10 @@ export class TeleReporterEmitter implements Reporter {
}; };
} }
private _serializeProject(suite: Suite): JsonProject { private _serializeProject(suite: Suite, projectIds: Map<FullProject, string>): JsonProject {
const project = suite.project()!; const project = suite.project()!;
const report: JsonProject = { const report: JsonProject = {
id: FullProjectInternal.from(project).id, id: projectIds.get(project)!,
metadata: project.metadata, metadata: project.metadata,
name: project.name, name: project.name,
outputDir: this._relativePath(project.outputDir), outputDir: this._relativePath(project.outputDir),

View file

@ -172,7 +172,7 @@ export async function createRootSuite(testRun: TestRun, errors: TestError[], sho
{ {
// Filtering only and sharding might have reduced the number of top-level projects. // Filtering only and sharding might have reduced the number of top-level projects.
// Build the project closure to only include dependencies that are still needed. // Build the project closure to only include dependencies that are still needed.
const projectClosure = new Map(buildProjectsClosure(rootSuite.suites.map(suite => suite._projectConfig!))); const projectClosure = new Map(buildProjectsClosure(rootSuite.suites.map(suite => suite._fullProject!)));
// Clone file suites for dependency projects. // Clone file suites for dependency projects.
for (const [project, fileSuites] of testRun.projectSuites) { for (const [project, fileSuites] of testRun.projectSuites) {
@ -186,7 +186,7 @@ export async function createRootSuite(testRun: TestRun, errors: TestError[], sho
async function createProjectSuite(fileSuites: Suite[], project: FullProjectInternal, options: { cliFileFilters: TestFileFilter[], cliTitleMatcher?: Matcher, testIdMatcher?: Matcher }): Promise<Suite> { async function createProjectSuite(fileSuites: Suite[], project: FullProjectInternal, options: { cliFileFilters: TestFileFilter[], cliTitleMatcher?: Matcher, testIdMatcher?: Matcher }): Promise<Suite> {
const projectSuite = new Suite(project.project.name, 'project'); const projectSuite = new Suite(project.project.name, 'project');
projectSuite._projectConfig = project; projectSuite._fullProject = project;
if (project.fullyParallel) if (project.fullyParallel)
projectSuite._parallelMode = 'parallel'; projectSuite._parallelMode = 'parallel';
for (const fileSuite of fileSuites) { for (const fileSuite of fileSuites) {

View file

@ -180,7 +180,7 @@ function createPhasesTask(): Task<TestRun> {
let maxConcurrentTestGroups = 0; let maxConcurrentTestGroups = 0;
const processed = new Set<FullProjectInternal>(); const processed = new Set<FullProjectInternal>();
const projectToSuite = new Map(testRun.rootSuite!.suites.map(suite => [suite._projectConfig!, suite])); const projectToSuite = new Map(testRun.rootSuite!.suites.map(suite => [suite._fullProject!, suite]));
for (let i = 0; i < projectToSuite.size; i++) { for (let i = 0; i < projectToSuite.size; i++) {
// Find all projects that have all their dependencies processed by previous phases. // Find all projects that have all their dependencies processed by previous phases.
const phaseProjects: FullProjectInternal[] = []; const phaseProjects: FullProjectInternal[] = [];