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,106 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
DEFAULT_SITE_PRIMARY_COLOR,
|
||||
buildDefaultSiteSettings,
|
||||
normalizeSiteDefaultLocale,
|
||||
normalizeSitePrimaryColor,
|
||||
parseSiteSettingsValue,
|
||||
} from "@/lib/site-settings";
|
||||
|
||||
describe("normalizeSiteDefaultLocale", () => {
|
||||
it("keeps the three supported locales", () => {
|
||||
expect(normalizeSiteDefaultLocale("ar")).toBe("ar");
|
||||
expect(normalizeSiteDefaultLocale("en")).toBe("en");
|
||||
expect(normalizeSiteDefaultLocale("de")).toBe("de");
|
||||
});
|
||||
|
||||
it("defaults to de for anything else", () => {
|
||||
expect(normalizeSiteDefaultLocale("fr")).toBe("de");
|
||||
expect(normalizeSiteDefaultLocale(undefined)).toBe("de");
|
||||
expect(normalizeSiteDefaultLocale(123)).toBe("de");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normalizeSitePrimaryColor", () => {
|
||||
it("accepts and lowercases 6-digit hex", () => {
|
||||
expect(normalizeSitePrimaryColor("#AABBCC")).toBe("#aabbcc");
|
||||
expect(normalizeSitePrimaryColor(" #112233 ")).toBe("#112233");
|
||||
});
|
||||
|
||||
it("rejects invalid colors", () => {
|
||||
expect(normalizeSitePrimaryColor("red")).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
expect(normalizeSitePrimaryColor("#abc")).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
expect(normalizeSitePrimaryColor("#12345g")).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
expect(normalizeSitePrimaryColor(42)).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
expect(normalizeSitePrimaryColor(null)).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildDefaultSiteSettings", () => {
|
||||
it("uses the fallback name across all locales", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio Moh");
|
||||
expect(settings.defaultLocale).toBe("de");
|
||||
expect(settings.brand.primaryColor).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
expect(settings.locales.ar.siteName).toBe("Studio Moh");
|
||||
expect(settings.locales.en.titleTemplate).toBe("{pageTitle} | {siteName}");
|
||||
expect(settings.locales.de.subhead).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseSiteSettingsValue", () => {
|
||||
it("returns defaults for empty input", () => {
|
||||
expect(parseSiteSettingsValue(null, "Fallback")).toEqual(buildDefaultSiteSettings("Fallback"));
|
||||
});
|
||||
|
||||
it("returns defaults for invalid json", () => {
|
||||
expect(parseSiteSettingsValue("{bad", "Fallback")).toEqual(buildDefaultSiteSettings("Fallback"));
|
||||
});
|
||||
|
||||
it("merges stored values with safe defaults", () => {
|
||||
const settings = parseSiteSettingsValue(
|
||||
JSON.stringify({
|
||||
defaultLocale: "ar",
|
||||
brand: { primaryColor: "#112233" },
|
||||
locales: {
|
||||
en: { siteName: "Brand EN", titleTemplate: "{pageTitle} - {siteName}", siteDescription: "English" },
|
||||
de: { siteName: "Brand DE", subhead: "Sub" },
|
||||
},
|
||||
}),
|
||||
"Fallback",
|
||||
);
|
||||
expect(settings.defaultLocale).toBe("ar");
|
||||
expect(settings.brand.primaryColor).toBe("#112233");
|
||||
expect(settings.locales.en.siteName).toBe("Brand EN");
|
||||
expect(settings.locales.en.titleTemplate).toBe("{pageTitle} - {siteName}");
|
||||
expect(settings.locales.en.subhead).toBe("");
|
||||
expect(settings.locales.ar.siteName).toBe("Fallback");
|
||||
expect(settings.locales.de.subhead).toBe("Sub");
|
||||
});
|
||||
|
||||
it("ignores title templates that lack the {pageTitle} token", () => {
|
||||
const settings = parseSiteSettingsValue(
|
||||
JSON.stringify({ locales: { en: { siteName: "X", titleTemplate: "no token here" } } }),
|
||||
"Fallback",
|
||||
);
|
||||
expect(settings.locales.en.titleTemplate).toBe("{pageTitle} | {siteName}");
|
||||
});
|
||||
|
||||
it("falls back for invalid default locale and primary color", () => {
|
||||
const settings = parseSiteSettingsValue(
|
||||
JSON.stringify({ defaultLocale: "fr", brand: { primaryColor: "nope" } }),
|
||||
"Fallback",
|
||||
);
|
||||
expect(settings.defaultLocale).toBe("de");
|
||||
expect(settings.brand.primaryColor).toBe(DEFAULT_SITE_PRIMARY_COLOR);
|
||||
});
|
||||
|
||||
it("trims string fields", () => {
|
||||
const settings = parseSiteSettingsValue(
|
||||
JSON.stringify({ locales: { de: { siteName: " Trimmed ", siteDescription: " d " } } }),
|
||||
"Fallback",
|
||||
);
|
||||
expect(settings.locales.de.siteName).toBe("Trimmed");
|
||||
expect(settings.locales.de.siteDescription).toBe("d");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user