From a15d28d6fa43b7f6488f8095b866df1cc0cd5d4b Mon Sep 17 00:00:00 2001 From: Brad Harris Date: Wed, 5 Aug 2026 20:23:39 -0600 Subject: [PATCH] Add unit coverage for the template launch dialog LaunchTemplateDialog (automations-launch-dialog.tsx) had zero direct coverage despite owning the template launch contract: required-arg gating, agent-type override, the JSON-vs-multipart wire payload, and the consumer wiring of the shared useStartupAttachments hook. 13 jsdom tests render the real dialog, mutation, and context picker with only the HTTP and toast seams mocked, pinning both payload branches end to end plus success navigation, error toast, pending-resubmit suppression, and the terminal/allowMedia gating. A 12-mutant battery was verified killed. Co-Authored-By: Claude Fable 5 --- .../app/automations-launch-dialog.test.tsx | 401 ++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 apps/web/src/components/app/automations-launch-dialog.test.tsx diff --git a/apps/web/src/components/app/automations-launch-dialog.test.tsx b/apps/web/src/components/app/automations-launch-dialog.test.tsx new file mode 100644 index 00000000..b45d9384 --- /dev/null +++ b/apps/web/src/components/app/automations-launch-dialog.test.tsx @@ -0,0 +1,401 @@ +// @vitest-environment jsdom +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { + act, + cleanup, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/react"; +import { MemoryRouter, useLocation } from "react-router-dom"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import type { Agent } from "@/components/app/types"; +import type { Template } from "@/hooks/use-templates"; + +import { LaunchTemplateDialog } from "./automations-launch-dialog"; + +// The dialog renders its real children and the real useTemplateActions +// mutation; only the HTTP seam and toast sink are mocked. That pins the whole +// launch contract end to end: form state -> mutation input -> wire payload +// (JSON vs multipart), which is exactly what a stubbed launchTemplate mock +// could silently get wrong. +vi.mock("@/lib/api", () => ({ api: vi.fn() })); +vi.mock("sonner", () => ({ toast: { error: vi.fn() } })); + +const { api } = await import("@/lib/api"); +const { toast } = await import("sonner"); +const apiMock = vi.mocked(api); +const toastErrorMock = vi.mocked(toast.error); + +function makeTemplate(overrides: Partial