ScuttleBot

scuttlebot / tests / e2e / node_modules / playwright / lib / common / configLoader.js
Blame History Raw 345 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 configLoader_exports = {};
30
__export(configLoader_exports, {
31
defineConfig: () => defineConfig,
32
deserializeConfig: () => deserializeConfig,
33
loadConfig: () => loadConfig,
34
loadConfigFromFile: () => loadConfigFromFile,
35
loadEmptyConfigForMergeReports: () => loadEmptyConfigForMergeReports,
36
resolveConfigLocation: () => resolveConfigLocation
37
});
38
module.exports = __toCommonJS(configLoader_exports);
39
var import_fs = __toESM(require("fs"));
40
var import_path = __toESM(require("path"));
41
var import_utils = require("playwright-core/lib/utils");
42
var import_transform = require("../transform/transform");
43
var import_util = require("../util");
44
var import_config = require("./config");
45
var import_esmLoaderHost = require("./esmLoaderHost");
46
var import_compilationCache = require("../transform/compilationCache");
47
const kDefineConfigWasUsed = Symbol("defineConfigWasUsed");
48
const defineConfig = (...configs) => {
49
let result = configs[0];
50
for (let i = 1; i < configs.length; ++i) {
51
const config = configs[i];
52
const prevProjects = result.projects;
53
result = {
54
...result,
55
...config,
56
expect: {
57
...result.expect,
58
...config.expect
59
},
60
use: {
61
...result.use,
62
...config.use
63
},
64
build: {
65
...result.build,
66
...config.build
67
},
68
webServer: [
69
...Array.isArray(result.webServer) ? result.webServer : result.webServer ? [result.webServer] : [],
70
...Array.isArray(config.webServer) ? config.webServer : config.webServer ? [config.webServer] : []
71
]
72
};
73
if (!result.projects && !config.projects)
74
continue;
75
const projectOverrides = /* @__PURE__ */ new Map();
76
for (const project of config.projects || [])
77
projectOverrides.set(project.name, project);
78
const projects = [];
79
for (const project of prevProjects || []) {
80
const projectOverride = projectOverrides.get(project.name);
81
if (projectOverride) {
82
projects.push({
83
...project,
84
...projectOverride,
85
use: {
86
...project.use,
87
...projectOverride.use
88
}
89
});
90
projectOverrides.delete(project.name);
91
} else {
92
projects.push(project);
93
}
94
}
95
projects.push(...projectOverrides.values());
96
result.projects = projects;
97
}
98
result[kDefineConfigWasUsed] = true;
99
return result;
100
};
101
async function deserializeConfig(data) {
102
if (data.compilationCache)
103
(0, import_compilationCache.addToCompilationCache)(data.compilationCache);
104
return await loadConfig(data.location, data.configCLIOverrides, void 0, data.metadata ? JSON.parse(data.metadata) : void 0);
105
}
106
async function loadUserConfig(location) {
107
let object = location.resolvedConfigFile ? await (0, import_transform.requireOrImport)(location.resolvedConfigFile) : {};
108
if (object && typeof object === "object" && "default" in object)
109
object = object["default"];
110
return object;
111
}
112
async function loadConfig(location, overrides, ignoreProjectDependencies = false, metadata) {
113
if (!(0, import_esmLoaderHost.registerESMLoader)()) {
114
if (location.resolvedConfigFile && (0, import_util.fileIsModule)(location.resolvedConfigFile))
115
throw (0, import_util.errorWithFile)(location.resolvedConfigFile, `Playwright requires Node.js 18.19 or higher to load esm modules. Please update your version of Node.js.`);
116
}
117
(0, import_transform.setSingleTSConfig)(overrides?.tsconfig);
118
await (0, import_esmLoaderHost.configureESMLoader)();
119
const userConfig = await loadUserConfig(location);
120
validateConfig(location.resolvedConfigFile || "<default config>", userConfig);
121
const fullConfig = new import_config.FullConfigInternal(location, userConfig, overrides || {}, metadata);
122
fullConfig.defineConfigWasUsed = !!userConfig[kDefineConfigWasUsed];
123
if (ignoreProjectDependencies) {
124
for (const project of fullConfig.projects) {
125
project.deps = [];
126
project.teardown = void 0;
127
}
128
}
129
const babelPlugins = userConfig["@playwright/test"]?.babelPlugins || [];
130
const external = userConfig.build?.external || [];
131
(0, import_transform.setTransformConfig)({ babelPlugins, external });
132
if (!overrides?.tsconfig)
133
(0, import_transform.setSingleTSConfig)(fullConfig?.singleTSConfigPath);
134
await (0, import_esmLoaderHost.configureESMLoaderTransformConfig)();
135
return fullConfig;
136
}
137
function validateConfig(file, config) {
138
if (typeof config !== "object" || !config)
139
throw (0, import_util.errorWithFile)(file, `Configuration file must export a single object`);
140
validateProject(file, config, "config");
141
if ("forbidOnly" in config && config.forbidOnly !== void 0) {
142
if (typeof config.forbidOnly !== "boolean")
143
throw (0, import_util.errorWithFile)(file, `config.forbidOnly must be a boolean`);
144
}
145
if ("globalSetup" in config && config.globalSetup !== void 0) {
146
if (Array.isArray(config.globalSetup)) {
147
config.globalSetup.forEach((item, index) => {
148
if (typeof item !== "string")
149
throw (0, import_util.errorWithFile)(file, `config.globalSetup[${index}] must be a string`);
150
});
151
} else if (typeof config.globalSetup !== "string") {
152
throw (0, import_util.errorWithFile)(file, `config.globalSetup must be a string`);
153
}
154
}
155
if ("globalTeardown" in config && config.globalTeardown !== void 0) {
156
if (Array.isArray(config.globalTeardown)) {
157
config.globalTeardown.forEach((item, index) => {
158
if (typeof item !== "string")
159
throw (0, import_util.errorWithFile)(file, `config.globalTeardown[${index}] must be a string`);
160
});
161
} else if (typeof config.globalTeardown !== "string") {
162
throw (0, import_util.errorWithFile)(file, `config.globalTeardown must be a string`);
163
}
164
}
165
if ("globalTimeout" in config && config.globalTimeout !== void 0) {
166
if (typeof config.globalTimeout !== "number" || config.globalTimeout < 0)
167
throw (0, import_util.errorWithFile)(file, `config.globalTimeout must be a non-negative number`);
168
}
169
if ("grep" in config && config.grep !== void 0) {
170
if (Array.isArray(config.grep)) {
171
config.grep.forEach((item, index) => {
172
if (!(0, import_utils.isRegExp)(item))
173
throw (0, import_util.errorWithFile)(file, `config.grep[${index}] must be a RegExp`);
174
});
175
} else if (!(0, import_utils.isRegExp)(config.grep)) {
176
throw (0, import_util.errorWithFile)(file, `config.grep must be a RegExp`);
177
}
178
}
179
if ("grepInvert" in config && config.grepInvert !== void 0) {
180
if (Array.isArray(config.grepInvert)) {
181
config.grepInvert.forEach((item, index) => {
182
if (!(0, import_utils.isRegExp)(item))
183
throw (0, import_util.errorWithFile)(file, `config.grepInvert[${index}] must be a RegExp`);
184
});
185
} else if (!(0, import_utils.isRegExp)(config.grepInvert)) {
186
throw (0, import_util.errorWithFile)(file, `config.grepInvert must be a RegExp`);
187
}
188
}
189
if ("maxFailures" in config && config.maxFailures !== void 0) {
190
if (typeof config.maxFailures !== "number" || config.maxFailures < 0)
191
throw (0, import_util.errorWithFile)(file, `config.maxFailures must be a non-negative number`);
192
}
193
if ("preserveOutput" in config && config.preserveOutput !== void 0) {
194
if (typeof config.preserveOutput !== "string" || !["always", "never", "failures-only"].includes(config.preserveOutput))
195
throw (0, import_util.errorWithFile)(file, `config.preserveOutput must be one of "always", "never" or "failures-only"`);
196
}
197
if ("projects" in config && config.projects !== void 0) {
198
if (!Array.isArray(config.projects))
199
throw (0, import_util.errorWithFile)(file, `config.projects must be an array`);
200
config.projects.forEach((project, index) => {
201
validateProject(file, project, `config.projects[${index}]`);
202
});
203
}
204
if ("quiet" in config && config.quiet !== void 0) {
205
if (typeof config.quiet !== "boolean")
206
throw (0, import_util.errorWithFile)(file, `config.quiet must be a boolean`);
207
}
208
if ("reporter" in config && config.reporter !== void 0) {
209
if (Array.isArray(config.reporter)) {
210
config.reporter.forEach((item, index) => {
211
if (!Array.isArray(item) || item.length <= 0 || item.length > 2 || typeof item[0] !== "string")
212
throw (0, import_util.errorWithFile)(file, `config.reporter[${index}] must be a tuple [name, optionalArgument]`);
213
});
214
} else if (typeof config.reporter !== "string") {
215
throw (0, import_util.errorWithFile)(file, `config.reporter must be a string`);
216
}
217
}
218
if ("reportSlowTests" in config && config.reportSlowTests !== void 0 && config.reportSlowTests !== null) {
219
if (!config.reportSlowTests || typeof config.reportSlowTests !== "object")
220
throw (0, import_util.errorWithFile)(file, `config.reportSlowTests must be an object`);
221
if (!("max" in config.reportSlowTests) || typeof config.reportSlowTests.max !== "number" || config.reportSlowTests.max < 0)
222
throw (0, import_util.errorWithFile)(file, `config.reportSlowTests.max must be a non-negative number`);
223
if (!("threshold" in config.reportSlowTests) || typeof config.reportSlowTests.threshold !== "number" || config.reportSlowTests.threshold < 0)
224
throw (0, import_util.errorWithFile)(file, `config.reportSlowTests.threshold must be a non-negative number`);
225
}
226
if ("shard" in config && config.shard !== void 0 && config.shard !== null) {
227
if (!config.shard || typeof config.shard !== "object")
228
throw (0, import_util.errorWithFile)(file, `config.shard must be an object`);
229
if (!("total" in config.shard) || typeof config.shard.total !== "number" || config.shard.total < 1)
230
throw (0, import_util.errorWithFile)(file, `config.shard.total must be a positive number`);
231
if (!("current" in config.shard) || typeof config.shard.current !== "number" || config.shard.current < 1 || config.shard.current > config.shard.total)
232
throw (0, import_util.errorWithFile)(file, `config.shard.current must be a positive number, not greater than config.shard.total`);
233
}
234
if ("updateSnapshots" in config && config.updateSnapshots !== void 0) {
235
if (typeof config.updateSnapshots !== "string" || !["all", "changed", "missing", "none"].includes(config.updateSnapshots))
236
throw (0, import_util.errorWithFile)(file, `config.updateSnapshots must be one of "all", "changed", "missing" or "none"`);
237
}
238
if ("tsconfig" in config && config.tsconfig !== void 0) {
239
if (typeof config.tsconfig !== "string")
240
throw (0, import_util.errorWithFile)(file, `config.tsconfig must be a string`);
241
if (!import_fs.default.existsSync(import_path.default.resolve(file, "..", config.tsconfig)))
242
throw (0, import_util.errorWithFile)(file, `config.tsconfig does not exist`);
243
}
244
}
245
function validateProject(file, project, title) {
246
if (typeof project !== "object" || !project)
247
throw (0, import_util.errorWithFile)(file, `${title} must be an object`);
248
if ("name" in project && project.name !== void 0) {
249
if (typeof project.name !== "string")
250
throw (0, import_util.errorWithFile)(file, `${title}.name must be a string`);
251
}
252
if ("outputDir" in project && project.outputDir !== void 0) {
253
if (typeof project.outputDir !== "string")
254
throw (0, import_util.errorWithFile)(file, `${title}.outputDir must be a string`);
255
}
256
if ("repeatEach" in project && project.repeatEach !== void 0) {
257
if (typeof project.repeatEach !== "number" || project.repeatEach < 0)
258
throw (0, import_util.errorWithFile)(file, `${title}.repeatEach must be a non-negative number`);
259
}
260
if ("retries" in project && project.retries !== void 0) {
261
if (typeof project.retries !== "number" || project.retries < 0)
262
throw (0, import_util.errorWithFile)(file, `${title}.retries must be a non-negative number`);
263
}
264
if ("testDir" in project && project.testDir !== void 0) {
265
if (typeof project.testDir !== "string")
266
throw (0, import_util.errorWithFile)(file, `${title}.testDir must be a string`);
267
}
268
for (const prop of ["testIgnore", "testMatch"]) {
269
if (prop in project && project[prop] !== void 0) {
270
const value = project[prop];
271
if (Array.isArray(value)) {
272
value.forEach((item, index) => {
273
if (typeof item !== "string" && !(0, import_utils.isRegExp)(item))
274
throw (0, import_util.errorWithFile)(file, `${title}.${prop}[${index}] must be a string or a RegExp`);
275
});
276
} else if (typeof value !== "string" && !(0, import_utils.isRegExp)(value)) {
277
throw (0, import_util.errorWithFile)(file, `${title}.${prop} must be a string or a RegExp`);
278
}
279
}
280
}
281
if ("timeout" in project && project.timeout !== void 0) {
282
if (typeof project.timeout !== "number" || project.timeout < 0)
283
throw (0, import_util.errorWithFile)(file, `${title}.timeout must be a non-negative number`);
284
}
285
if ("use" in project && project.use !== void 0) {
286
if (!project.use || typeof project.use !== "object")
287
throw (0, import_util.errorWithFile)(file, `${title}.use must be an object`);
288
}
289
if ("ignoreSnapshots" in project && project.ignoreSnapshots !== void 0) {
290
if (typeof project.ignoreSnapshots !== "boolean")
291
throw (0, import_util.errorWithFile)(file, `${title}.ignoreSnapshots must be a boolean`);
292
}
293
if ("workers" in project && project.workers !== void 0) {
294
if (typeof project.workers === "number" && project.workers <= 0)
295
throw (0, import_util.errorWithFile)(file, `${title}.workers must be a positive number`);
296
else if (typeof project.workers === "string" && !project.workers.endsWith("%"))
297
throw (0, import_util.errorWithFile)(file, `${title}.workers must be a number or percentage`);
298
}
299
}
300
function resolveConfigLocation(configFile) {
301
const configFileOrDirectory = configFile ? import_path.default.resolve(process.cwd(), configFile) : process.cwd();
302
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
303
return {
304
resolvedConfigFile,
305
configDir: resolvedConfigFile ? import_path.default.dirname(resolvedConfigFile) : configFileOrDirectory
306
};
307
}
308
function resolveConfigFile(configFileOrDirectory) {
309
const resolveConfig = (configFile) => {
310
if (import_fs.default.existsSync(configFile))
311
return configFile;
312
};
313
const resolveConfigFileFromDirectory = (directory) => {
314
for (const ext of [".ts", ".js", ".mts", ".mjs", ".cts", ".cjs"]) {
315
const configFile = resolveConfig(import_path.default.resolve(directory, "playwright.config" + ext));
316
if (configFile)
317
return configFile;
318
}
319
};
320
if (!import_fs.default.existsSync(configFileOrDirectory))
321
throw new Error(`${configFileOrDirectory} does not exist`);
322
if (import_fs.default.statSync(configFileOrDirectory).isDirectory()) {
323
const configFile = resolveConfigFileFromDirectory(configFileOrDirectory);
324
if (configFile)
325
return configFile;
326
return void 0;
327
}
328
return configFileOrDirectory;
329
}
330
async function loadConfigFromFile(configFile, overrides, ignoreDeps) {
331
return await loadConfig(resolveConfigLocation(configFile), overrides, ignoreDeps);
332
}
333
async function loadEmptyConfigForMergeReports() {
334
return await loadConfig({ configDir: process.cwd() });
335
}
336
// Annotate the CommonJS export names for ESM import in node:
337
0 && (module.exports = {
338
defineConfig,
339
deserializeConfig,
340
loadConfig,
341
loadConfigFromFile,
342
loadEmptyConfigForMergeReports,
343
resolveConfigLocation
344
});
345

Keyboard Shortcuts

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