From d2f4bddcb110e320bb344a4fce242fcf05e1c5df Mon Sep 17 00:00:00 2001 From: rocketraccoon Date: Tue, 30 Jun 2026 00:15:44 +0700 Subject: [PATCH] fix: add timetravel timeout --- src/worker/runner/test-runner/index.js | 17 ++++++- test/src/worker/runner/test-runner/index.js | 55 +++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/worker/runner/test-runner/index.js b/src/worker/runner/test-runner/index.js index 41dda4966..c6cd68e9d 100644 --- a/src/worker/runner/test-runner/index.js +++ b/src/worker/runner/test-runner/index.js @@ -14,6 +14,9 @@ const { filterExtraStackFrames } = require("../../../browser/stacktrace/utils"); const { extendWithCodeSnippet } = require("../../../error-snippets"); const { startSelectivity } = require("../../../browser/cdp/selectivity"); +const SNAPSHOTS_TIMEOUT_MS = 5000; +const SNAPSHOTS_WARNING_TIMEOUT_MS = 2000; + module.exports = class TestRunner { static create(...args) { return new this(...args); @@ -229,13 +232,23 @@ module.exports = class TestRunner { attempt: this._attempt, }); + const snapshotsTimeout = new Promise((_, reject) => + setTimeout( + () => + reject(new Error(`Collecting Time Travel snapshots timed out after ${SNAPSHOTS_TIMEOUT_MS}ms`)), + SNAPSHOTS_TIMEOUT_MS, + ), + ); + // If collecting time travel snapshots takes a lot of time, make it obvious by writing a message const collectingSnapshotsMessageTimeout = setTimeout(() => { console.log("Collecting Time Travel snapshots takes longer than expected. Waiting..."); - }, 2000); + }, SNAPSHOTS_WARNING_TIMEOUT_MS); try { - await this._browser.snapshotsPromiseRef.current; + await Promise.race([this._browser.snapshotsPromiseRef.current, snapshotsTimeout]); + } catch (e) { + console.error(e.message); } finally { clearTimeout(collectingSnapshotsMessageTimeout); await history.cleanupDomSnapshots({ diff --git a/test/src/worker/runner/test-runner/index.js b/test/src/worker/runner/test-runner/index.js index 51aea617d..d69877582 100644 --- a/test/src/worker/runner/test-runner/index.js +++ b/test/src/worker/runner/test-runner/index.js @@ -1079,4 +1079,59 @@ describe("worker/runner/test-runner", () => { assert.strictEqual(browser.state.isLastTestFailed, false); }); }); + + describe("snapshots collection timeout", () => { + let clock; + let TimeTravelTestRunner; + + const run_ = async () => { + const browser = mkBrowser_(); + browser.snapshotsPromiseRef = { current: new Promise(() => {}) }; + BrowserAgent.prototype.getBrowser.resolves(browser); + + const runner = TimeTravelTestRunner.create({ + test: mkTest_(), + file: "/default/file/path", + config: makeConfigStub(), + browserAgent: Object.create(BrowserAgent.prototype), + }); + + await runner.prepareBrowser({ sessionId: "session-id", sessionCaps: {}, sessionOpts: {}, state: {} }); + return runner.run(); + }; + + beforeEach(() => { + clock = sinon.useFakeTimers(); + + TimeTravelTestRunner = proxyquire("src/worker/runner/test-runner", { + "../../../browser/history": { + runGroup: historyRunGroupStub, + requestDomSnapshots: sandbox.stub(), + cleanupDomSnapshots: sandbox.stub().resolves(), + }, + "../../../browser/cdp/selectivity": { + startSelectivity: sandbox.stub().resolves(() => Promise.resolve()), + }, + "./capture-fail-screenshot": { + captureFailScreenshot: captureFailScreenshotStub, + }, + }); + }); + + afterEach(() => { + clock.restore(); + }); + + it("should log warning after 2 seconds if snapshots collection is slow and log error after 5 seconds timeout ", async () => { + sandbox.stub(console, "error"); + sandbox.stub(console, "log"); + + const runPromise = run_(); + await clock.tickAsync(5000); + await runPromise; + + assert.calledWith(console.log, "Collecting Time Travel snapshots takes longer than expected. Waiting..."); + assert.calledWith(console.error, "Collecting Time Travel snapshots timed out after 5000ms"); + }); + }); });