Add SPA session validation and buglist, update migration docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-03 21:28:08 +00:00
parent 9be3dfc14e
commit cff287e870
24169 changed files with 10223 additions and 7120 deletions

28
node_modules/playwright/lib/runner/dispatcher.js generated vendored Normal file → Executable file
View File

@@ -26,6 +26,8 @@ var import_utils2 = require("playwright-core/lib/utils");
var import_rebase = require("./rebase");
var import_workerHost = require("./workerHost");
var import_ipc = require("../common/ipc");
var import_internalReporter = require("../reporters/internalReporter");
var import_util = require("../util");
class Dispatcher {
constructor(config, reporter, failureTracker) {
this._workerSlots = [];
@@ -70,7 +72,7 @@ class Dispatcher {
return;
}
this._queue.splice(jobIndex, 1);
const jobDispatcher = new JobDispatcher(job, this._reporter, this._failureTracker, () => this.stop().catch(() => {
const jobDispatcher = new JobDispatcher(job, this._config, this._reporter, this._failureTracker, () => this.stop().catch(() => {
}));
this._workerSlots[workerIndex].busy = true;
this._workerSlots[workerIndex].jobDispatcher = jobDispatcher;
@@ -209,7 +211,7 @@ class Dispatcher {
}
}
class JobDispatcher {
constructor(job, reporter, failureTracker, stopCallback) {
constructor(job, config, reporter, failureTracker, stopCallback) {
this.jobResult = new import_utils.ManualPromise();
this._listeners = [];
this._failedTests = /* @__PURE__ */ new Set();
@@ -219,6 +221,7 @@ class JobDispatcher {
this._parallelIndex = 0;
this._workerIndex = 0;
this.job = job;
this._config = config;
this._reporter = reporter;
this._failureTracker = failureTracker;
this._stopCallback = stopCallback;
@@ -449,10 +452,30 @@ class JobDispatcher {
import_utils.eventsHelper.addEventListener(worker, "stepBegin", this._onStepBegin.bind(this)),
import_utils.eventsHelper.addEventListener(worker, "stepEnd", this._onStepEnd.bind(this)),
import_utils.eventsHelper.addEventListener(worker, "attach", this._onAttach.bind(this)),
import_utils.eventsHelper.addEventListener(worker, "testPaused", this._onTestPaused.bind(this, worker)),
import_utils.eventsHelper.addEventListener(worker, "done", this._onDone.bind(this)),
import_utils.eventsHelper.addEventListener(worker, "exit", this.onExit.bind(this))
];
}
_onTestPaused(worker, params) {
const sendMessage = async (message) => {
try {
if (this.jobResult.isDone())
throw new Error("Test has already stopped");
const response = await worker.sendCustomMessage({ testId: params.testId, request: message.request });
if (response.error)
(0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, response.error);
return response;
} catch (e) {
const error = (0, import_util.serializeError)(e);
(0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error);
return { response: void 0, error };
}
};
for (const error of params.errors)
(0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error);
this._failureTracker.onTestPaused?.({ ...params, sendMessage });
}
skipWholeJob() {
const allTestsSkipped = this.job.tests.every((test) => test.expectedStatus === "skipped");
if (allTestsSkipped && !this._failureTracker.hasReachedMaxFailures()) {
@@ -460,6 +483,7 @@ class JobDispatcher {
const result = test._appendTestResult();
this._reporter.onTestBegin?.(test, result);
result.status = "skipped";
result.annotations = [...test.annotations];
this._reportTestEnd(test, result);
}
return true;

10
node_modules/playwright/lib/runner/failureTracker.js generated vendored Normal file → Executable file
View File

@@ -22,13 +22,13 @@ __export(failureTracker_exports, {
});
module.exports = __toCommonJS(failureTracker_exports);
class FailureTracker {
constructor(_config, options) {
this._config = _config;
constructor(config, options) {
this._failureCount = 0;
this._hasWorkerErrors = false;
this._topLevelProjects = [];
this._pauseOnError = options?.pauseOnError ?? false;
this._pauseAtEnd = options?.pauseAtEnd ?? false;
this._config = config;
this._pauseOnError = !!options?.pauseOnError;
this._pauseAtEnd = !!options?.pauseAtEnd;
}
onRootSuite(rootSuite, topLevelProjects) {
this._rootSuite = rootSuite;
@@ -45,7 +45,7 @@ class FailureTracker {
return this._pauseOnError;
}
pauseAtEnd(inProject) {
return this._pauseAtEnd && this._topLevelProjects.includes(inProject);
return this._topLevelProjects.includes(inProject) && this._pauseAtEnd;
}
hasReachedMaxFailures() {
return this.maxFailures() > 0 && this._failureCount >= this.maxFailures();

0
node_modules/playwright/lib/runner/lastRun.js generated vendored Normal file → Executable file
View File

3
node_modules/playwright/lib/runner/loadUtils.js generated vendored Normal file → Executable file
View File

@@ -159,7 +159,8 @@ async function createRootSuite(testRun, errors, shouldFilterOnly) {
if (config.config.shard) {
const testGroups = [];
for (const projectSuite of rootSuite.suites) {
testGroups.push(...(0, import_testGroups.createTestGroups)(projectSuite, config.config.shard.total));
for (const group of (0, import_testGroups.createTestGroups)(projectSuite, config.config.shard.total))
testGroups.push(group);
}
const testGroupsInThisShard = (0, import_testGroups.filterForShard)(config.config.shard, testGroups);
const testsInThisShard = /* @__PURE__ */ new Set();

2
node_modules/playwright/lib/runner/loaderHost.js generated vendored Normal file → Executable file
View File

@@ -48,7 +48,7 @@ class InProcessLoaderHost {
return true;
}
async loadTestFile(file, testErrors) {
const result = await (0, import_testLoader.loadTestFile)(file, this._config.config.rootDir, testErrors);
const result = await (0, import_testLoader.loadTestFile)(file, this._config, testErrors);
this._poolBuilder.buildPools(result, testErrors);
return result;
}

0
node_modules/playwright/lib/runner/processHost.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/projectUtils.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/rebase.js generated vendored Normal file → Executable file
View File

9
node_modules/playwright/lib/runner/reporters.js generated vendored Normal file → Executable file
View File

@@ -47,7 +47,7 @@ var import_line = __toESM(require("../reporters/line"));
var import_list = __toESM(require("../reporters/list"));
var import_listModeReporter = __toESM(require("../reporters/listModeReporter"));
var import_reporterV2 = require("../reporters/reporterV2");
async function createReporters(config, mode, isTestServer, descriptions) {
async function createReporters(config, mode, descriptions) {
const defaultReporters = {
blob: import_blob.BlobReporter,
dot: mode === "list" ? import_listModeReporter.default : import_dot.default,
@@ -63,7 +63,7 @@ async function createReporters(config, mode, isTestServer, descriptions) {
descriptions ??= config.config.reporter;
if (config.configCLIOverrides.additionalReporters)
descriptions = [...descriptions, ...config.configCLIOverrides.additionalReporters];
const runOptions = reporterOptions(config, mode, isTestServer);
const runOptions = reporterOptions(config, mode);
for (const r of descriptions) {
const [name, arg] = r;
const options = { ...runOptions, ...arg };
@@ -104,11 +104,10 @@ function createErrorCollectingReporter(screen) {
errors: () => errors
};
}
function reporterOptions(config, mode, isTestServer) {
function reporterOptions(config, mode) {
return {
configDir: config.configDir,
_mode: mode,
_isTestServer: isTestServer,
_commandHash: computeCommandHash(config)
};
}
@@ -125,6 +124,8 @@ function computeCommandHash(config) {
command.cliGrepInvert = config.cliGrepInvert;
if (config.cliOnlyChanged)
command.cliOnlyChanged = config.cliOnlyChanged;
if (config.config.tags.length)
command.tags = config.config.tags.join(" ");
if (Object.keys(command).length)
parts.push((0, import_utils.calculateSha1)(JSON.stringify(command)).substring(0, 7));
return parts.join("-");

0
node_modules/playwright/lib/runner/sigIntWatcher.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/taskRunner.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/tasks.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/testGroups.js generated vendored Normal file → Executable file
View File

17
node_modules/playwright/lib/runner/testRunner.js generated vendored Normal file → Executable file
View File

@@ -51,7 +51,8 @@ var import_reporters = require("./reporters");
var import_tasks = require("./tasks");
var import_lastRun = require("./lastRun");
const TestRunnerEvent = {
TestFilesChanged: "testFilesChanged"
TestFilesChanged: "testFilesChanged",
TestPaused: "testPaused"
};
class TestRunner extends import_events.default {
constructor(configLocation, configCLIOverrides) {
@@ -93,7 +94,7 @@ class TestRunner extends import_events.default {
}
async installBrowsers() {
const executables = import_server.registry.defaultExecutables();
await import_server.registry.install(executables, false);
await import_server.registry.install(executables);
}
async loadConfig() {
const { config, error } = await this._loadConfig(this._configCLIOverrides);
@@ -245,16 +246,13 @@ class TestRunner extends import_events.default {
...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
_optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : void 0,
actionTimeout: params.actionTimeout
},
...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" };
@@ -269,7 +267,7 @@ class TestRunner extends import_events.default {
const testIdSet = new Set(params.testIds);
config.preOnlyTestFilters.push((test) => testIdSet.has(test.id));
}
const configReporters = params.disableConfigReporters ? [] : await (0, import_reporters.createReporters)(config, "test", true);
const configReporters = params.disableConfigReporters ? [] : await (0, import_reporters.createReporters)(config, "test");
const reporter = new import_internalReporter.InternalReporter([...configReporters, userReporter]);
const stop = new import_utils.ManualPromise();
const tasks = [
@@ -278,6 +276,7 @@ class TestRunner extends import_events.default {
...(0, import_tasks.createRunTestsTasks)(config)
];
const testRun = new import_tasks.TestRun(config, reporter, { pauseOnError: params.pauseOnError, pauseAtEnd: params.pauseAtEnd });
testRun.failureTracker.onTestPaused = (params2) => this.emit(TestRunnerEvent.TestPaused, params2);
const run = (0, import_tasks.runTasks)(testRun, tasks, 0, stop).then(async (status) => {
this._testRun = void 0;
return status;
@@ -363,7 +362,7 @@ 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 reporters = await (0, import_reporters.createReporters)(config, listOnly ? "list" : "test");
const lastRun = new import_lastRun.LastRunReporter(config);
if (config.cliLastFailed)
await lastRun.filterLastFailed();

11
node_modules/playwright/lib/runner/testServer.js generated vendored Normal file → Executable file
View File

@@ -45,6 +45,7 @@ var import_testRunner = require("./testRunner");
const originalDebugLog = import_utilsBundle.debug.log;
const originalStdoutWrite = process.stdout.write;
const originalStderrWrite = process.stderr.write;
const originalStdinIsTTY = process.stdin.isTTY;
class TestServer {
constructor(configLocation, configCLIOverrides) {
this._configLocation = configLocation;
@@ -74,6 +75,7 @@ class TestServerDispatcher {
};
this._dispatchEvent = (method, params) => this.transport.sendEvent?.(method, params);
this._testRunner.on(import_testRunner.TestRunnerEvent.TestFilesChanged, (testFiles) => this._dispatchEvent("testFilesChanged", { testFiles }));
this._testRunner.on(import_testRunner.TestRunnerEvent.TestPaused, (params) => this._dispatchEvent("testPaused", { errors: params.errors }));
}
async _wireReporter(messageSink) {
return await (0, import_reporters.createReporterForTestServer)(this._serializer, messageSink);
@@ -110,7 +112,6 @@ class TestServerDispatcher {
await this._testRunner.installBrowsers();
}
async runGlobalSetup(params) {
await this.runGlobalTeardown();
const { reporter, report } = await this._collectingReporter();
this._globalSetupReport = report;
const { status } = await this._testRunner.runGlobalSetup([reporter, new import_list.default()]);
@@ -151,7 +152,9 @@ class TestServerDispatcher {
const wireReporter = await this._wireReporter((e) => this._dispatchEvent("report", e));
const { status } = await this._testRunner.runTests(wireReporter, {
...params,
doNotRunDepsOutsideProjectFilter: true
doNotRunDepsOutsideProjectFilter: true,
pauseAtEnd: params.pauseAtEnd,
pauseOnError: params.pauseOnError
});
return { status };
}
@@ -191,17 +194,19 @@ class TestServerDispatcher {
};
process.stdout.write = stdoutWrite;
process.stderr.write = stderrWrite;
process.stdin.isTTY = void 0;
} else {
import_utilsBundle.debug.log = originalDebugLog;
process.stdout.write = originalStdoutWrite;
process.stderr.write = originalStderrWrite;
process.stdin.isTTY = originalStdinIsTTY;
}
}
}
async function runUIMode(configFile, configCLIOverrides, options) {
const configLocation = (0, import_configLoader.resolveConfigLocation)(configFile);
return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server, cancelPromise) => {
await (0, import_server.installRootRedirect)(server, [], { ...options, webApp: "uiMode.html" });
await (0, import_server.installRootRedirect)(server, void 0, { ...options, webApp: "uiMode.html" });
if (options.host !== void 0 || options.port !== void 0) {
await (0, import_server.openTraceInBrowser)(server.urlPrefix("human-readable"));
} else {

0
node_modules/playwright/lib/runner/uiModeReporter.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/vcs.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/runner/watchMode.js generated vendored Normal file → Executable file
View File

3
node_modules/playwright/lib/runner/workerHost.js generated vendored Normal file → Executable file
View File

@@ -79,6 +79,9 @@ class WorkerHost extends import_processHost.ProcessHost {
runTestGroup(runPayload) {
this.sendMessageNoReply({ method: "runTestGroup", params: runPayload });
}
async sendCustomMessage(payload) {
return await this.sendMessage({ method: "customMessage", params: payload });
}
hash() {
return this._hash;
}