Add tests for Dialog and Tooltip, raise components/ui threshold to 93%
Dialog: open/close lifecycle, cancel event handling, DialogHeader. Tooltip: show on pointer enter, hide on pointer leave. Raises components/ui coverage threshold to enforce testing of future primitives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
71
apps/web/src/components/__tests__/dialog.test.tsx
Normal file
71
apps/web/src/components/__tests__/dialog.test.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
import { cleanup, render, screen } from "@testing-library/react";
|
||||||
|
import { userEvent } from "@testing-library/user-event";
|
||||||
|
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||||
|
import { Dialog, DialogHeader } from "../ui/dialog.js";
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
HTMLDialogElement.prototype.showModal =
|
||||||
|
HTMLDialogElement.prototype.showModal ||
|
||||||
|
function showModal(this: HTMLDialogElement) {
|
||||||
|
this.setAttribute("open", "");
|
||||||
|
};
|
||||||
|
HTMLDialogElement.prototype.close =
|
||||||
|
HTMLDialogElement.prototype.close ||
|
||||||
|
function close(this: HTMLDialogElement) {
|
||||||
|
this.removeAttribute("open");
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(cleanup);
|
||||||
|
|
||||||
|
describe("Dialog", () => {
|
||||||
|
it("opens when open=true", () => {
|
||||||
|
render(
|
||||||
|
<Dialog open={true} onClose={() => {}}>
|
||||||
|
Content
|
||||||
|
</Dialog>,
|
||||||
|
);
|
||||||
|
expect(screen.getByText("Content")).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("closes when open changes from true to false", () => {
|
||||||
|
const { rerender } = render(
|
||||||
|
<Dialog open={true} onClose={() => {}}>
|
||||||
|
Content
|
||||||
|
</Dialog>,
|
||||||
|
);
|
||||||
|
const dialog = document.querySelector("dialog");
|
||||||
|
expect(dialog?.hasAttribute("open")).toBe(true);
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<Dialog open={false} onClose={() => {}}>
|
||||||
|
Content
|
||||||
|
</Dialog>,
|
||||||
|
);
|
||||||
|
expect(dialog?.hasAttribute("open")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onClose on cancel event", () => {
|
||||||
|
const onClose = vi.fn();
|
||||||
|
render(
|
||||||
|
<Dialog open={true} onClose={onClose}>
|
||||||
|
Content
|
||||||
|
</Dialog>,
|
||||||
|
);
|
||||||
|
const dialog = document.querySelector("dialog");
|
||||||
|
dialog?.dispatchEvent(new Event("cancel"));
|
||||||
|
expect(onClose).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("DialogHeader", () => {
|
||||||
|
it("renders title and close button", async () => {
|
||||||
|
const onClose = vi.fn();
|
||||||
|
render(<DialogHeader title="Test Title" onClose={onClose} />);
|
||||||
|
|
||||||
|
expect(screen.getByText("Test Title")).toBeDefined();
|
||||||
|
await userEvent.click(screen.getByRole("button"));
|
||||||
|
expect(onClose).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
});
|
||||||
42
apps/web/src/components/__tests__/tooltip.test.tsx
Normal file
42
apps/web/src/components/__tests__/tooltip.test.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import { afterEach, describe, expect, it } from "vitest";
|
||||||
|
import { Tooltip } from "../ui/tooltip.js";
|
||||||
|
|
||||||
|
afterEach(cleanup);
|
||||||
|
|
||||||
|
describe("Tooltip", () => {
|
||||||
|
it("renders children", () => {
|
||||||
|
render(
|
||||||
|
<Tooltip content="Hint">
|
||||||
|
<button type="button">Hover me</button>
|
||||||
|
</Tooltip>,
|
||||||
|
);
|
||||||
|
expect(screen.getByText("Hover me")).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show tooltip initially", () => {
|
||||||
|
render(
|
||||||
|
<Tooltip content="Hint">
|
||||||
|
<span>Target</span>
|
||||||
|
</Tooltip>,
|
||||||
|
);
|
||||||
|
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows tooltip on pointer enter and hides on pointer leave", () => {
|
||||||
|
render(
|
||||||
|
<Tooltip content="Hint text">
|
||||||
|
<span>Target</span>
|
||||||
|
</Tooltip>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const wrapper = screen.getByText("Target").closest("span");
|
||||||
|
fireEvent.pointerEnter(wrapper as HTMLElement);
|
||||||
|
expect(screen.getByRole("tooltip")).toBeDefined();
|
||||||
|
expect(screen.getByText("Hint text")).toBeDefined();
|
||||||
|
|
||||||
|
fireEvent.pointerLeave(wrapper as HTMLElement);
|
||||||
|
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -34,8 +34,8 @@ export default defineConfig({
|
|||||||
branches: 55,
|
branches: 55,
|
||||||
},
|
},
|
||||||
"apps/web/src/components/ui": {
|
"apps/web/src/components/ui": {
|
||||||
lines: 86,
|
lines: 93,
|
||||||
branches: 83,
|
branches: 90,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user