ScuttleBot

scuttlebot / tests / e2e / node_modules / playwright / lib / worker / fixtureRunner.js
Blame History Raw 263 lines
1
"use strict";
2
var __defProp = Object.defineProperty;
3
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
var __getOwnPropNames = Object.getOwnPropertyNames;
5
var __hasOwnProp = Object.prototype.hasOwnProperty;
6
var __export = (target, all) => {
7
for (var name in all)
8
__defProp(target, name, { get: all[name], enumerable: true });
9
};
10
var __copyProps = (to, from, except, desc) => {
11
if (from && typeof from === "object" || typeof from === "function") {
12
for (let key of __getOwnPropNames(from))
13
if (!__hasOwnProp.call(to, key) && key !== except)
14
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
}
16
return to;
17
};
18
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
var fixtureRunner_exports = {};
20
__export(fixtureRunner_exports, {
21
FixtureRunner: () => FixtureRunner
22
});
23
module.exports = __toCommonJS(fixtureRunner_exports);
24
var import_utils = require("playwright-core/lib/utils");
25
var import_fixtures = require("../common/fixtures");
26
var import_util = require("../util");
27
class Fixture {
28
constructor(runner, registration) {
29
this.failed = false;
30
this._deps = /* @__PURE__ */ new Set();
31
this._usages = /* @__PURE__ */ new Set();
32
this.runner = runner;
33
this.registration = registration;
34
this.value = null;
35
const isUserFixture = this.registration.location && (0, import_util.filterStackFile)(this.registration.location.file);
36
const title = this.registration.customTitle || this.registration.name;
37
const location = isUserFixture ? this.registration.location : void 0;
38
this._stepInfo = { title: `Fixture ${(0, import_utils.escapeWithQuotes)(title, '"')}`, category: "fixture", location };
39
if (this.registration.box === "self")
40
this._stepInfo = void 0;
41
else if (this.registration.box)
42
this._stepInfo.group = isUserFixture ? "configuration" : "internal";
43
this._setupDescription = {
44
title,
45
phase: "setup",
46
location,
47
slot: this.registration.timeout !== void 0 ? {
48
timeout: this.registration.timeout,
49
elapsed: 0
50
} : this.registration.scope === "worker" ? {
51
timeout: this.runner.workerFixtureTimeout,
52
elapsed: 0
53
} : void 0
54
};
55
this._teardownDescription = { ...this._setupDescription, phase: "teardown" };
56
}
57
async setup(testInfo, runnable) {
58
this.runner.instanceForId.set(this.registration.id, this);
59
if (typeof this.registration.fn !== "function") {
60
this.value = this.registration.fn;
61
return;
62
}
63
const run = () => testInfo._runWithTimeout({ ...runnable, fixture: this._setupDescription }, () => this._setupInternal(testInfo));
64
if (this._stepInfo)
65
await testInfo._runAsStep(this._stepInfo, run);
66
else
67
await run();
68
}
69
async _setupInternal(testInfo) {
70
const params = {};
71
for (const name of this.registration.deps) {
72
const registration = this.runner.pool.resolve(name, this.registration);
73
const dep = this.runner.instanceForId.get(registration.id);
74
if (!dep) {
75
this.failed = true;
76
return;
77
}
78
dep._usages.add(this);
79
this._deps.add(dep);
80
params[name] = dep.value;
81
if (dep.failed) {
82
this.failed = true;
83
return;
84
}
85
}
86
let called = false;
87
const useFuncStarted = new import_utils.ManualPromise();
88
const useFunc = async (value) => {
89
if (called)
90
throw new Error(`Cannot provide fixture value for the second time`);
91
called = true;
92
this.value = value;
93
this._useFuncFinished = new import_utils.ManualPromise();
94
useFuncStarted.resolve();
95
await this._useFuncFinished;
96
};
97
const workerInfo = { config: testInfo.config, parallelIndex: testInfo.parallelIndex, workerIndex: testInfo.workerIndex, project: testInfo.project };
98
const info = this.registration.scope === "worker" ? workerInfo : testInfo;
99
this._selfTeardownComplete = (async () => {
100
try {
101
await this.registration.fn(params, useFunc, info);
102
if (!useFuncStarted.isDone())
103
throw new Error(`use() was not called in fixture "${this.registration.name}"`);
104
} catch (error) {
105
this.failed = true;
106
if (!useFuncStarted.isDone())
107
useFuncStarted.reject(error);
108
else
109
throw error;
110
}
111
})();
112
await useFuncStarted;
113
}
114
async teardown(testInfo, runnable) {
115
try {
116
const fixtureRunnable = { ...runnable, fixture: this._teardownDescription };
117
if (!testInfo._timeoutManager.isTimeExhaustedFor(fixtureRunnable)) {
118
const run = () => testInfo._runWithTimeout(fixtureRunnable, () => this._teardownInternal());
119
if (this._stepInfo)
120
await testInfo._runAsStep(this._stepInfo, run);
121
else
122
await run();
123
}
124
} finally {
125
for (const dep of this._deps)
126
dep._usages.delete(this);
127
this.runner.instanceForId.delete(this.registration.id);
128
}
129
}
130
async _teardownInternal() {
131
if (typeof this.registration.fn !== "function")
132
return;
133
if (this._usages.size !== 0) {
134
console.error("Internal error: fixture integrity at", this._teardownDescription.title);
135
this._usages.clear();
136
}
137
if (this._useFuncFinished) {
138
this._useFuncFinished.resolve();
139
this._useFuncFinished = void 0;
140
await this._selfTeardownComplete;
141
}
142
}
143
_collectFixturesInTeardownOrder(scope, collector) {
144
if (this.registration.scope !== scope)
145
return;
146
for (const fixture of this._usages)
147
fixture._collectFixturesInTeardownOrder(scope, collector);
148
collector.add(this);
149
}
150
}
151
class FixtureRunner {
152
constructor() {
153
this.testScopeClean = true;
154
this.instanceForId = /* @__PURE__ */ new Map();
155
this.workerFixtureTimeout = 0;
156
}
157
setPool(pool) {
158
if (!this.testScopeClean)
159
throw new Error("Did not teardown test scope");
160
if (this.pool && pool.digest !== this.pool.digest) {
161
throw new Error([
162
`Playwright detected inconsistent test.use() options.`,
163
`Most common mistakes that lead to this issue:`,
164
` - Calling test.use() outside of the test file, for example in a common helper.`,
165
` - One test file imports from another test file.`
166
].join("\n"));
167
}
168
this.pool = pool;
169
}
170
_collectFixturesInSetupOrder(registration, collector) {
171
if (collector.has(registration))
172
return;
173
for (const name of registration.deps) {
174
const dep = this.pool.resolve(name, registration);
175
this._collectFixturesInSetupOrder(dep, collector);
176
}
177
collector.add(registration);
178
}
179
async teardownScope(scope, testInfo, runnable) {
180
const fixtures = Array.from(this.instanceForId.values()).reverse();
181
const collector = /* @__PURE__ */ new Set();
182
for (const fixture of fixtures)
183
fixture._collectFixturesInTeardownOrder(scope, collector);
184
let firstError;
185
for (const fixture of collector) {
186
try {
187
await fixture.teardown(testInfo, runnable);
188
} catch (error) {
189
firstError = firstError ?? error;
190
}
191
}
192
if (scope === "test")
193
this.testScopeClean = true;
194
if (firstError)
195
throw firstError;
196
}
197
async resolveParametersForFunction(fn, testInfo, autoFixtures, runnable) {
198
const collector = /* @__PURE__ */ new Set();
199
const auto = [];
200
for (const registration of this.pool.autoFixtures()) {
201
let shouldRun = true;
202
if (autoFixtures === "all-hooks-only")
203
shouldRun = registration.scope === "worker" || registration.auto === "all-hooks-included";
204
else if (autoFixtures === "worker")
205
shouldRun = registration.scope === "worker";
206
if (shouldRun)
207
auto.push(registration);
208
}
209
auto.sort((r1, r2) => (r1.scope === "worker" ? 0 : 1) - (r2.scope === "worker" ? 0 : 1));
210
for (const registration of auto)
211
this._collectFixturesInSetupOrder(registration, collector);
212
const names = getRequiredFixtureNames(fn);
213
for (const name of names)
214
this._collectFixturesInSetupOrder(this.pool.resolve(name), collector);
215
for (const registration of collector)
216
await this._setupFixtureForRegistration(registration, testInfo, runnable);
217
const params = {};
218
for (const name of names) {
219
const registration = this.pool.resolve(name);
220
const fixture = this.instanceForId.get(registration.id);
221
if (!fixture || fixture.failed)
222
return null;
223
params[name] = fixture.value;
224
}
225
return params;
226
}
227
async resolveParametersAndRunFunction(fn, testInfo, autoFixtures, runnable) {
228
const params = await this.resolveParametersForFunction(fn, testInfo, autoFixtures, runnable);
229
if (params === null) {
230
return null;
231
}
232
await testInfo._runWithTimeout(runnable, () => fn(params, testInfo));
233
}
234
async _setupFixtureForRegistration(registration, testInfo, runnable) {
235
if (registration.scope === "test")
236
this.testScopeClean = false;
237
let fixture = this.instanceForId.get(registration.id);
238
if (fixture)
239
return fixture;
240
fixture = new Fixture(this, registration);
241
await fixture.setup(testInfo, runnable);
242
return fixture;
243
}
244
dependsOnWorkerFixturesOnly(fn, location) {
245
const names = getRequiredFixtureNames(fn, location);
246
for (const name of names) {
247
const registration = this.pool.resolve(name);
248
if (registration.scope !== "worker")
249
return false;
250
}
251
return true;
252
}
253
}
254
function getRequiredFixtureNames(fn, location) {
255
return (0, import_fixtures.fixtureParameterNames)(fn, location ?? { file: "<unknown>", line: 1, column: 1 }, (e) => {
256
throw new Error(`${(0, import_util.formatLocation)(e.location)}: ${e.message}`);
257
});
258
}
259
// Annotate the CommonJS export names for ESM import in node:
260
0 && (module.exports = {
261
FixtureRunner
262
});
263

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button