From 0078b736b97cd3d99b59f3a1740b3de2a8135f6a Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Mon, 23 Mar 2026 22:17:03 +0900 Subject: [PATCH] fix: stabilize stale timeout tests with fixed Date.now() Tests 'should use default timeout when config not provided' (manager.test.ts) and 'should use DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS when not configured' (task-poller.test.ts) failed in CI because Date.now() drifted between test setup (when creating timestamps like Date.now() - 46*60*1000) and actual execution inside checkAndInterruptStaleTasks(). On slower CI machines, this drift pushed borderline values across the threshold, causing tasks that should be stale to remain 'running'. Fix: Mock Date.now with spyOn to return a fixed time, ensuring consistent timeout calculations regardless of execution speed. --- src/features/background-agent/manager.test.ts | 14 +++++++++++++- src/features/background-agent/task-poller.test.ts | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/features/background-agent/manager.test.ts b/src/features/background-agent/manager.test.ts index 44b4c0859..4553cf1cb 100644 --- a/src/features/background-agent/manager.test.ts +++ b/src/features/background-agent/manager.test.ts @@ -1,5 +1,5 @@ declare const require: (name: string) => any -const { describe, test, expect, beforeEach, afterEach } = require("bun:test") +const { describe, test, expect, beforeEach, afterEach, spyOn } = require("bun:test") import { tmpdir } from "node:os" import type { PluginInput } from "@opencode-ai/plugin" import type { BackgroundTask, ResumeInput } from "./types" @@ -2781,6 +2781,18 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { }) describe("BackgroundManager.checkAndInterruptStaleTasks", () => { + const originalDateNow = Date.now + let fixedTime: number + + beforeEach(() => { + fixedTime = Date.now() + spyOn(globalThis.Date, "now").mockReturnValue(fixedTime) + }) + + afterEach(() => { + Date.now = originalDateNow + }) + test("should NOT interrupt task running less than 30 seconds (min runtime guard)", async () => { const client = { session: { diff --git a/src/features/background-agent/task-poller.test.ts b/src/features/background-agent/task-poller.test.ts index a39a51b40..ec3d09a74 100644 --- a/src/features/background-agent/task-poller.test.ts +++ b/src/features/background-agent/task-poller.test.ts @@ -1,5 +1,5 @@ declare const require: (name: string) => any -const { describe, it, expect, mock } = require("bun:test") +const { describe, it, expect, mock, spyOn, beforeEach, afterEach } = require("bun:test") import { checkAndInterruptStaleTasks, pruneStaleTasksAndNotifications } from "./task-poller" import type { BackgroundTask } from "./types" @@ -29,6 +29,18 @@ describe("checkAndInterruptStaleTasks", () => { ...overrides, } } + const originalDateNow = Date.now + let fixedTime: number + + beforeEach(() => { + fixedTime = Date.now() + spyOn(globalThis.Date, "now").mockReturnValue(fixedTime) + }) + + afterEach(() => { + Date.now = originalDateNow + }) + it("should interrupt tasks with lastUpdate exceeding stale timeout", async () => { //#given