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,113 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { buildDefaultSiteSettings } from "@/lib/site-settings";
|
||||
import {
|
||||
applyTitleTemplateFn,
|
||||
buildAppMetadataFromConfig,
|
||||
buildLocaleAlternates,
|
||||
buildLocalizedMetadataFromConfig,
|
||||
} from "@/lib/metadata";
|
||||
|
||||
const noBindings = {
|
||||
siteLogoLight: null,
|
||||
siteLogoDark: null,
|
||||
favicon: null,
|
||||
defaultOgImage: null,
|
||||
};
|
||||
|
||||
describe("applyTitleTemplateFn", () => {
|
||||
it("substitutes page title and site name", () => {
|
||||
expect(applyTitleTemplateFn("About", "{pageTitle} | {siteName}", "Studio")).toBe("About | Studio");
|
||||
});
|
||||
|
||||
it("replaces every site-name token but only the first page-title token", () => {
|
||||
expect(applyTitleTemplateFn("P", "{siteName} {pageTitle} {siteName}", "S")).toBe("S P S");
|
||||
});
|
||||
|
||||
it("falls back to a default template when the token is missing", () => {
|
||||
expect(applyTitleTemplateFn("About", "Just Site", "Studio")).toBe("About | Studio");
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildLocaleAlternates", () => {
|
||||
it("builds canonical, hreflang, and x-default against the default locale", () => {
|
||||
const alt = buildLocaleAlternates("/about", "ar");
|
||||
expect(alt.canonical).toBe("https://mohfarawati.de/about");
|
||||
expect(alt.languages.ar).toBe("https://mohfarawati.de/about");
|
||||
expect(alt.languages.de).toBe("https://mohfarawati.de/de/about");
|
||||
expect(alt.languages.en).toBe("https://mohfarawati.de/en/about");
|
||||
expect(alt.languages["x-default"]).toBe("https://mohfarawati.de/about");
|
||||
});
|
||||
|
||||
it("shifts prefixes when the default locale changes", () => {
|
||||
const alt = buildLocaleAlternates("/about", "en");
|
||||
expect(alt.canonical).toBe("https://mohfarawati.de/about");
|
||||
expect(alt.languages.en).toBe("https://mohfarawati.de/about");
|
||||
expect(alt.languages.de).toBe("https://mohfarawati.de/de/about");
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildAppMetadataFromConfig", () => {
|
||||
it("uses summary twitter card and omits og images when unset", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio");
|
||||
const metadata = buildAppMetadataFromConfig(settings, noBindings);
|
||||
expect(metadata.title).toBe("Studio");
|
||||
expect(metadata.twitter).toMatchObject({ card: "summary" });
|
||||
expect(metadata.openGraph?.images).toBeUndefined();
|
||||
expect(metadata.metadataBase?.toString()).toBe("https://mohfarawati.de/");
|
||||
});
|
||||
|
||||
it("uses summary_large_image and a versioned favicon when bindings exist", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio");
|
||||
const metadata = buildAppMetadataFromConfig(settings, {
|
||||
...noBindings,
|
||||
favicon: { assetId: "f", url: "/uploads/media/site-settings/favicon.svg", version: "v9" },
|
||||
defaultOgImage: { assetId: "og", url: "/uploads/media/site-settings/og.png", version: "v9" },
|
||||
});
|
||||
expect(metadata.twitter).toMatchObject({ card: "summary_large_image" });
|
||||
expect(metadata.icons).toMatchObject({ icon: [{ url: "/favicon.ico?v=v9" }] });
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildLocalizedMetadataFromConfig", () => {
|
||||
it("applies the title template and localized description by default", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio");
|
||||
settings.locales.en.siteDescription = "English description";
|
||||
const metadata = buildLocalizedMetadataFromConfig({
|
||||
settings,
|
||||
bindings: noBindings,
|
||||
locale: "en",
|
||||
pathname: "/about",
|
||||
title: "About",
|
||||
});
|
||||
expect(metadata.title).toBe("About | Studio");
|
||||
expect(metadata.description).toBe("English description");
|
||||
expect(metadata.openGraph?.locale).toBe("en");
|
||||
});
|
||||
|
||||
it("can skip the title template (homepage)", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio");
|
||||
const metadata = buildLocalizedMetadataFromConfig({
|
||||
settings,
|
||||
bindings: noBindings,
|
||||
locale: "ar",
|
||||
pathname: "/",
|
||||
title: "الرئيسية",
|
||||
applyTitleTemplate: false,
|
||||
});
|
||||
expect(metadata.title).toBe("الرئيسية");
|
||||
});
|
||||
|
||||
it("prefers an explicit description over the locale default", () => {
|
||||
const settings = buildDefaultSiteSettings("Studio");
|
||||
const metadata = buildLocalizedMetadataFromConfig({
|
||||
settings,
|
||||
bindings: noBindings,
|
||||
locale: "de",
|
||||
pathname: "/x",
|
||||
title: "T",
|
||||
description: " Custom desc ",
|
||||
});
|
||||
expect(metadata.description).toBe("Custom desc");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user