cbc343963c
Three mechanisms, merged in ThreadList: a 10s heartbeat polling the new ?status=busy filter (out-of-band runs: scheduled tasks, other clients), a module-level running store fed by useChat's own run lifecycle (zero latency for this client's runs), and a spinner replacing the status dot while either source marks the thread busy. The BFF list route now validates and forwards the status filter, which also unbreaks the previously ignored status dropdown. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
getRunningThreadIds,
|
|
setThreadRunning,
|
|
subscribeRunningThreads,
|
|
} from "./useThreads";
|
|
|
|
describe("running thread store", () => {
|
|
it("tracks running threads and notifies subscribers", () => {
|
|
const listener = vi.fn();
|
|
const unsubscribe = subscribeRunningThreads(listener);
|
|
|
|
setThreadRunning("thread-a", true);
|
|
expect(getRunningThreadIds().has("thread-a")).toBe(true);
|
|
expect(listener).toHaveBeenCalledTimes(1);
|
|
|
|
setThreadRunning("thread-a", false);
|
|
expect(getRunningThreadIds().has("thread-a")).toBe(false);
|
|
expect(listener).toHaveBeenCalledTimes(2);
|
|
|
|
unsubscribe();
|
|
setThreadRunning("thread-b", true);
|
|
expect(listener).toHaveBeenCalledTimes(2);
|
|
setThreadRunning("thread-b", false);
|
|
});
|
|
|
|
it("keeps snapshot identity stable for useSyncExternalStore", () => {
|
|
const before = getRunningThreadIds();
|
|
// Re-asserting the same state must not swap the snapshot (no-op writes).
|
|
setThreadRunning("thread-c", true);
|
|
const during = getRunningThreadIds();
|
|
expect(during).not.toBe(before);
|
|
setThreadRunning("thread-c", true);
|
|
expect(getRunningThreadIds()).toBe(during);
|
|
setThreadRunning("thread-c", false);
|
|
});
|
|
});
|