/** * @vitest-environment jsdom */ import { cleanup, fireEvent, render, screen, waitFor, } from "@testing-library/react"; import { Popover } from "@workspace/ui/components/popover"; import { afterEach, describe, expect, it, vi } from "vitest"; import { RemarkForm } from "./remark-form"; afterEach(() => { cleanup(); }); function renderRemarkForm(props: Parameters[0]) { return render( ); } describe("RemarkForm", () => { it("submits an intentionally cleared remark", async () => { const onSave = vi.fn[0]["onSave"]>(); renderRemarkForm({ initialRemark: "old remark", onSave }); fireEvent.change(screen.getByPlaceholderText("在此输入备注..."), { target: { value: "" }, }); fireEvent.click(screen.getByRole("button", { name: "保存" })); await waitFor(() => expect(onSave).toHaveBeenCalledWith("")); }); it("shows loading and keeps the input disabled while saving", async () => { let resolveSave: (() => void) | undefined; const onSave = vi.fn( () => new Promise((resolve) => { resolveSave = resolve; }) ); renderRemarkForm({ initialRemark: "old remark", onSave }); fireEvent.click(screen.getByRole("button", { name: "保存" })); expect( screen.getByRole("button", { name: "保存中..." }).hasAttribute("disabled") ).toBe(true); expect( screen.getByPlaceholderText("在此输入备注...").hasAttribute("disabled") ).toBe(true); resolveSave?.(); await waitFor(() => expect( screen.getByRole("button", { name: "保存" }).hasAttribute("disabled") ).toBe(false) ); }); it("shows an error state and preserves input after save failure", async () => { const onSave = vi.fn[0]["onSave"]>(); onSave.mockRejectedValue(new Error("failed")); renderRemarkForm({ initialRemark: "old remark", onSave }); fireEvent.change(screen.getByPlaceholderText("在此输入备注..."), { target: { value: "kept remark" }, }); fireEvent.click(screen.getByRole("button", { name: "保存" })); expect((await screen.findByRole("alert")).textContent).toBe( "备注保存失败,请重试" ); expect(screen.getByDisplayValue("kept remark")).not.toBeNull(); }); });