Files
MOH 0a5f77d8de REFACTORED - migrate the data layer from Prisma to Drizzle (unify the stack)
- Add lib/db (Drizzle schema: 7 tables + 6 enums + relations, postgres.js client),
  drizzle.config.ts, lib/db/enums.ts (Prisma-compatible enum objects)
- Rewrite all 14 app consumers + 4 admin components to Drizzle
- Move the test DB layer to Drizzle + in-process PGlite; convert all 8 integration
  test files + factories (371 tests green)
- Remove Prisma: deps, prisma/ schema+migrations, lib/prisma.ts, Dockerfile prisma
  generate; wire db:generate/migrate/push/studio to drizzle-kit; update Makefile
- Preserve the old seed as scripts/legacy-prisma-seed.cjs (needs a Drizzle rewrite)
2026-08-07 14:18:41 +02:00

142 lines
4.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
DEFAULT_SITE_NAME,
MAINTENANCE_MODE_KEY,
SITE_NAME_KEY,
SITE_SETTINGS_ENTITY_ID,
SITE_SETTINGS_ENTITY_TYPE,
SITE_SETTINGS_FAVICON_FIELD_KEY,
SITE_SETTINGS_LOGO_LIGHT_FIELD_KEY,
buildDefaultMailSettings,
buildDefaultMarqueeSettings,
getMailSettings,
getMaintenanceMode,
getMarqueeSettings,
getSiteSettings,
getSiteSettingsMediaBindings,
setMaintenanceMode,
updateMailSettings,
updateMarqueeSettings,
updateSiteSettings,
} from "@/lib/app-config";
import { eq } from "drizzle-orm";
import { db } from "@/lib/db";
import { appConfig, mediaUsage } from "@/lib/db/schema";
import { createMediaAsset } from "@/tests/helpers/factories";
describe("maintenance mode", () => {
it("defaults to false when unset", async () => {
expect(await getMaintenanceMode()).toBe(false);
});
it("persists and reads back the enabled flag", async () => {
await setMaintenanceMode(true);
expect(await getMaintenanceMode()).toBe(true);
const row = await db.query.appConfig.findFirst({ where: eq(appConfig.key, MAINTENANCE_MODE_KEY) });
expect(row?.value).toBe("true");
await setMaintenanceMode(false);
expect(await getMaintenanceMode()).toBe(false);
});
});
describe("site settings", () => {
it("returns defaults (with fallback name) when nothing stored", async () => {
const settings = await getSiteSettings();
expect(settings.defaultLocale).toBe("de");
expect(settings.locales.en.siteName).toBe(DEFAULT_SITE_NAME);
});
it("uses the stored siteName key as the fallback name", async () => {
await db.insert(appConfig).values({ key: SITE_NAME_KEY, value: "My Studio" });
const settings = await getSiteSettings();
expect(settings.locales.ar.siteName).toBe("My Studio");
});
it("round-trips an updated settings object", async () => {
const next = await getSiteSettings();
next.defaultLocale = "ar";
next.brand.primaryColor = "#123456";
next.locales.en.siteName = "Updated EN";
await updateSiteSettings(next);
const reloaded = await getSiteSettings();
expect(reloaded.defaultLocale).toBe("ar");
expect(reloaded.brand.primaryColor).toBe("#123456");
expect(reloaded.locales.en.siteName).toBe("Updated EN");
});
});
describe("mail settings", () => {
it("returns defaults when unset", async () => {
expect(await getMailSettings()).toEqual(buildDefaultMailSettings());
});
it("round-trips stored mail settings", async () => {
const next = buildDefaultMailSettings();
next.smtp.host = "smtp.test";
next.smtp.port = 465;
next.sender.email = "from@test";
next.recipients.contact = "c@test";
await updateMailSettings(next);
const reloaded = await getMailSettings();
expect(reloaded.smtp.host).toBe("smtp.test");
expect(reloaded.smtp.port).toBe(465);
expect(reloaded.recipients.contact).toBe("c@test");
});
});
describe("marquee settings", () => {
it("returns defaults when unset", async () => {
const settings = await getMarqueeSettings();
expect(settings.locales.de.row1).toBe(buildDefaultMarqueeSettings().locales.de.row1);
});
it("stores german-synced values", async () => {
const next = buildDefaultMarqueeSettings();
next.locales.de.row1 = "GERMAN ROW";
next.locales.en.row1 = "will be overwritten";
await updateMarqueeSettings(next);
const reloaded = await getMarqueeSettings();
expect(reloaded.locales.de.row1).toBe("GERMAN ROW");
expect(reloaded.locales.en.row1).toBe("GERMAN ROW");
expect(reloaded.locales.ar.row1).toBe("GERMAN ROW");
});
});
describe("getSiteSettingsMediaBindings", () => {
it("returns nulls when there are no usages", async () => {
const bindings = await getSiteSettingsMediaBindings();
expect(bindings).toEqual({ siteLogoLight: null, siteLogoDark: null, favicon: null, defaultOgImage: null });
});
it("maps media usages to their field bindings", async () => {
const logo = await createMediaAsset({ url: "https://cdn/logo.png" });
const favicon = await createMediaAsset({ url: "https://cdn/favicon.svg" });
await db.insert(mediaUsage).values({
assetId: logo.id,
usageType: "GENERIC",
entityType: SITE_SETTINGS_ENTITY_TYPE,
entityId: SITE_SETTINGS_ENTITY_ID,
fieldKey: SITE_SETTINGS_LOGO_LIGHT_FIELD_KEY,
});
await db.insert(mediaUsage).values({
assetId: favicon.id,
usageType: "GENERIC",
entityType: SITE_SETTINGS_ENTITY_TYPE,
entityId: SITE_SETTINGS_ENTITY_ID,
fieldKey: SITE_SETTINGS_FAVICON_FIELD_KEY,
});
const bindings = await getSiteSettingsMediaBindings();
expect(bindings.siteLogoLight?.assetId).toBe(logo.id);
expect(bindings.siteLogoLight?.url).toBe("https://cdn/logo.png");
expect(bindings.favicon?.assetId).toBe(favicon.id);
expect(bindings.favicon?.version).toMatch(/\d{4}-\d{2}-\d{2}T/); // updatedAt ISO string
expect(bindings.siteLogoDark).toBeNull();
});
});