import { describe, it, expect, vi } from "vitest"; import { renderToStaticMarkup } from "react-dom/server"; // SSE hook + the server action are deliberately stubbed. The action's // optimistic result is provided by feeding `useActionState` a manual // initial state via the mock's exported helper. const sendTestActionMock = vi.fn(); vi.mock("@/actions/groups", () => ({ sendTestAction: (...args: unknown[]) => sendTestActionMock(...args), })); // Capture the handlers the form passes to useEvents so we can fire // `send_test.done` ourselves and observe the state transition. const eventHandlers: { "send_test.done"?: (e: { groupId: string; ok: boolean; error: string | null }) => void; } = {}; vi.mock("@/hooks/use-events", () => ({ useEvents: (handlers: typeof eventHandlers) => { Object.assign(eventHandlers, handlers); }, })); import { SendTestForm } from "./send-test-form"; describe("SendTestForm — initial render", () => { it("renders the textarea and submit button, no status pill yet", () => { const html = renderToStaticMarkup(); expect(html).toMatch(/]*name="text"/); expect(html).toMatch(/]*type="submit"/); expect(html).toContain("Send Test"); // No success / error / in-flight pill on first render. expect(html).not.toContain("Sent ✓"); expect(html).not.toContain("Sending"); expect(html).not.toContain("role=\"alert\""); }); it("includes the groupId as a hidden input the action will read", () => { const html = renderToStaticMarkup(); expect(html).toMatch(/]+type="hidden"[^>]+name="groupId"[^>]+value="abc-uuid"/); }); }); describe("SendTestForm — wires `send_test.done` events", () => { it("registers a `send_test.done` handler with useEvents on render", () => { // Reset the captured handlers between tests. delete eventHandlers["send_test.done"]; renderToStaticMarkup(); expect(typeof eventHandlers["send_test.done"]).toBe("function"); }); it("the handler ignores events for OTHER groups (won't move our state)", () => { // We can't easily inspect React state from SSR markup, but we can // at least verify the handler accepts and discards an event with a // mismatched groupId without throwing. delete eventHandlers["send_test.done"]; renderToStaticMarkup(); expect(() => eventHandlers["send_test.done"]?.({ groupId: "g-2", ok: true, error: null, }), ).not.toThrow(); }); it("the handler accepts a matching success event without throwing", () => { delete eventHandlers["send_test.done"]; renderToStaticMarkup(); expect(() => eventHandlers["send_test.done"]?.({ groupId: "g-1", ok: true, error: null, }), ).not.toThrow(); }); it("the handler accepts a matching failure event without throwing", () => { delete eventHandlers["send_test.done"]; renderToStaticMarkup(); expect(() => eventHandlers["send_test.done"]?.({ groupId: "g-1", ok: false, error: "Account not connected", }), ).not.toThrow(); }); });