Files
Checkmate/server/test/unit/controllers/statusPageThemeFlag.test.ts
T
gorkem-bwl d80d939bd8 test(status-page): cover theme-flag helpers and document remaining caveats
Address review follow-ups on PR #3568:

- Extract the controller's withoutThemeFields and applyDefaultTheme helpers from a private class field into a standalone module (controllers/statusPageThemeFlag.ts) so they can be tested without a controller harness; the controller is now a one-line consumer
- Add 9 unit tests covering both helpers (test/unit/controllers/statusPageThemeFlag.test.ts): no-mutation guarantees, partial inputs, all-fields-preserved verbatim, override-with-defaults semantics, and "page has no theme set yet" — the flag-off path is now exercised in both directions
- Expand the comment over withoutThemeFields to spell out why the strip is silent rather than a 400: this is an ops kill switch, not API semantics; clients shouldn't need to know whether themes are disabled today

Two caveats called out in review that this commit does NOT change:
- Mongoose `default:` directives only inject during hydration, not on partial updates. Legacy documents updated with `findOneAndUpdate` still won't have `theme` / `themeMode` written to Mongo. They render as defaults on read because the schema injects them — functionally equivalent, but the DB will hold a mix of present and absent fields indefinitely. Acceptable per the original commit intent.
- docs/plans/status-page-themes.md (304 lines) covers both backend and frontend work for the themes feature. It lives in this PR as the design artefact that drove both branches; moving it for purity would break the "where did this come from?" trail. Leaving it in.
2026-04-27 19:26:16 -04:00

107 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "@jest/globals";
import { applyDefaultTheme, withoutThemeFields } from "../../../src/controllers/statusPageThemeFlag.ts";
import { DEFAULT_STATUS_PAGE_THEME, DEFAULT_STATUS_PAGE_THEME_MODE } from "../../../src/types/statusPage.ts";
import type { StatusPage } from "../../../src/types/index.ts";
const makeStatusPage = (overrides?: Partial<StatusPage>): StatusPage =>
({
id: "sp-1",
teamId: "team-1",
userId: "user-1",
url: "my-status-page",
companyName: "Test Co",
monitors: ["mon-1"],
theme: "modern",
themeMode: "dark",
createdAt: "2026-01-01T00:00:00Z",
updatedAt: "2026-01-01T00:00:00Z",
...overrides,
}) as StatusPage;
describe("statusPageThemeFlag", () => {
describe("withoutThemeFields", () => {
it("removes theme and themeMode from a body that has them", () => {
const body = { companyName: "Co", theme: "modern", themeMode: "dark" };
const result = withoutThemeFields(body);
expect(result).toEqual({ companyName: "Co" });
});
it("is a no-op when neither field is present", () => {
const body = { companyName: "Co", url: "page" };
const result = withoutThemeFields(body);
expect(result).toEqual({ companyName: "Co", url: "page" });
});
it("removes only the theme fields when one is present", () => {
const body = { companyName: "Co", theme: "bold" };
const result = withoutThemeFields(body);
expect(result).toEqual({ companyName: "Co" });
});
it("does not mutate the input body", () => {
const body = { companyName: "Co", theme: "modern", themeMode: "dark" };
withoutThemeFields(body);
expect(body).toEqual({ companyName: "Co", theme: "modern", themeMode: "dark" });
});
it("preserves all other fields verbatim", () => {
const body = {
companyName: "Co",
monitors: ["m-1", "m-2"],
isPublished: true,
showCharts: false,
color: "#13715B",
theme: "editorial",
themeMode: "light",
};
const result = withoutThemeFields(body);
expect(result).toEqual({
companyName: "Co",
monitors: ["m-1", "m-2"],
isPublished: true,
showCharts: false,
color: "#13715B",
});
});
});
describe("applyDefaultTheme", () => {
it("overwrites theme and themeMode with the canonical defaults", () => {
const sp = makeStatusPage({ theme: "modern", themeMode: "dark" });
const result = applyDefaultTheme(sp);
expect(result.theme).toBe(DEFAULT_STATUS_PAGE_THEME);
expect(result.themeMode).toBe(DEFAULT_STATUS_PAGE_THEME_MODE);
});
it("leaves all other fields untouched", () => {
const sp = makeStatusPage({
companyName: "Test Co",
url: "my-page",
monitors: ["mon-1", "mon-2"],
isPublished: true,
color: "#13715B",
});
const result = applyDefaultTheme(sp);
expect(result.companyName).toBe("Test Co");
expect(result.url).toBe("my-page");
expect(result.monitors).toEqual(["mon-1", "mon-2"]);
expect(result.isPublished).toBe(true);
expect(result.color).toBe("#13715B");
});
it("does not mutate the input status page", () => {
const sp = makeStatusPage({ theme: "modern", themeMode: "dark" });
applyDefaultTheme(sp);
expect(sp.theme).toBe("modern");
expect(sp.themeMode).toBe("dark");
});
it("works on a status page that has no theme set yet", () => {
const sp = makeStatusPage({ theme: undefined, themeMode: undefined });
const result = applyDefaultTheme(sp);
expect(result.theme).toBe(DEFAULT_STATUS_PAGE_THEME);
expect(result.themeMode).toBe(DEFAULT_STATUS_PAGE_THEME_MODE);
});
});
});