diff --git a/packages/playwright/src/common/fixtures.ts b/packages/playwright/src/common/fixtures.ts index 53acadee04..8d2c7c2304 100644 --- a/packages/playwright/src/common/fixtures.ts +++ b/packages/playwright/src/common/fixtures.ts @@ -72,11 +72,11 @@ function isFixtureOption(value: any): value is FixtureTuple { export class FixturePool { readonly digest: string; - readonly registrations: Map; + private readonly _registrations: Map; private _onLoadError: LoadErrorSink; constructor(fixturesList: FixturesWithLocation[], onLoadError: LoadErrorSink, parentPool?: FixturePool, disallowWorkerFixtures?: boolean, optionOverrides?: OptionOverrides) { - this.registrations = new Map(parentPool ? parentPool.registrations : []); + this._registrations = new Map(parentPool ? parentPool._registrations : []); this._onLoadError = onLoadError; const allOverrides = optionOverrides?.overrides ?? {}; @@ -117,7 +117,7 @@ export class FixturePool { } let fn = value as (Function | any); - const previous = this.registrations.get(name); + const previous = this._registrations.get(name); if (previous && options) { if (previous.scope !== options.scope) { this._addLoadError(`Fixture "${name}" has already been registered as a { scope: '${previous.scope}' } fixture defined in ${formatLocation(previous.location)}.`, location); @@ -154,7 +154,7 @@ export class FixturePool { const deps = fixtureParameterNames(fn, location, e => this._onLoadError(e)); const registration: FixtureRegistration = { id: '', name, location, scope: options.scope, fn, auto: options.auto, option: options.option, timeout: options.timeout, customTitle: options.customTitle, hideStep: options.hideStep, deps, super: previous, optionOverride: isOptionsOverride }; registrationId(registration); - this.registrations.set(name, registration); + this._registrations.set(name, registration); } } @@ -165,7 +165,7 @@ export class FixturePool { markers.set(registration, 'visiting'); stack.push(registration); for (const name of registration.deps) { - const dep = this.resolveDependency(registration, name); + const dep = this.resolve(name, registration); if (!dep) { if (name === registration.name) this._addLoadError(`Fixture "${registration.name}" references itself, but does not have a base implementation.`, registration.location); @@ -192,9 +192,9 @@ export class FixturePool { }; const hash = crypto.createHash('sha1'); - const names = Array.from(this.registrations.keys()).sort(); + const names = Array.from(this._registrations.keys()).sort(); for (const name of names) { - const registration = this.registrations.get(name)!; + const registration = this._registrations.get(name)!; visit(registration); if (registration.scope === 'worker') hash.update(registration.id + ';'); @@ -204,16 +204,20 @@ export class FixturePool { validateFunction(fn: Function, prefix: string, location: Location) { for (const name of fixtureParameterNames(fn, location, e => this._onLoadError(e))) { - const registration = this.registrations.get(name); + const registration = this._registrations.get(name); if (!registration) this._addLoadError(`${prefix} has unknown parameter "${name}".`, location); } } - resolveDependency(registration: FixtureRegistration, name: string): FixtureRegistration | undefined { - if (name === registration.name) - return registration.super; - return this.registrations.get(name); + resolve(name: string, forFixture?: FixtureRegistration): FixtureRegistration | undefined { + if (name === forFixture?.name) + return forFixture.super; + return this._registrations.get(name); + } + + autoFixtures() { + return [...this._registrations.values()].filter(r => r.auto !== false); } private _addLoadError(message: string, location: Location) { diff --git a/packages/playwright/src/worker/fixtureRunner.ts b/packages/playwright/src/worker/fixtureRunner.ts index 2aed5c08f7..9a3bedc429 100644 --- a/packages/playwright/src/worker/fixtureRunner.ts +++ b/packages/playwright/src/worker/fixtureRunner.ts @@ -59,7 +59,7 @@ class Fixture { const params: { [key: string]: any } = {}; for (const name of this.registration.deps) { - const registration = this.runner.pool!.resolveDependency(this.registration, name)!; + const registration = this.runner.pool!.resolve(name, this.registration)!; const dep = await this.runner.setupFixtureForRegistration(registration, testInfo); // Fixture teardown is root => leafs, when we need to teardown a fixture, // it recursively tears down its usages first. @@ -221,9 +221,7 @@ export class FixtureRunner { async resolveParametersForFunction(fn: Function, testInfo: TestInfoImpl, autoFixtures: 'worker' | 'test' | 'all-hooks-only'): Promise { // Install automatic fixtures. const auto: FixtureRegistration[] = []; - for (const registration of this.pool!.registrations.values()) { - if (registration.auto === false) - continue; + for (const registration of this.pool!.autoFixtures()) { let shouldRun = true; if (autoFixtures === 'all-hooks-only') shouldRun = registration.scope === 'worker' || registration.auto === 'all-hooks-included'; @@ -243,7 +241,7 @@ export class FixtureRunner { const names = getRequiredFixtureNames(fn); const params: { [key: string]: any } = {}; for (const name of names) { - const registration = this.pool!.registrations.get(name)!; + const registration = this.pool!.resolve(name)!; const fixture = await this.setupFixtureForRegistration(registration, testInfo); if (fixture.failed) return null; @@ -278,7 +276,7 @@ export class FixtureRunner { dependsOnWorkerFixturesOnly(fn: Function, location: Location): boolean { const names = getRequiredFixtureNames(fn, location); for (const name of names) { - const registration = this.pool!.registrations.get(name)!; + const registration = this.pool!.resolve(name)!; if (registration.scope !== 'worker') return false; } diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index 3b4bd32b65..ffc6e81671 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -332,7 +332,7 @@ export class WorkerMain extends ProcessRunner { // test runner instead of a fixture belonging to Playwright. // However, for backwards compatibility, we have to read it from a fixture today. // We decided to not introduce the config-level option just yet. - const traceFixtureRegistration = test._pool!.registrations.get('trace'); + const traceFixtureRegistration = test._pool!.resolve('trace'); if (!traceFixtureRegistration) return; if (typeof traceFixtureRegistration.fn === 'function')