test: add unit and component tests across the monorepo

Adds ~1000 tests to bring the previously-untested packages and apps
under coverage:

- packages/utils — string, color, date, file, level, locale, sanitize,
  field, html, network-icons, rate-limit, url, url-security, monorepo,
  resume/patch, resume/docx/link-utils, style helpers (~97% on the
  testable utility files)
- packages/ui — 28 component test files plus the use-controlled-state,
  use-mobile, use-confirm, use-prompt hooks (95% statements)
- packages/pdf — shared template helpers (filtering, columns, picture,
  metrics, section-links, page-size, rich-text-html, section-title)
- packages/schema — resumeDataSchema, page, templates, default
- packages/fonts — expanded coverage on font helpers
- packages/ai — resume sanitize and extraction template
- packages/api — resume-access-policy
- apps/web — error-message, locale, theme, pwa, dialogs/store, and
  the resume/move-item / section-actions / make-section-item helpers

Adds jsdom polyfills (ResizeObserver, IntersectionObserver,
scrollIntoView, matchMedia) and an explicit React Testing Library
cleanup hook to vitest.setup.ts so portal- and overlay-based components
work without per-test setup.
This commit is contained in:
Amruth Pillai
2026-05-10 20:00:07 +02:00
parent 33103536ae
commit 6a01207b6b
83 changed files with 8097 additions and 4 deletions
@@ -0,0 +1,85 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { Button } from "./button";
describe("Button", () => {
it("renders children", () => {
render(<Button>Click me</Button>);
expect(screen.getByRole("button", { name: "Click me" })).toBeInTheDocument();
});
it("defaults to type='button' to prevent accidental form submits", () => {
render(<Button>Submit</Button>);
expect(screen.getByRole("button")).toHaveAttribute("type", "button");
});
it("respects an explicit type override", () => {
render(<Button type="submit">Submit</Button>);
expect(screen.getByRole("button")).toHaveAttribute("type", "submit");
});
it("applies the data-slot attribute for shadcn/base-ui slotting", () => {
render(<Button>x</Button>);
expect(screen.getByRole("button")).toHaveAttribute("data-slot", "button");
});
it("merges custom className with variant classes", () => {
render(<Button className="my-custom-class">x</Button>);
expect(screen.getByRole("button")).toHaveClass("my-custom-class");
});
it("calls onClick when clicked", async () => {
const onClick = vi.fn();
render(<Button onClick={onClick}>Click</Button>);
await userEvent.click(screen.getByRole("button"));
expect(onClick).toHaveBeenCalledOnce();
});
it("does not fire onClick when disabled", async () => {
const onClick = vi.fn();
render(
<Button disabled onClick={onClick}>
Click
</Button>,
);
await userEvent.click(screen.getByRole("button"));
expect(onClick).not.toHaveBeenCalled();
});
it("renders disabled state", () => {
render(<Button disabled>x</Button>);
expect(screen.getByRole("button")).toBeDisabled();
});
it.each([
["default"],
["outline"],
["secondary"],
["ghost"],
["destructive"],
["link"],
] as const)("renders variant=%s without throwing", (variant) => {
render(<Button variant={variant}>x</Button>);
expect(screen.getByRole("button")).toBeInTheDocument();
});
it.each([
["default"],
["xs"],
["sm"],
["lg"],
["icon"],
["icon-xs"],
["icon-sm"],
["icon-lg"],
] as const)("renders size=%s without throwing", (size) => {
render(<Button size={size}>x</Button>);
expect(screen.getByRole("button")).toBeInTheDocument();
});
it("forwards aria-label", () => {
render(<Button aria-label="Close">×</Button>);
expect(screen.getByRole("button", { name: "Close" })).toBeInTheDocument();
});
});