ScuttleBot

Source Blame History 282 lines
f7eb47b… lmata 1 "use strict";
f7eb47b… lmata 2 var __create = Object.create;
f7eb47b… lmata 3 var __defProp = Object.defineProperty;
f7eb47b… lmata 4 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
f7eb47b… lmata 5 var __getOwnPropNames = Object.getOwnPropertyNames;
f7eb47b… lmata 6 var __getProtoOf = Object.getPrototypeOf;
f7eb47b… lmata 7 var __hasOwnProp = Object.prototype.hasOwnProperty;
f7eb47b… lmata 8 var __export = (target, all) => {
f7eb47b… lmata 9 for (var name in all)
f7eb47b… lmata 10 __defProp(target, name, { get: all[name], enumerable: true });
f7eb47b… lmata 11 };
f7eb47b… lmata 12 var __copyProps = (to, from, except, desc) => {
f7eb47b… lmata 13 if (from && typeof from === "object" || typeof from === "function") {
f7eb47b… lmata 14 for (let key of __getOwnPropNames(from))
f7eb47b… lmata 15 if (!__hasOwnProp.call(to, key) && key !== except)
f7eb47b… lmata 16 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
f7eb47b… lmata 17 }
f7eb47b… lmata 18 return to;
f7eb47b… lmata 19 };
f7eb47b… lmata 20 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
f7eb47b… lmata 21 // If the importer is in node compatibility mode or this is not an ESM
f7eb47b… lmata 22 // file that has been converted to a CommonJS file using a Babel-
f7eb47b… lmata 23 // compatible transform (i.e. "__esModule" has not been set), then set
f7eb47b… lmata 24 // "default" to the CommonJS "module.exports" for node compatibility.
f7eb47b… lmata 25 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
f7eb47b… lmata 26 mod
f7eb47b… lmata 27 ));
f7eb47b… lmata 28 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
f7eb47b… lmata 29 var config_exports = {};
f7eb47b… lmata 30 __export(config_exports, {
f7eb47b… lmata 31 FullConfigInternal: () => FullConfigInternal,
f7eb47b… lmata 32 FullProjectInternal: () => FullProjectInternal,
f7eb47b… lmata 33 builtInReporters: () => builtInReporters,
f7eb47b… lmata 34 defaultGrep: () => defaultGrep,
f7eb47b… lmata 35 defaultReporter: () => defaultReporter,
f7eb47b… lmata 36 defaultTimeout: () => defaultTimeout,
f7eb47b… lmata 37 getProjectId: () => getProjectId,
f7eb47b… lmata 38 takeFirst: () => takeFirst,
f7eb47b… lmata 39 toReporters: () => toReporters
f7eb47b… lmata 40 });
f7eb47b… lmata 41 module.exports = __toCommonJS(config_exports);
f7eb47b… lmata 42 var import_fs = __toESM(require("fs"));
f7eb47b… lmata 43 var import_os = __toESM(require("os"));
f7eb47b… lmata 44 var import_path = __toESM(require("path"));
f7eb47b… lmata 45 var import_util = require("../util");
f7eb47b… lmata 46 const defaultTimeout = 3e4;
f7eb47b… lmata 47 class FullConfigInternal {
f7eb47b… lmata 48 constructor(location, userConfig, configCLIOverrides, metadata) {
f7eb47b… lmata 49 this.projects = [];
f7eb47b… lmata 50 this.cliArgs = [];
f7eb47b… lmata 51 this.cliListOnly = false;
f7eb47b… lmata 52 this.preOnlyTestFilters = [];
f7eb47b… lmata 53 this.postShardTestFilters = [];
f7eb47b… lmata 54 this.defineConfigWasUsed = false;
f7eb47b… lmata 55 this.globalSetups = [];
f7eb47b… lmata 56 this.globalTeardowns = [];
f7eb47b… lmata 57 if (configCLIOverrides.projects && userConfig.projects)
f7eb47b… lmata 58 throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`);
f7eb47b… lmata 59 const { resolvedConfigFile, configDir } = location;
f7eb47b… lmata 60 const packageJsonPath = (0, import_util.getPackageJsonPath)(configDir);
f7eb47b… lmata 61 const packageJsonDir = packageJsonPath ? import_path.default.dirname(packageJsonPath) : process.cwd();
f7eb47b… lmata 62 this.configDir = configDir;
f7eb47b… lmata 63 this.configCLIOverrides = configCLIOverrides;
f7eb47b… lmata 64 const privateConfiguration = userConfig["@playwright/test"];
f7eb47b… lmata 65 this.plugins = (privateConfiguration?.plugins || []).map((p) => ({ factory: p }));
f7eb47b… lmata 66 this.singleTSConfigPath = pathResolve(configDir, userConfig.tsconfig);
f7eb47b… lmata 67 this.captureGitInfo = userConfig.captureGitInfo;
f7eb47b… lmata 68 this.failOnFlakyTests = takeFirst(configCLIOverrides.failOnFlakyTests, userConfig.failOnFlakyTests, false);
f7eb47b… lmata 69 this.globalSetups = (Array.isArray(userConfig.globalSetup) ? userConfig.globalSetup : [userConfig.globalSetup]).map((s) => resolveScript(s, configDir)).filter((script) => script !== void 0);
f7eb47b… lmata 70 this.globalTeardowns = (Array.isArray(userConfig.globalTeardown) ? userConfig.globalTeardown : [userConfig.globalTeardown]).map((s) => resolveScript(s, configDir)).filter((script) => script !== void 0);
f7eb47b… lmata 71 userConfig.metadata = userConfig.metadata || {};
f7eb47b… lmata 72 const globalTags = Array.isArray(userConfig.tag) ? userConfig.tag : userConfig.tag ? [userConfig.tag] : [];
f7eb47b… lmata 73 for (const tag of globalTags) {
f7eb47b… lmata 74 if (tag[0] !== "@")
f7eb47b… lmata 75 throw new Error(`Tag must start with "@" symbol, got "${tag}" instead.`);
f7eb47b… lmata 76 }
f7eb47b… lmata 77 this.config = {
f7eb47b… lmata 78 configFile: resolvedConfigFile,
f7eb47b… lmata 79 rootDir: pathResolve(configDir, userConfig.testDir) || configDir,
f7eb47b… lmata 80 forbidOnly: takeFirst(configCLIOverrides.forbidOnly, userConfig.forbidOnly, false),
f7eb47b… lmata 81 fullyParallel: takeFirst(configCLIOverrides.fullyParallel, userConfig.fullyParallel, false),
f7eb47b… lmata 82 globalSetup: this.globalSetups[0] ?? null,
f7eb47b… lmata 83 globalTeardown: this.globalTeardowns[0] ?? null,
f7eb47b… lmata 84 globalTimeout: takeFirst(configCLIOverrides.debug ? 0 : void 0, configCLIOverrides.globalTimeout, userConfig.globalTimeout, 0),
f7eb47b… lmata 85 grep: takeFirst(userConfig.grep, defaultGrep),
f7eb47b… lmata 86 grepInvert: takeFirst(userConfig.grepInvert, null),
f7eb47b… lmata 87 maxFailures: takeFirst(configCLIOverrides.debug ? 1 : void 0, configCLIOverrides.maxFailures, userConfig.maxFailures, 0),
f7eb47b… lmata 88 metadata: metadata ?? userConfig.metadata,
f7eb47b… lmata 89 preserveOutput: takeFirst(userConfig.preserveOutput, "always"),
f7eb47b… lmata 90 projects: [],
f7eb47b… lmata 91 quiet: takeFirst(configCLIOverrides.quiet, userConfig.quiet, false),
f7eb47b… lmata 92 reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(userConfig.reporter, configDir), [[defaultReporter]]),
f7eb47b… lmata 93 reportSlowTests: takeFirst(userConfig.reportSlowTests, {
f7eb47b… lmata 94 max: 5,
f7eb47b… lmata 95 threshold: 3e5
f7eb47b… lmata 96 /* 5 minutes */
f7eb47b… lmata 97 }),
f7eb47b… lmata 98 // @ts-expect-error runAgents is hidden
f7eb47b… lmata 99 runAgents: takeFirst(configCLIOverrides.runAgents, "none"),
f7eb47b… lmata 100 shard: takeFirst(configCLIOverrides.shard, userConfig.shard, null),
f7eb47b… lmata 101 tags: globalTags,
f7eb47b… lmata 102 updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, userConfig.updateSnapshots, "missing"),
f7eb47b… lmata 103 updateSourceMethod: takeFirst(configCLIOverrides.updateSourceMethod, userConfig.updateSourceMethod, "patch"),
f7eb47b… lmata 104 version: require("../../package.json").version,
f7eb47b… lmata 105 workers: resolveWorkers(takeFirst(configCLIOverrides.debug || configCLIOverrides.pause ? 1 : void 0, configCLIOverrides.workers, userConfig.workers, "50%")),
f7eb47b… lmata 106 webServer: null
f7eb47b… lmata 107 };
f7eb47b… lmata 108 for (const key in userConfig) {
f7eb47b… lmata 109 if (key.startsWith("@"))
f7eb47b… lmata 110 this.config[key] = userConfig[key];
f7eb47b… lmata 111 }
f7eb47b… lmata 112 this.config[configInternalSymbol] = this;
f7eb47b… lmata 113 const webServers = takeFirst(userConfig.webServer, null);
f7eb47b… lmata 114 if (Array.isArray(webServers)) {
f7eb47b… lmata 115 this.config.webServer = null;
f7eb47b… lmata 116 this.webServers = webServers;
f7eb47b… lmata 117 } else if (webServers) {
f7eb47b… lmata 118 this.config.webServer = webServers;
f7eb47b… lmata 119 this.webServers = [webServers];
f7eb47b… lmata 120 } else {
f7eb47b… lmata 121 this.webServers = [];
f7eb47b… lmata 122 }
f7eb47b… lmata 123 const projectConfigs = configCLIOverrides.projects || userConfig.projects || [{ ...userConfig, workers: void 0 }];
f7eb47b… lmata 124 this.projects = projectConfigs.map((p) => new FullProjectInternal(configDir, userConfig, this, p, this.configCLIOverrides, packageJsonDir));
f7eb47b… lmata 125 resolveProjectDependencies(this.projects);
f7eb47b… lmata 126 this._assignUniqueProjectIds(this.projects);
f7eb47b… lmata 127 this.config.projects = this.projects.map((p) => p.project);
f7eb47b… lmata 128 }
f7eb47b… lmata 129 _assignUniqueProjectIds(projects) {
f7eb47b… lmata 130 const usedNames = /* @__PURE__ */ new Set();
f7eb47b… lmata 131 for (const p of projects) {
f7eb47b… lmata 132 const name = p.project.name || "";
f7eb47b… lmata 133 for (let i = 0; i < projects.length; ++i) {
f7eb47b… lmata 134 const candidate = name + (i ? i : "");
f7eb47b… lmata 135 if (usedNames.has(candidate))
f7eb47b… lmata 136 continue;
f7eb47b… lmata 137 p.id = candidate;
f7eb47b… lmata 138 p.project.__projectId = p.id;
f7eb47b… lmata 139 usedNames.add(candidate);
f7eb47b… lmata 140 break;
f7eb47b… lmata 141 }
f7eb47b… lmata 142 }
f7eb47b… lmata 143 }
f7eb47b… lmata 144 }
f7eb47b… lmata 145 class FullProjectInternal {
f7eb47b… lmata 146 constructor(configDir, config, fullConfig, projectConfig, configCLIOverrides, packageJsonDir) {
f7eb47b… lmata 147 this.id = "";
f7eb47b… lmata 148 this.deps = [];
f7eb47b… lmata 149 this.fullConfig = fullConfig;
f7eb47b… lmata 150 const testDir = takeFirst(pathResolve(configDir, projectConfig.testDir), pathResolve(configDir, config.testDir), fullConfig.configDir);
f7eb47b… lmata 151 this.snapshotPathTemplate = takeFirst(projectConfig.snapshotPathTemplate, config.snapshotPathTemplate);
f7eb47b… lmata 152 this.project = {
f7eb47b… lmata 153 grep: takeFirst(projectConfig.grep, config.grep, defaultGrep),
f7eb47b… lmata 154 grepInvert: takeFirst(projectConfig.grepInvert, config.grepInvert, null),
f7eb47b… lmata 155 outputDir: takeFirst(configCLIOverrides.outputDir, pathResolve(configDir, projectConfig.outputDir), pathResolve(configDir, config.outputDir), import_path.default.join(packageJsonDir, "test-results")),
f7eb47b… lmata 156 // Note: we either apply the cli override for repeatEach or not, depending on whether the
f7eb47b… lmata 157 // project is top-level vs dependency. See collectProjectsAndTestFiles in loadUtils.
f7eb47b… lmata 158 repeatEach: takeFirst(projectConfig.repeatEach, config.repeatEach, 1),
f7eb47b… lmata 159 retries: takeFirst(configCLIOverrides.retries, projectConfig.retries, config.retries, 0),
f7eb47b… lmata 160 metadata: takeFirst(projectConfig.metadata, config.metadata, {}),
f7eb47b… lmata 161 name: takeFirst(projectConfig.name, config.name, ""),
f7eb47b… lmata 162 testDir,
f7eb47b… lmata 163 snapshotDir: takeFirst(pathResolve(configDir, projectConfig.snapshotDir), pathResolve(configDir, config.snapshotDir), testDir),
f7eb47b… lmata 164 testIgnore: takeFirst(projectConfig.testIgnore, config.testIgnore, []),
f7eb47b… lmata 165 testMatch: takeFirst(projectConfig.testMatch, config.testMatch, "**/*.@(spec|test).?(c|m)[jt]s?(x)"),
f7eb47b… lmata 166 timeout: takeFirst(configCLIOverrides.debug ? 0 : void 0, configCLIOverrides.timeout, projectConfig.timeout, config.timeout, defaultTimeout),
f7eb47b… lmata 167 use: (0, import_util.mergeObjects)(config.use, projectConfig.use, configCLIOverrides.use),
f7eb47b… lmata 168 dependencies: projectConfig.dependencies || [],
f7eb47b… lmata 169 teardown: projectConfig.teardown
f7eb47b… lmata 170 };
f7eb47b… lmata 171 this.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, projectConfig.fullyParallel, config.fullyParallel, void 0);
f7eb47b… lmata 172 this.expect = takeFirst(projectConfig.expect, config.expect, {});
f7eb47b… lmata 173 if (this.expect.toHaveScreenshot?.stylePath) {
f7eb47b… lmata 174 const stylePaths = Array.isArray(this.expect.toHaveScreenshot.stylePath) ? this.expect.toHaveScreenshot.stylePath : [this.expect.toHaveScreenshot.stylePath];
f7eb47b… lmata 175 this.expect.toHaveScreenshot.stylePath = stylePaths.map((stylePath) => import_path.default.resolve(configDir, stylePath));
f7eb47b… lmata 176 }
f7eb47b… lmata 177 this.respectGitIgnore = takeFirst(projectConfig.respectGitIgnore, config.respectGitIgnore, !projectConfig.testDir && !config.testDir);
f7eb47b… lmata 178 this.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, projectConfig.ignoreSnapshots, config.ignoreSnapshots, false);
f7eb47b… lmata 179 this.workers = projectConfig.workers ? resolveWorkers(projectConfig.workers) : void 0;
f7eb47b… lmata 180 if (configCLIOverrides.debug && this.workers)
f7eb47b… lmata 181 this.workers = 1;
f7eb47b… lmata 182 }
f7eb47b… lmata 183 }
f7eb47b… lmata 184 function takeFirst(...args) {
f7eb47b… lmata 185 for (const arg of args) {
f7eb47b… lmata 186 if (arg !== void 0)
f7eb47b… lmata 187 return arg;
f7eb47b… lmata 188 }
f7eb47b… lmata 189 return void 0;
f7eb47b… lmata 190 }
f7eb47b… lmata 191 function pathResolve(baseDir, relative) {
f7eb47b… lmata 192 if (!relative)
f7eb47b… lmata 193 return void 0;
f7eb47b… lmata 194 return import_path.default.resolve(baseDir, relative);
f7eb47b… lmata 195 }
f7eb47b… lmata 196 function resolveReporters(reporters, rootDir) {
f7eb47b… lmata 197 return toReporters(reporters)?.map(([id, arg]) => {
f7eb47b… lmata 198 if (builtInReporters.includes(id))
f7eb47b… lmata 199 return [id, arg];
f7eb47b… lmata 200 return [require.resolve(id, { paths: [rootDir] }), arg];
f7eb47b… lmata 201 });
f7eb47b… lmata 202 }
f7eb47b… lmata 203 function resolveWorkers(workers) {
f7eb47b… lmata 204 if (typeof workers === "string") {
f7eb47b… lmata 205 if (workers.endsWith("%")) {
f7eb47b… lmata 206 const cpus = import_os.default.cpus().length;
f7eb47b… lmata 207 return Math.max(1, Math.floor(cpus * (parseInt(workers, 10) / 100)));
f7eb47b… lmata 208 }
f7eb47b… lmata 209 const parsedWorkers = parseInt(workers, 10);
f7eb47b… lmata 210 if (isNaN(parsedWorkers))
f7eb47b… lmata 211 throw new Error(`Workers ${workers} must be a number or percentage.`);
f7eb47b… lmata 212 return parsedWorkers;
f7eb47b… lmata 213 }
f7eb47b… lmata 214 return workers;
f7eb47b… lmata 215 }
f7eb47b… lmata 216 function resolveProjectDependencies(projects) {
f7eb47b… lmata 217 const teardownSet = /* @__PURE__ */ new Set();
f7eb47b… lmata 218 for (const project of projects) {
f7eb47b… lmata 219 for (const dependencyName of project.project.dependencies) {
f7eb47b… lmata 220 const dependencies = projects.filter((p) => p.project.name === dependencyName);
f7eb47b… lmata 221 if (!dependencies.length)
f7eb47b… lmata 222 throw new Error(`Project '${project.project.name}' depends on unknown project '${dependencyName}'`);
f7eb47b… lmata 223 if (dependencies.length > 1)
f7eb47b… lmata 224 throw new Error(`Project dependencies should have unique names, reading ${dependencyName}`);
f7eb47b… lmata 225 project.deps.push(...dependencies);
f7eb47b… lmata 226 }
f7eb47b… lmata 227 if (project.project.teardown) {
f7eb47b… lmata 228 const teardowns = projects.filter((p) => p.project.name === project.project.teardown);
f7eb47b… lmata 229 if (!teardowns.length)
f7eb47b… lmata 230 throw new Error(`Project '${project.project.name}' has unknown teardown project '${project.project.teardown}'`);
f7eb47b… lmata 231 if (teardowns.length > 1)
f7eb47b… lmata 232 throw new Error(`Project teardowns should have unique names, reading ${project.project.teardown}`);
f7eb47b… lmata 233 const teardown = teardowns[0];
f7eb47b… lmata 234 project.teardown = teardown;
f7eb47b… lmata 235 teardownSet.add(teardown);
f7eb47b… lmata 236 }
f7eb47b… lmata 237 }
f7eb47b… lmata 238 for (const teardown of teardownSet) {
f7eb47b… lmata 239 if (teardown.deps.length)
f7eb47b… lmata 240 throw new Error(`Teardown project ${teardown.project.name} must not have dependencies`);
f7eb47b… lmata 241 }
f7eb47b… lmata 242 for (const project of projects) {
f7eb47b… lmata 243 for (const dep of project.deps) {
f7eb47b… lmata 244 if (teardownSet.has(dep))
f7eb47b… lmata 245 throw new Error(`Project ${project.project.name} must not depend on a teardown project ${dep.project.name}`);
f7eb47b… lmata 246 }
f7eb47b… lmata 247 }
f7eb47b… lmata 248 }
f7eb47b… lmata 249 function toReporters(reporters) {
f7eb47b… lmata 250 if (!reporters)
f7eb47b… lmata 251 return;
f7eb47b… lmata 252 if (typeof reporters === "string")
f7eb47b… lmata 253 return [[reporters]];
f7eb47b… lmata 254 return reporters;
f7eb47b… lmata 255 }
f7eb47b… lmata 256 const builtInReporters = ["list", "line", "dot", "json", "junit", "null", "github", "html", "blob"];
f7eb47b… lmata 257 function resolveScript(id, rootDir) {
f7eb47b… lmata 258 if (!id)
f7eb47b… lmata 259 return void 0;
f7eb47b… lmata 260 const localPath = import_path.default.resolve(rootDir, id);
f7eb47b… lmata 261 if (import_fs.default.existsSync(localPath))
f7eb47b… lmata 262 return localPath;
f7eb47b… lmata 263 return require.resolve(id, { paths: [rootDir] });
f7eb47b… lmata 264 }
f7eb47b… lmata 265 const defaultGrep = /.*/;
f7eb47b… lmata 266 const defaultReporter = process.env.CI ? "dot" : "list";
f7eb47b… lmata 267 const configInternalSymbol = Symbol("configInternalSymbol");
f7eb47b… lmata 268 function getProjectId(project) {
f7eb47b… lmata 269 return project.__projectId;
f7eb47b… lmata 270 }
f7eb47b… lmata 271 // Annotate the CommonJS export names for ESM import in node:
f7eb47b… lmata 272 0 && (module.exports = {
f7eb47b… lmata 273 FullConfigInternal,
f7eb47b… lmata 274 FullProjectInternal,
f7eb47b… lmata 275 builtInReporters,
f7eb47b… lmata 276 defaultGrep,
f7eb47b… lmata 277 defaultReporter,
f7eb47b… lmata 278 defaultTimeout,
f7eb47b… lmata 279 getProjectId,
f7eb47b… lmata 280 takeFirst,
f7eb47b… lmata 281 toReporters
f7eb47b… lmata 282 });

Keyboard Shortcuts

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