test(prompt-async-gate): replace setTimeout sleeps with deterministic sync

Test-discipline.md forbids setTimeout(resolve, N) and sleep(N) in test bodies. Replace the 3 microtask and expiry sleeps with explicit microtask yields and deterministic clock advancement, preserving the prompt gate invariants without real-time waits.

Closes BLOCKER-3

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-16 01:36:57 +09:00
parent f8d6f2a2ec
commit 845d862b9b
+32 -27
View File
@@ -3,8 +3,8 @@ import { afterEach, describe, expect, test } from "bun:test"
import { import {
promptAfterSessionIdle, promptAfterSessionIdle,
promptAsyncAfterSessionIdle, promptAsyncAfterSessionIdle,
releasePromptAsyncReservation,
releaseAllPromptAsyncReservationsForTesting, releaseAllPromptAsyncReservationsForTesting,
releasePromptAsyncReservation,
} from "./prompt-async-gate" } from "./prompt-async-gate"
describe("promptAsyncAfterSessionIdle", () => { describe("promptAsyncAfterSessionIdle", () => {
@@ -76,7 +76,7 @@ describe("promptAsyncAfterSessionIdle", () => {
source: "test:hold:first", source: "test:hold:first",
settleMs: 0, settleMs: 0,
}) })
await new Promise((resolve) => setTimeout(resolve, 0)) await new Promise<void>((resolve) => queueMicrotask(resolve))
const second = await promptAsyncAfterSessionIdle({ const second = await promptAsyncAfterSessionIdle({
client, client,
sessionID: "ses_hold_after_dispatch", sessionID: "ses_hold_after_dispatch",
@@ -85,7 +85,6 @@ describe("promptAsyncAfterSessionIdle", () => {
settleMs: 0, settleMs: 0,
}) })
const firstResult = await first const firstResult = await first
// then // then
expect(firstResult.status).toBe("dispatched") expect(firstResult.status).toBe("dispatched")
expect(second.status).toBe("reserved") expect(second.status).toBe("reserved")
@@ -122,6 +121,9 @@ describe("promptAsyncAfterSessionIdle", () => {
test("#given dispatch hold has expired #when the same session prompts again #then the next promptAsync is accepted", async () => { test("#given dispatch hold has expired #when the same session prompts again #then the next promptAsync is accepted", async () => {
// given // given
let promptCalls = 0 let promptCalls = 0
const originalDateNow = Date.now
let currentNow = originalDateNow()
Date.now = () => currentNow
const client = { const client = {
session: { session: {
promptAsync: async () => { promptAsync: async () => {
@@ -130,29 +132,33 @@ describe("promptAsyncAfterSessionIdle", () => {
}, },
} }
// when try {
const first = await promptAsyncAfterSessionIdle({ // when
client, const first = await promptAsyncAfterSessionIdle({
sessionID: "ses_expired_hold", client,
input: { path: { id: "ses_expired_hold" }, body: { parts: [] } }, sessionID: "ses_expired_hold",
source: "test:expired:first", input: { path: { id: "ses_expired_hold" }, body: { parts: [] } },
settleMs: 0, source: "test:expired:first",
postDispatchHoldMs: 1, settleMs: 0,
}) postDispatchHoldMs: 1,
await new Promise((resolve) => setTimeout(resolve, 5)) })
const second = await promptAsyncAfterSessionIdle({ currentNow += 2
client, const second = await promptAsyncAfterSessionIdle({
sessionID: "ses_expired_hold", client,
input: { path: { id: "ses_expired_hold" }, body: { parts: [] } }, sessionID: "ses_expired_hold",
source: "test:expired:second", input: { path: { id: "ses_expired_hold" }, body: { parts: [] } },
settleMs: 0, source: "test:expired:second",
postDispatchHoldMs: 0, settleMs: 0,
}) postDispatchHoldMs: 0,
})
// then // then
expect(first.status).toBe("dispatched") expect(first.status).toBe("dispatched")
expect(second.status).toBe("dispatched") expect(second.status).toBe("dispatched")
expect(promptCalls).toBe(2) expect(promptCalls).toBe(2)
} finally {
Date.now = originalDateNow
}
}) })
test("#given a peer-message promptAsync hold #when an unrelated route releases the session #then the peer-message hold remains reserved", async () => { test("#given a peer-message promptAsync hold #when an unrelated route releases the session #then the peer-message hold remains reserved", async () => {
@@ -425,7 +431,7 @@ describe("promptAsyncAfterSessionIdle", () => {
source: "test:prompt-hold:first", source: "test:prompt-hold:first",
settleMs: 0, settleMs: 0,
}) })
await new Promise((resolve) => setTimeout(resolve, 0)) await new Promise<void>((resolve) => queueMicrotask(resolve))
const second = await promptAfterSessionIdle({ const second = await promptAfterSessionIdle({
client, client,
sessionID: "ses_prompt_hold_after_dispatch", sessionID: "ses_prompt_hold_after_dispatch",
@@ -434,7 +440,6 @@ describe("promptAsyncAfterSessionIdle", () => {
settleMs: 0, settleMs: 0,
}) })
const firstResult = await first const firstResult = await first
// then // then
expect(firstResult.status).toBe("dispatched") expect(firstResult.status).toBe("dispatched")
expect(second.status).toBe("reserved") expect(second.status).toBe("reserved")