test: add comprehensive automated test coverage
- Vitest multi-project setup (unit / integration / component) - Real-Postgres integration harness via in-process PGlite (TEST_DATABASE_URL override), migrations applied per worker; production code untouched - Unit: routing, locale, validation/Zod schemas, metadata, mail, site-theme, marquee, media, portfolio helpers, plus architecture-rule tests - Integration: Prisma data layer, API routes, and all server actions - Component: UI primitives and form components (jsdom + Testing Library) - 371 tests passing
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { buildSiteThemeStyleText, buildSiteThemeTokens } from "@/lib/site-theme";
|
||||
|
||||
const CHANNEL = /^\d+ \d+% \d+%$/;
|
||||
|
||||
describe("buildSiteThemeTokens", () => {
|
||||
it("converts pure red to the expected HSL channels", () => {
|
||||
const tokens = buildSiteThemeTokens("#ff0000");
|
||||
expect(tokens.light.primary).toBe("0 100% 50%");
|
||||
// dark primary lightens by 6 and clamps saturation into [40,95]
|
||||
expect(tokens.dark.primary).toBe("0 95% 56%");
|
||||
});
|
||||
|
||||
it("produces zero saturation for a neutral gray", () => {
|
||||
const tokens = buildSiteThemeTokens("#808080");
|
||||
expect(tokens.light.primary.startsWith("0 0%")).toBe(true);
|
||||
});
|
||||
|
||||
it("emits well-formed channel strings for every token", () => {
|
||||
const tokens = buildSiteThemeTokens("#dc5a35");
|
||||
for (const value of [
|
||||
tokens.light.primary,
|
||||
tokens.light.secondary,
|
||||
tokens.dark.primary,
|
||||
tokens.dark.secondary,
|
||||
]) {
|
||||
expect(value).toMatch(CHANNEL);
|
||||
}
|
||||
});
|
||||
|
||||
it("derives distinct dark and secondary variants", () => {
|
||||
const tokens = buildSiteThemeTokens("#dc5a35");
|
||||
expect(tokens.dark.primary).not.toBe(tokens.light.primary);
|
||||
expect(tokens.light.secondary).not.toBe(tokens.light.primary);
|
||||
});
|
||||
|
||||
it("falls back to the default brand color for invalid input", () => {
|
||||
expect(buildSiteThemeTokens("not-a-color")).toEqual(buildSiteThemeTokens("#dc5a35"));
|
||||
expect(buildSiteThemeTokens("")).toEqual(buildSiteThemeTokens("#dc5a35"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildSiteThemeStyleText", () => {
|
||||
it("emits :root and .dark blocks with the derived channels", () => {
|
||||
const css = buildSiteThemeStyleText("#ff0000");
|
||||
expect(css).toContain(":root {");
|
||||
expect(css).toContain(".dark {");
|
||||
expect(css).toContain("--primary: 0 100% 50%;");
|
||||
expect(css).toContain("--brand-secondary:");
|
||||
expect(css).toContain("--sidebar-ring:");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user