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
+102
View File
@@ -0,0 +1,102 @@
import { describe, expect, it } from "vitest";
import { parseColorString, rgbaStringToHex } from "./color";
describe("rgbaStringToHex", () => {
it("converts opaque rgb to hex", () => {
expect(rgbaStringToHex("rgb(255, 0, 0)")).toBe("#ff0000");
});
it("converts opaque rgba to hex (alpha not represented)", () => {
expect(rgbaStringToHex("rgba(0, 255, 0, 1)")).toBe("#00ff00");
});
it("converts black", () => {
expect(rgbaStringToHex("rgb(0, 0, 0)")).toBe("#000000");
});
it("converts white", () => {
expect(rgbaStringToHex("rgb(255, 255, 255)")).toBe("#ffffff");
});
it("converts arbitrary mid-range color", () => {
expect(rgbaStringToHex("rgb(128, 64, 200)")).toBe("#8040c8");
});
});
describe("parseColorString", () => {
describe("rgb format", () => {
it("parses rgb without alpha as alpha=1", () => {
expect(parseColorString("rgb(255, 128, 64)")).toEqual({ r: 255, g: 128, b: 64, a: 1 });
});
it("parses rgba with alpha", () => {
expect(parseColorString("rgba(10, 20, 30, 0.5)")).toEqual({ r: 10, g: 20, b: 30, a: 0.5 });
});
it("parses rgba with alpha=0", () => {
expect(parseColorString("rgba(0, 0, 0, 0)")).toEqual({ r: 0, g: 0, b: 0, a: 0 });
});
it("handles extra whitespace in rgb", () => {
expect(parseColorString("rgb( 255 , 0 , 0 )")).toEqual({ r: 255, g: 0, b: 0, a: 1 });
});
it("trims surrounding whitespace", () => {
expect(parseColorString(" rgb(1, 2, 3) ")).toEqual({ r: 1, g: 2, b: 3, a: 1 });
});
it("returns null for malformed rgb", () => {
expect(parseColorString("rgb(255, 0)")).toBeNull();
expect(parseColorString("rgb(a, b, c)")).toBeNull();
});
});
describe("hex format", () => {
it("parses 6-digit hex", () => {
expect(parseColorString("#ff8040")).toEqual({ r: 255, g: 128, b: 64, a: 1 });
});
it("parses 6-digit hex uppercase", () => {
expect(parseColorString("#FF8040")).toEqual({ r: 255, g: 128, b: 64, a: 1 });
});
it("parses 3-digit hex by doubling each digit", () => {
expect(parseColorString("#f80")).toEqual({ r: 0xff, g: 0x88, b: 0x00, a: 1 });
});
it("parses #000 as black", () => {
expect(parseColorString("#000")).toEqual({ r: 0, g: 0, b: 0, a: 1 });
});
it("parses #fff as white", () => {
expect(parseColorString("#fff")).toEqual({ r: 255, g: 255, b: 255, a: 1 });
});
it("returns null for hex without #", () => {
expect(parseColorString("ff0000")).toBeNull();
});
it("returns null for invalid hex length", () => {
expect(parseColorString("#ff00")).toBeNull();
expect(parseColorString("#ff00ff00")).toBeNull();
});
it("returns null for hex with non-hex chars", () => {
expect(parseColorString("#zz0000")).toBeNull();
});
});
describe("invalid input", () => {
it("returns null for empty string", () => {
expect(parseColorString("")).toBeNull();
});
it("returns null for plain color names", () => {
expect(parseColorString("red")).toBeNull();
});
it("returns null for hsl format", () => {
expect(parseColorString("hsl(0, 100%, 50%)")).toBeNull();
});
});
});