ScuttleBot

scuttlebot / tests / e2e / node_modules / playwright / lib / runner / testRunner.js
Blame History Raw 399 lines
1
"use strict";
2
var __create = Object.create;
3
var __defProp = Object.defineProperty;
4
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
var __getOwnPropNames = Object.getOwnPropertyNames;
6
var __getProtoOf = Object.getPrototypeOf;
7
var __hasOwnProp = Object.prototype.hasOwnProperty;
8
var __export = (target, all) => {
9
for (var name in all)
10
__defProp(target, name, { get: all[name], enumerable: true });
11
};
12
var __copyProps = (to, from, except, desc) => {
13
if (from && typeof from === "object" || typeof from === "function") {
14
for (let key of __getOwnPropNames(from))
15
if (!__hasOwnProp.call(to, key) && key !== except)
16
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
}
18
return to;
19
};
20
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
// If the importer is in node compatibility mode or this is not an ESM
22
// file that has been converted to a CommonJS file using a Babel-
23
// compatible transform (i.e. "__esModule" has not been set), then set
24
// "default" to the CommonJS "module.exports" for node compatibility.
25
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
mod
27
));
28
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
var testRunner_exports = {};
30
__export(testRunner_exports, {
31
TestRunner: () => TestRunner,
32
TestRunnerEvent: () => TestRunnerEvent,
33
runAllTestsWithConfig: () => runAllTestsWithConfig
34
});
35
module.exports = __toCommonJS(testRunner_exports);
36
var import_events = __toESM(require("events"));
37
var import_fs = __toESM(require("fs"));
38
var import_path = __toESM(require("path"));
39
var import_server = require("playwright-core/lib/server");
40
var import_utils = require("playwright-core/lib/utils");
41
var import_configLoader = require("../common/configLoader");
42
var import_fsWatcher = require("../fsWatcher");
43
var import_teleReceiver = require("../isomorphic/teleReceiver");
44
var import_gitCommitInfoPlugin = require("../plugins/gitCommitInfoPlugin");
45
var import_webServerPlugin = require("../plugins/webServerPlugin");
46
var import_base = require("../reporters/base");
47
var import_internalReporter = require("../reporters/internalReporter");
48
var import_compilationCache = require("../transform/compilationCache");
49
var import_util = require("../util");
50
var import_reporters = require("./reporters");
51
var import_tasks = require("./tasks");
52
var import_lastRun = require("./lastRun");
53
const TestRunnerEvent = {
54
TestFilesChanged: "testFilesChanged",
55
TestPaused: "testPaused"
56
};
57
class TestRunner extends import_events.default {
58
constructor(configLocation, configCLIOverrides) {
59
super();
60
this._watchedProjectDirs = /* @__PURE__ */ new Set();
61
this._ignoredProjectOutputs = /* @__PURE__ */ new Set();
62
this._watchedTestDependencies = /* @__PURE__ */ new Set();
63
this._queue = Promise.resolve();
64
this._watchTestDirs = false;
65
this._populateDependenciesOnList = false;
66
this._startingEnv = {};
67
this.configLocation = configLocation;
68
this._configCLIOverrides = configCLIOverrides;
69
this._watcher = new import_fsWatcher.Watcher((events) => {
70
const collector = /* @__PURE__ */ new Set();
71
events.forEach((f) => (0, import_compilationCache.collectAffectedTestFiles)(f.file, collector));
72
this.emit(TestRunnerEvent.TestFilesChanged, [...collector]);
73
});
74
}
75
async initialize(params) {
76
(0, import_utils.setPlaywrightTestProcessEnv)();
77
this._watchTestDirs = !!params.watchTestDirs;
78
this._populateDependenciesOnList = !!params.populateDependenciesOnList;
79
this._startingEnv = { ...process.env };
80
}
81
resizeTerminal(params) {
82
process.stdout.columns = params.cols;
83
process.stdout.rows = params.rows;
84
process.stderr.columns = params.cols;
85
process.stderr.rows = params.rows;
86
}
87
hasSomeBrowsers() {
88
for (const browserName of ["chromium", "webkit", "firefox"]) {
89
try {
90
import_server.registry.findExecutable(browserName).executablePathOrDie("javascript");
91
return true;
92
} catch {
93
}
94
}
95
return false;
96
}
97
async installBrowsers() {
98
const executables = import_server.registry.defaultExecutables();
99
await import_server.registry.install(executables);
100
}
101
async loadConfig() {
102
const { config, error } = await this._loadConfig(this._configCLIOverrides);
103
if (config)
104
return config;
105
throw new Error("Failed to load config: " + (error ? error.message : "Unknown error"));
106
}
107
async runGlobalSetup(userReporters) {
108
await this.runGlobalTeardown();
109
const reporter = new import_internalReporter.InternalReporter(userReporters);
110
const config = await this._loadConfigOrReportError(reporter, this._configCLIOverrides);
111
if (!config)
112
return { status: "failed", env: [] };
113
const { status, cleanup } = await (0, import_tasks.runTasksDeferCleanup)(new import_tasks.TestRun(config, reporter), [
114
...(0, import_tasks.createGlobalSetupTasks)(config)
115
]);
116
const env = [];
117
for (const key of /* @__PURE__ */ new Set([...Object.keys(process.env), ...Object.keys(this._startingEnv)])) {
118
if (this._startingEnv[key] !== process.env[key])
119
env.push([key, process.env[key] ?? null]);
120
}
121
if (status !== "passed")
122
await cleanup();
123
else
124
this._globalSetup = { cleanup };
125
return { status, env };
126
}
127
async runGlobalTeardown() {
128
const globalSetup = this._globalSetup;
129
const status = await globalSetup?.cleanup();
130
this._globalSetup = void 0;
131
return { status };
132
}
133
async startDevServer(userReporter, mode) {
134
await this.stopDevServer();
135
const reporter = new import_internalReporter.InternalReporter([userReporter]);
136
const config = await this._loadConfigOrReportError(reporter);
137
if (!config)
138
return { status: "failed" };
139
const { status, cleanup } = await (0, import_tasks.runTasksDeferCleanup)(new import_tasks.TestRun(config, reporter), [
140
...(0, import_tasks.createPluginSetupTasks)(config),
141
(0, import_tasks.createLoadTask)(mode, { failOnLoadErrors: true, filterOnly: false }),
142
(0, import_tasks.createStartDevServerTask)()
143
]);
144
if (status !== "passed")
145
await cleanup();
146
else
147
this._devServer = { cleanup };
148
return { status };
149
}
150
async stopDevServer() {
151
const devServer = this._devServer;
152
const status = await devServer?.cleanup();
153
this._devServer = void 0;
154
return { status };
155
}
156
async clearCache(userReporter) {
157
const reporter = new import_internalReporter.InternalReporter(userReporter ? [userReporter] : []);
158
const config = await this._loadConfigOrReportError(reporter);
159
if (!config)
160
return { status: "failed" };
161
const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
162
...(0, import_tasks.createPluginSetupTasks)(config),
163
(0, import_tasks.createClearCacheTask)(config)
164
]);
165
return { status };
166
}
167
async listFiles(userReporter, projects) {
168
const reporter = new import_internalReporter.InternalReporter([userReporter]);
169
const config = await this._loadConfigOrReportError(reporter);
170
if (!config)
171
return { status: "failed" };
172
config.cliProjectFilter = projects?.length ? projects : void 0;
173
const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
174
(0, import_tasks.createListFilesTask)(),
175
(0, import_tasks.createReportBeginTask)()
176
]);
177
return { status };
178
}
179
async listTests(userReporter, params) {
180
let result;
181
this._queue = this._queue.then(async () => {
182
const { config, status } = await this._innerListTests(userReporter, params);
183
if (config)
184
await this._updateWatchedDirs(config);
185
result = { status };
186
}).catch(printInternalError);
187
await this._queue;
188
return result;
189
}
190
async _innerListTests(userReporter, params) {
191
const overrides = {
192
...this._configCLIOverrides,
193
repeatEach: 1,
194
retries: 0
195
};
196
const reporter = new import_internalReporter.InternalReporter([userReporter]);
197
const config = await this._loadConfigOrReportError(reporter, overrides);
198
if (!config)
199
return { status: "failed" };
200
config.cliArgs = params.locations || [];
201
config.cliGrep = params.grep;
202
config.cliGrepInvert = params.grepInvert;
203
config.cliProjectFilter = params.projects?.length ? params.projects : void 0;
204
config.cliListOnly = true;
205
const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
206
(0, import_tasks.createLoadTask)("out-of-process", { failOnLoadErrors: false, filterOnly: false, populateDependencies: this._populateDependenciesOnList }),
207
(0, import_tasks.createReportBeginTask)()
208
]);
209
return { config, status };
210
}
211
async _updateWatchedDirs(config) {
212
this._watchedProjectDirs = /* @__PURE__ */ new Set();
213
this._ignoredProjectOutputs = /* @__PURE__ */ new Set();
214
for (const p of config.projects) {
215
this._watchedProjectDirs.add(p.project.testDir);
216
this._ignoredProjectOutputs.add(p.project.outputDir);
217
}
218
const result = await resolveCtDirs(config);
219
if (result) {
220
this._watchedProjectDirs.add(result.templateDir);
221
this._ignoredProjectOutputs.add(result.outDir);
222
}
223
if (this._watchTestDirs)
224
await this._updateWatcher(false);
225
}
226
async _updateWatcher(reportPending) {
227
await this._watcher.update([...this._watchedProjectDirs, ...this._watchedTestDependencies], [...this._ignoredProjectOutputs], reportPending);
228
}
229
async runTests(userReporter, params) {
230
let result = { status: "passed" };
231
this._queue = this._queue.then(async () => {
232
result = await this._innerRunTests(userReporter, params).catch((e) => {
233
printInternalError(e);
234
return { status: "failed" };
235
});
236
});
237
await this._queue;
238
return result;
239
}
240
async _innerRunTests(userReporter, params) {
241
await this.stopTests();
242
const overrides = {
243
...this._configCLIOverrides,
244
repeatEach: 1,
245
retries: 0,
246
timeout: params.timeout,
247
preserveOutputDir: true,
248
reporter: params.reporters ? params.reporters.map((r) => [r]) : void 0,
249
use: {
250
...this._configCLIOverrides.use,
251
...params.trace === "on" ? { trace: { mode: "on", sources: false, _live: true } } : {},
252
...params.trace === "off" ? { trace: "off" } : {},
253
...params.video === "on" || params.video === "off" ? { video: params.video } : {},
254
...params.headed !== void 0 ? { headless: !params.headed } : {},
255
_optionContextReuseMode: params.reuseContext ? "when-possible" : void 0,
256
_optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : void 0,
257
actionTimeout: params.actionTimeout
258
},
259
...params.updateSnapshots ? { updateSnapshots: params.updateSnapshots } : {},
260
...params.updateSourceMethod ? { updateSourceMethod: params.updateSourceMethod } : {},
261
...params.runAgents ? { runAgents: params.runAgents } : {},
262
...params.workers ? { workers: params.workers } : {}
263
};
264
const config = await this._loadConfigOrReportError(new import_internalReporter.InternalReporter([userReporter]), overrides);
265
if (!config)
266
return { status: "failed" };
267
config.cliListOnly = false;
268
config.cliPassWithNoTests = true;
269
config.cliArgs = params.locations;
270
config.cliGrep = params.grep;
271
config.cliGrepInvert = params.grepInvert;
272
config.cliProjectFilter = params.projects?.length ? params.projects : void 0;
273
config.preOnlyTestFilters = [];
274
if (params.testIds) {
275
const testIdSet = new Set(params.testIds);
276
config.preOnlyTestFilters.push((test) => testIdSet.has(test.id));
277
}
278
const configReporters = params.disableConfigReporters ? [] : await (0, import_reporters.createReporters)(config, "test");
279
const reporter = new import_internalReporter.InternalReporter([...configReporters, userReporter]);
280
const stop = new import_utils.ManualPromise();
281
const tasks = [
282
(0, import_tasks.createApplyRebaselinesTask)(),
283
(0, import_tasks.createLoadTask)("out-of-process", { filterOnly: true, failOnLoadErrors: !!params.failOnLoadErrors, doNotRunDepsOutsideProjectFilter: params.doNotRunDepsOutsideProjectFilter }),
284
...(0, import_tasks.createRunTestsTasks)(config)
285
];
286
const testRun = new import_tasks.TestRun(config, reporter, { pauseOnError: params.pauseOnError, pauseAtEnd: params.pauseAtEnd });
287
testRun.failureTracker.onTestPaused = (params2) => this.emit(TestRunnerEvent.TestPaused, params2);
288
const run = (0, import_tasks.runTasks)(testRun, tasks, 0, stop).then(async (status) => {
289
this._testRun = void 0;
290
return status;
291
});
292
this._testRun = { run, stop };
293
return { status: await run };
294
}
295
async watch(fileNames) {
296
this._watchedTestDependencies = /* @__PURE__ */ new Set();
297
for (const fileName of fileNames) {
298
this._watchedTestDependencies.add(fileName);
299
(0, import_compilationCache.dependenciesForTestFile)(fileName).forEach((file) => this._watchedTestDependencies.add(file));
300
}
301
await this._updateWatcher(true);
302
}
303
async findRelatedTestFiles(files, userReporter) {
304
const errorReporter = (0, import_reporters.createErrorCollectingReporter)(import_base.internalScreen);
305
const reporter = new import_internalReporter.InternalReporter(userReporter ? [userReporter, errorReporter] : [errorReporter]);
306
const config = await this._loadConfigOrReportError(reporter);
307
if (!config)
308
return { errors: errorReporter.errors(), testFiles: [] };
309
const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
310
...(0, import_tasks.createPluginSetupTasks)(config),
311
(0, import_tasks.createLoadTask)("out-of-process", { failOnLoadErrors: true, filterOnly: false, populateDependencies: true })
312
]);
313
if (status !== "passed")
314
return { errors: errorReporter.errors(), testFiles: [] };
315
return { testFiles: (0, import_compilationCache.affectedTestFiles)(files) };
316
}
317
async stopTests() {
318
this._testRun?.stop?.resolve();
319
await this._testRun?.run;
320
}
321
async closeGracefully() {
322
(0, import_utils.gracefullyProcessExitDoNotHang)(0);
323
}
324
async stop() {
325
await this.runGlobalTeardown();
326
}
327
async _loadConfig(overrides) {
328
try {
329
const config = await (0, import_configLoader.loadConfig)(this.configLocation, overrides);
330
if (!this._plugins) {
331
(0, import_webServerPlugin.webServerPluginsForConfig)(config).forEach((p) => config.plugins.push({ factory: p }));
332
(0, import_gitCommitInfoPlugin.addGitCommitInfoPlugin)(config);
333
this._plugins = config.plugins || [];
334
} else {
335
config.plugins.splice(0, config.plugins.length, ...this._plugins);
336
}
337
return { config };
338
} catch (e) {
339
return { config: null, error: (0, import_util.serializeError)(e) };
340
}
341
}
342
async _loadConfigOrReportError(reporter, overrides) {
343
const { config, error } = await this._loadConfig(overrides);
344
if (config)
345
return config;
346
reporter.onConfigure(import_teleReceiver.baseFullConfig);
347
reporter.onError(error);
348
await reporter.onEnd({ status: "failed" });
349
await reporter.onExit();
350
return null;
351
}
352
}
353
function printInternalError(e) {
354
console.error("Internal error:", e);
355
}
356
async function resolveCtDirs(config) {
357
const use = config.config.projects[0].use;
358
const relativeTemplateDir = use.ctTemplateDir || "playwright";
359
const templateDir = await import_fs.default.promises.realpath(import_path.default.normalize(import_path.default.join(config.configDir, relativeTemplateDir))).catch(() => void 0);
360
if (!templateDir)
361
return null;
362
const outDir = use.ctCacheDir ? import_path.default.resolve(config.configDir, use.ctCacheDir) : import_path.default.resolve(templateDir, ".cache");
363
return {
364
outDir,
365
templateDir
366
};
367
}
368
async function runAllTestsWithConfig(config) {
369
(0, import_utils.setPlaywrightTestProcessEnv)();
370
const listOnly = config.cliListOnly;
371
(0, import_gitCommitInfoPlugin.addGitCommitInfoPlugin)(config);
372
(0, import_webServerPlugin.webServerPluginsForConfig)(config).forEach((p) => config.plugins.push({ factory: p }));
373
const reporters = await (0, import_reporters.createReporters)(config, listOnly ? "list" : "test");
374
const lastRun = new import_lastRun.LastRunReporter(config);
375
if (config.cliLastFailed)
376
await lastRun.filterLastFailed();
377
const reporter = new import_internalReporter.InternalReporter([...reporters, lastRun]);
378
const tasks = listOnly ? [
379
(0, import_tasks.createLoadTask)("in-process", { failOnLoadErrors: true, filterOnly: false }),
380
(0, import_tasks.createReportBeginTask)()
381
] : [
382
(0, import_tasks.createApplyRebaselinesTask)(),
383
...(0, import_tasks.createGlobalSetupTasks)(config),
384
(0, import_tasks.createLoadTask)("in-process", { filterOnly: true, failOnLoadErrors: true }),
385
...(0, import_tasks.createRunTestsTasks)(config)
386
];
387
const testRun = new import_tasks.TestRun(config, reporter, { pauseAtEnd: config.configCLIOverrides.pause, pauseOnError: config.configCLIOverrides.pause });
388
const status = await (0, import_tasks.runTasks)(testRun, tasks, config.config.globalTimeout);
389
await new Promise((resolve) => process.stdout.write("", () => resolve()));
390
await new Promise((resolve) => process.stderr.write("", () => resolve()));
391
return status;
392
}
393
// Annotate the CommonJS export names for ESM import in node:
394
0 && (module.exports = {
395
TestRunner,
396
TestRunnerEvent,
397
runAllTestsWithConfig
398
});
399

Keyboard Shortcuts

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