import type { Job } from "@shared/types.js"; import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import * as api from "../api"; import { TailoringEditor } from "./TailoringEditor"; vi.mock("../api", () => ({ getResumeProjectsCatalog: vi.fn().mockResolvedValue([]), updateJob: vi.fn().mockResolvedValue({}), summarizeJob: vi.fn(), generateJobPdf: vi.fn(), })); vi.mock("sonner", () => ({ toast: { success: vi.fn(), error: vi.fn(), }, })); const createJob = (overrides: Partial = {}): Job => ({ id: "job-1", tailoredSummary: "Saved summary", jobDescription: "Saved description", selectedProjectIds: "p1", ...overrides, }) as Job; describe("TailoringEditor", () => { beforeEach(() => { vi.clearAllMocks(); }); it("does not rehydrate local edits from same-job prop updates", async () => { const { rerender } = render( , ); await waitFor(() => expect(api.getResumeProjectsCatalog).toHaveBeenCalled(), ); fireEvent.change(screen.getByLabelText("Tailored Summary"), { target: { value: "Local draft" }, }); rerender( , ); expect(screen.getByLabelText("Tailored Summary")).toHaveValue("Local draft"); }); it("resets local state when job id changes", async () => { const { rerender } = render( , ); await waitFor(() => expect(api.getResumeProjectsCatalog).toHaveBeenCalled(), ); fireEvent.change(screen.getByLabelText("Tailored Summary"), { target: { value: "Local draft" }, }); rerender( , ); expect(screen.getByLabelText("Tailored Summary")).toHaveValue("New job summary"); }); it("emits dirty state changes", async () => { const onDirtyChange = vi.fn(); render( , ); await waitFor(() => expect(api.getResumeProjectsCatalog).toHaveBeenCalled(), ); fireEvent.change(screen.getByLabelText("Tailored Summary"), { target: { value: "Local draft" }, }); expect(onDirtyChange).toHaveBeenCalledWith(true); }); it("does not sync same-job props while summary field is focused", async () => { const { rerender } = render( , ); await waitFor(() => expect(api.getResumeProjectsCatalog).toHaveBeenCalled(), ); const summary = screen.getByLabelText("Tailored Summary"); fireEvent.focus(summary); rerender( , ); expect(screen.getByLabelText("Tailored Summary")).toHaveValue( "Saved summary", ); }); });