test(cli): fix flaky rename watch test with deterministic waiter polling

The rename test relied on a fixed 300ms setTimeout to fire after the CLI
subprocess had registered its waiter — adequate in isolation but flaky
under full-suite load on Windows (CLI spawn + first HTTP request can
exceed 300ms). Add a tiny public MailboxStore.waiterCount(name) helper
so the test can poll until the waiter is actually registered before
triggering the rename. Also tighten the missing-name assertion from
not-zero to the contract-exact exit code 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-05-20 16:34:47 +02:00
parent 1c2c1d2f7e
commit 9f8c1d9e9d
2 changed files with 14 additions and 3 deletions

View File

@@ -294,6 +294,10 @@ export class MailboxStore {
this.waiters.delete(oldName); this.waiters.delete(oldName);
} }
waiterCount(name: string): number {
return this.waiters.get(name)?.size ?? 0;
}
rejectAllWaiters(): void { rejectAllWaiters(): void {
for (const bucket of this.waiters.values()) { for (const bucket of this.waiters.values()) {
for (const w of bucket) w.resolve({ kind: "aborted" }); for (const w of bucket) w.resolve({ kind: "aborted" });

View File

@@ -93,13 +93,20 @@ describe("claude-mailbox watch CLI", () => {
store.upsertMailbox("oldname"); store.upsertMailbox("oldname");
const child = spawn( const child = spawn(
process.execPath, process.execPath,
[CLI, "watch", "--block", "--name", "oldname", "--timeout", "3", "--url", baseUrl], [CLI, "watch", "--block", "--name", "oldname", "--timeout", "5", "--url", baseUrl],
{ stdio: ["ignore", "pipe", "pipe"] }, { stdio: ["ignore", "pipe", "pipe"] },
); );
let stdout = ""; let stdout = "";
child.stdout.on("data", (d) => { stdout += d.toString(); }); child.stdout.on("data", (d) => { stdout += d.toString(); });
setTimeout(() => store.rename("oldname", "newname"), 300); // Wait for the CLI subprocess to register its waiter before renaming.
// A fixed delay is flaky under full-suite load on Windows.
const start = Date.now();
while (store.waiterCount("oldname") === 0) {
if (Date.now() - start > 4000) throw new Error("CLI never registered a waiter");
await new Promise((r) => setTimeout(r, 25));
}
store.rename("oldname", "newname");
const code: number = await new Promise((r) => child.on("exit", (c) => r(c ?? 1))); const code: number = await new Promise((r) => child.on("exit", (c) => r(c ?? 1)));
expect(code).toBe(0); expect(code).toBe(0);
@@ -116,7 +123,7 @@ describe("claude-mailbox watch CLI", () => {
it("exits 1 when --name is missing", async () => { it("exits 1 when --name is missing", async () => {
const r = await runCli(["watch", "--block", "--timeout", "1", "--url", baseUrl]); const r = await runCli(["watch", "--block", "--timeout", "1", "--url", baseUrl]);
expect(r.status).not.toBe(0); expect(r.status).toBe(1);
expect(r.stderr).toMatch(/required.*name|name.*required/i); expect(r.stderr).toMatch(/required.*name|name.*required/i);
}); });
}); });