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:
@@ -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" });
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user