// @vitest-environment jsdom
import { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { useNativeRunTranscripts } from "./useNativeRunTranscripts";
const eventsMock = vi.hoisted(() => vi.fn());
vi.mock("@/api/heartbeats", () => ({
heartbeatsApi: { events: eventsMock },
}));
function Probe() {
const { errorsByRun } = useNativeRunTranscripts([
{ id: "native-run", status: "succeeded", runtimeMode: "native" },
]);
return (
{[...errorsByRun.keys()].join(",")}
);
}
function MultiRunProbe() {
useNativeRunTranscripts([
{ id: "failed-run", status: "succeeded", runtimeMode: "native" },
{ id: "healthy-run", status: "succeeded", runtimeMode: "native" },
]);
return null;
}
describe("useNativeRunTranscripts", () => {
let container: HTMLDivElement;
let root: Root;
beforeEach(() => {
vi.useFakeTimers();
eventsMock.mockReset();
container = document.createElement("div");
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
vi.useRealTimers();
});
it("exposes event transport failures and retries terminal runs until recovery", async () => {
eventsMock
.mockRejectedValueOnce(new Error("event endpoint unavailable"))
.mockResolvedValue([]);
await act(async () => {
root.render();
await Promise.resolve();
});
expect(container.textContent).toBe("native-run");
await act(async () => {
await vi.advanceTimersByTimeAsync(2_000);
});
expect(eventsMock).toHaveBeenCalledTimes(2);
expect(container.textContent).toBe("");
});
it("retries only terminal runs whose event request failed", async () => {
eventsMock.mockImplementation((runId: string) => (
runId === "failed-run"
? Promise.reject(new Error("event endpoint unavailable"))
: Promise.resolve([])
));
await act(async () => {
root.render();
await Promise.resolve();
});
expect(eventsMock).toHaveBeenCalledTimes(2);
await act(async () => {
await vi.advanceTimersByTimeAsync(2_000);
});
expect(eventsMock).toHaveBeenCalledTimes(3);
expect(eventsMock.mock.calls.at(-1)?.[0]).toBe("failed-run");
});
});