| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- "use strict";
- var __create = Object.create;
- var __defProp = Object.defineProperty;
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
- var __getOwnPropNames = Object.getOwnPropertyNames;
- var __getProtoOf = Object.getPrototypeOf;
- var __hasOwnProp = Object.prototype.hasOwnProperty;
- var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
- };
- var __copyProps = (to, from, except, desc) => {
- if (from && typeof from === "object" || typeof from === "function") {
- for (let key of __getOwnPropNames(from))
- if (!__hasOwnProp.call(to, key) && key !== except)
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
- }
- return to;
- };
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
- // If the importer is in node compatibility mode or this is not an ESM
- // file that has been converted to a CommonJS file using a Babel-
- // compatible transform (i.e. "__esModule" has not been set), then set
- // "default" to the CommonJS "module.exports" for node compatibility.
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
- mod
- ));
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
- var testRunner_exports = {};
- __export(testRunner_exports, {
- TestRunner: () => TestRunner,
- TestRunnerEvent: () => TestRunnerEvent,
- runAllTestsWithConfig: () => runAllTestsWithConfig
- });
- module.exports = __toCommonJS(testRunner_exports);
- var import_events = __toESM(require("events"));
- var import_fs = __toESM(require("fs"));
- var import_path = __toESM(require("path"));
- var import_server = require("playwright-core/lib/server");
- var import_utils = require("playwright-core/lib/utils");
- var import_configLoader = require("../common/configLoader");
- var import_fsWatcher = require("../fsWatcher");
- var import_teleReceiver = require("../isomorphic/teleReceiver");
- var import_gitCommitInfoPlugin = require("../plugins/gitCommitInfoPlugin");
- var import_webServerPlugin = require("../plugins/webServerPlugin");
- var import_base = require("../reporters/base");
- var import_internalReporter = require("../reporters/internalReporter");
- var import_compilationCache = require("../transform/compilationCache");
- var import_util = require("../util");
- var import_reporters = require("./reporters");
- var import_tasks = require("./tasks");
- var import_lastRun = require("./lastRun");
- const TestRunnerEvent = {
- TestFilesChanged: "testFilesChanged",
- RecoverFromStepError: "recoverFromStepError"
- };
- class TestRunner extends import_events.default {
- constructor(configLocation, configCLIOverrides) {
- super();
- this._watchedProjectDirs = /* @__PURE__ */ new Set();
- this._ignoredProjectOutputs = /* @__PURE__ */ new Set();
- this._watchedTestDependencies = /* @__PURE__ */ new Set();
- this._queue = Promise.resolve();
- this._watchTestDirs = false;
- this._populateDependenciesOnList = false;
- this._recoverFromStepErrors = false;
- this._resumeAfterStepErrors = /* @__PURE__ */ new Map();
- this.configLocation = configLocation;
- this._configCLIOverrides = configCLIOverrides;
- this._watcher = new import_fsWatcher.Watcher((events) => {
- const collector = /* @__PURE__ */ new Set();
- events.forEach((f) => (0, import_compilationCache.collectAffectedTestFiles)(f.file, collector));
- this.emit(TestRunnerEvent.TestFilesChanged, [...collector]);
- });
- }
- async initialize(params) {
- this._watchTestDirs = !!params.watchTestDirs;
- this._populateDependenciesOnList = !!params.populateDependenciesOnList;
- this._recoverFromStepErrors = !!params.recoverFromStepErrors;
- }
- resizeTerminal(params) {
- process.stdout.columns = params.cols;
- process.stdout.rows = params.rows;
- process.stderr.columns = params.cols;
- process.stderr.rows = params.rows;
- }
- hasSomeBrowsers() {
- for (const browserName of ["chromium", "webkit", "firefox"]) {
- try {
- import_server.registry.findExecutable(browserName).executablePathOrDie("javascript");
- return true;
- } catch {
- }
- }
- return false;
- }
- async installBrowsers() {
- const executables = import_server.registry.defaultExecutables();
- await import_server.registry.install(executables, false);
- }
- async runGlobalSetup(userReporters) {
- await this.runGlobalTeardown();
- const reporter = new import_internalReporter.InternalReporter(userReporters);
- const config = await this._loadConfigOrReportError(reporter, this._configCLIOverrides);
- if (!config)
- return { status: "failed" };
- const { status, cleanup } = await (0, import_tasks.runTasksDeferCleanup)(new import_tasks.TestRun(config, reporter), [
- ...(0, import_tasks.createGlobalSetupTasks)(config)
- ]);
- if (status !== "passed")
- await cleanup();
- else
- this._globalSetup = { cleanup };
- return { status };
- }
- async runGlobalTeardown() {
- const globalSetup = this._globalSetup;
- const status = await globalSetup?.cleanup();
- this._globalSetup = void 0;
- return { status };
- }
- async startDevServer(userReporter, mode) {
- await this.stopDevServer();
- const reporter = new import_internalReporter.InternalReporter([userReporter]);
- const config = await this._loadConfigOrReportError(reporter);
- if (!config)
- return { status: "failed" };
- const { status, cleanup } = await (0, import_tasks.runTasksDeferCleanup)(new import_tasks.TestRun(config, reporter), [
- ...(0, import_tasks.createPluginSetupTasks)(config),
- (0, import_tasks.createLoadTask)(mode, { failOnLoadErrors: true, filterOnly: false }),
- (0, import_tasks.createStartDevServerTask)()
- ]);
- if (status !== "passed")
- await cleanup();
- else
- this._devServer = { cleanup };
- return { status };
- }
- async stopDevServer() {
- const devServer = this._devServer;
- const status = await devServer?.cleanup();
- this._devServer = void 0;
- return { status };
- }
- async clearCache(userReporter) {
- const reporter = new import_internalReporter.InternalReporter(userReporter ? [userReporter] : []);
- const config = await this._loadConfigOrReportError(reporter);
- if (!config)
- return { status: "failed" };
- const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
- ...(0, import_tasks.createPluginSetupTasks)(config),
- (0, import_tasks.createClearCacheTask)(config)
- ]);
- return { status };
- }
- async listFiles(userReporter, projects) {
- const reporter = new import_internalReporter.InternalReporter([userReporter]);
- const config = await this._loadConfigOrReportError(reporter);
- if (!config)
- return { status: "failed" };
- config.cliProjectFilter = projects?.length ? projects : void 0;
- const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
- (0, import_tasks.createListFilesTask)(),
- (0, import_tasks.createReportBeginTask)()
- ]);
- return { status };
- }
- async listTests(userReporter, params) {
- let result;
- this._queue = this._queue.then(async () => {
- const { config, status } = await this._innerListTests(userReporter, params);
- if (config)
- await this._updateWatchedDirs(config);
- result = { status };
- }).catch(printInternalError);
- await this._queue;
- return result;
- }
- async _innerListTests(userReporter, params) {
- const overrides = {
- ...this._configCLIOverrides,
- repeatEach: 1,
- retries: 0
- };
- const reporter = new import_internalReporter.InternalReporter([userReporter]);
- const config = await this._loadConfigOrReportError(reporter, overrides);
- if (!config)
- return { status: "failed" };
- config.cliArgs = params.locations || [];
- config.cliGrep = params.grep;
- config.cliGrepInvert = params.grepInvert;
- config.cliProjectFilter = params.projects?.length ? params.projects : void 0;
- config.cliListOnly = true;
- const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
- (0, import_tasks.createLoadTask)("out-of-process", { failOnLoadErrors: false, filterOnly: false, populateDependencies: this._populateDependenciesOnList }),
- (0, import_tasks.createReportBeginTask)()
- ]);
- return { config, status };
- }
- async _updateWatchedDirs(config) {
- this._watchedProjectDirs = /* @__PURE__ */ new Set();
- this._ignoredProjectOutputs = /* @__PURE__ */ new Set();
- for (const p of config.projects) {
- this._watchedProjectDirs.add(p.project.testDir);
- this._ignoredProjectOutputs.add(p.project.outputDir);
- }
- const result = await resolveCtDirs(config);
- if (result) {
- this._watchedProjectDirs.add(result.templateDir);
- this._ignoredProjectOutputs.add(result.outDir);
- }
- if (this._watchTestDirs)
- await this._updateWatcher(false);
- }
- async _updateWatcher(reportPending) {
- await this._watcher.update([...this._watchedProjectDirs, ...this._watchedTestDependencies], [...this._ignoredProjectOutputs], reportPending);
- }
- async runTests(userReporter, params) {
- let result = { status: "passed" };
- this._queue = this._queue.then(async () => {
- result = await this._innerRunTests(userReporter, params).catch((e) => {
- printInternalError(e);
- return { status: "failed" };
- });
- });
- await this._queue;
- return result;
- }
- async _innerRunTests(userReporter, params) {
- await this.stopTests();
- const overrides = {
- ...this._configCLIOverrides,
- repeatEach: 1,
- retries: 0,
- preserveOutputDir: true,
- reporter: params.reporters ? params.reporters.map((r) => [r]) : void 0,
- use: {
- ...this._configCLIOverrides.use,
- ...params.trace === "on" ? { trace: { mode: "on", sources: false, _live: true } } : {},
- ...params.trace === "off" ? { trace: "off" } : {},
- ...params.video === "on" || params.video === "off" ? { video: params.video } : {},
- ...params.headed !== void 0 ? { headless: !params.headed } : {},
- _optionContextReuseMode: params.reuseContext ? "when-possible" : void 0,
- _optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : void 0
- },
- ...params.updateSnapshots ? { updateSnapshots: params.updateSnapshots } : {},
- ...params.updateSourceMethod ? { updateSourceMethod: params.updateSourceMethod } : {},
- ...params.workers ? { workers: params.workers } : {}
- };
- if (params.trace === "on")
- process.env.PW_LIVE_TRACE_STACKS = "1";
- else
- process.env.PW_LIVE_TRACE_STACKS = void 0;
- const config = await this._loadConfigOrReportError(new import_internalReporter.InternalReporter([userReporter]), overrides);
- if (!config)
- return { status: "failed" };
- config.cliListOnly = false;
- config.cliPassWithNoTests = true;
- config.cliArgs = params.locations || [];
- config.cliGrep = params.grep;
- config.cliGrepInvert = params.grepInvert;
- config.cliProjectFilter = params.projects?.length ? params.projects : void 0;
- config.preOnlyTestFilters = [];
- if (params.testIds) {
- const testIdSet = new Set(params.testIds);
- config.preOnlyTestFilters.push((test) => testIdSet.has(test.id));
- }
- const configReporters = await (0, import_reporters.createReporters)(config, "test", true);
- const reporter = new import_internalReporter.InternalReporter([...configReporters, userReporter]);
- const stop = new import_utils.ManualPromise();
- const tasks = [
- (0, import_tasks.createApplyRebaselinesTask)(),
- (0, import_tasks.createLoadTask)("out-of-process", { filterOnly: true, failOnLoadErrors: false, doNotRunDepsOutsideProjectFilter: true }),
- ...(0, import_tasks.createRunTestsTasks)(config)
- ];
- const testRun = new import_tasks.TestRun(config, reporter);
- testRun.failureTracker.setRecoverFromStepErrorHandler(this._recoverFromStepError.bind(this));
- const run = (0, import_tasks.runTasks)(testRun, tasks, 0, stop).then(async (status) => {
- this._testRun = void 0;
- return status;
- });
- this._testRun = { run, stop };
- return { status: await run };
- }
- async _recoverFromStepError(stepId, error) {
- if (!this._recoverFromStepErrors)
- return { stepId, status: "failed" };
- const recoveryPromise = new import_utils.ManualPromise();
- this._resumeAfterStepErrors.set(stepId, recoveryPromise);
- if (!error?.message || !error?.location)
- return { stepId, status: "failed" };
- this.emit(TestRunnerEvent.RecoverFromStepError, stepId, error.message, error.location);
- const recoveredResult = await recoveryPromise;
- if (recoveredResult.stepId !== stepId)
- return { stepId, status: "failed" };
- return recoveredResult;
- }
- async resumeAfterStepError(params) {
- const recoveryPromise = this._resumeAfterStepErrors.get(params.stepId);
- if (recoveryPromise)
- recoveryPromise.resolve(params);
- }
- async watch(fileNames) {
- this._watchedTestDependencies = /* @__PURE__ */ new Set();
- for (const fileName of fileNames) {
- this._watchedTestDependencies.add(fileName);
- (0, import_compilationCache.dependenciesForTestFile)(fileName).forEach((file) => this._watchedTestDependencies.add(file));
- }
- await this._updateWatcher(true);
- }
- async findRelatedTestFiles(files, userReporter) {
- const errorReporter = (0, import_reporters.createErrorCollectingReporter)(import_base.internalScreen);
- const reporter = new import_internalReporter.InternalReporter(userReporter ? [userReporter, errorReporter] : [errorReporter]);
- const config = await this._loadConfigOrReportError(reporter);
- if (!config)
- return { errors: errorReporter.errors(), testFiles: [] };
- const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), [
- ...(0, import_tasks.createPluginSetupTasks)(config),
- (0, import_tasks.createLoadTask)("out-of-process", { failOnLoadErrors: true, filterOnly: false, populateDependencies: true })
- ]);
- if (status !== "passed")
- return { errors: errorReporter.errors(), testFiles: [] };
- return { testFiles: (0, import_compilationCache.affectedTestFiles)(files) };
- }
- async stopTests() {
- this._testRun?.stop?.resolve();
- await this._testRun?.run;
- this._resumeAfterStepErrors.clear();
- }
- async closeGracefully() {
- (0, import_utils.gracefullyProcessExitDoNotHang)(0);
- }
- async _loadConfig(overrides) {
- try {
- const config = await (0, import_configLoader.loadConfig)(this.configLocation, overrides);
- if (!this._plugins) {
- (0, import_webServerPlugin.webServerPluginsForConfig)(config).forEach((p) => config.plugins.push({ factory: p }));
- (0, import_gitCommitInfoPlugin.addGitCommitInfoPlugin)(config);
- this._plugins = config.plugins || [];
- } else {
- config.plugins.splice(0, config.plugins.length, ...this._plugins);
- }
- return { config };
- } catch (e) {
- return { config: null, error: (0, import_util.serializeError)(e) };
- }
- }
- async _loadConfigOrReportError(reporter, overrides) {
- const { config, error } = await this._loadConfig(overrides);
- if (config)
- return config;
- reporter.onConfigure(import_teleReceiver.baseFullConfig);
- reporter.onError(error);
- await reporter.onEnd({ status: "failed" });
- await reporter.onExit();
- return null;
- }
- }
- function printInternalError(e) {
- console.error("Internal error:", e);
- }
- async function resolveCtDirs(config) {
- const use = config.config.projects[0].use;
- const relativeTemplateDir = use.ctTemplateDir || "playwright";
- const templateDir = await import_fs.default.promises.realpath(import_path.default.normalize(import_path.default.join(config.configDir, relativeTemplateDir))).catch(() => void 0);
- if (!templateDir)
- return null;
- const outDir = use.ctCacheDir ? import_path.default.resolve(config.configDir, use.ctCacheDir) : import_path.default.resolve(templateDir, ".cache");
- return {
- outDir,
- templateDir
- };
- }
- async function runAllTestsWithConfig(config) {
- const listOnly = config.cliListOnly;
- (0, import_gitCommitInfoPlugin.addGitCommitInfoPlugin)(config);
- (0, import_webServerPlugin.webServerPluginsForConfig)(config).forEach((p) => config.plugins.push({ factory: p }));
- const reporters = await (0, import_reporters.createReporters)(config, listOnly ? "list" : "test", false);
- const lastRun = new import_lastRun.LastRunReporter(config);
- if (config.cliLastFailed)
- await lastRun.filterLastFailed();
- const reporter = new import_internalReporter.InternalReporter([...reporters, lastRun]);
- const tasks = listOnly ? [
- (0, import_tasks.createLoadTask)("in-process", { failOnLoadErrors: true, filterOnly: false }),
- (0, import_tasks.createReportBeginTask)()
- ] : [
- (0, import_tasks.createApplyRebaselinesTask)(),
- ...(0, import_tasks.createGlobalSetupTasks)(config),
- (0, import_tasks.createLoadTask)("in-process", { filterOnly: true, failOnLoadErrors: true }),
- ...(0, import_tasks.createRunTestsTasks)(config)
- ];
- const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), tasks, config.config.globalTimeout);
- await new Promise((resolve) => process.stdout.write("", () => resolve()));
- await new Promise((resolve) => process.stderr.write("", () => resolve()));
- return status;
- }
- // Annotate the CommonJS export names for ESM import in node:
- 0 && (module.exports = {
- TestRunner,
- TestRunnerEvent,
- runAllTestsWithConfig
- });
|