Files
calendar/apps/web/lib/pages/document/_applyThemeForDocument.test.ts
T
096026b92a fix: Vitest is being bundled to client + bump lingo.dev version (#23502)
* Fix vitest on prod

* Also extract out verify-email for the purpose of stopping test bundling

* Address NIT

* Fix lingo.dev imports

---------

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2025-09-02 01:58:08 +01:00

158 lines
4.5 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { applyTheme } from "./_applyThemeForDocument";
describe("applyTheme", () => {
let reconstructedFn: () => void;
let mockLocalStorage: Storage;
let mockRequestAnimationFrame: typeof window.requestAnimationFrame;
let mockDocument: Document;
let addedClasses: string[] = [];
beforeEach(() => {
// Create the function from stringified version
const stringifiedFunction = applyTheme.toString();
reconstructedFn = new Function(`return ${stringifiedFunction}`)();
// Mock localStorage
mockLocalStorage = {
getItem: vi.fn(() => null),
setItem: vi.fn(),
removeItem: vi.fn(),
clear: vi.fn(),
key: vi.fn(() => null),
length: 0,
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.localStorage = mockLocalStorage;
// Mock requestAnimationFrame
mockRequestAnimationFrame = vi.fn((cb) => {
cb(0);
return 0;
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.window = { location: { pathname: "/" } };
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.requestAnimationFrame = mockRequestAnimationFrame;
// Mock document
addedClasses = [];
mockDocument = {
body: {
classList: {
add: vi.fn((className: string) => {
addedClasses.push(className);
}),
},
},
} as unknown as Document;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.document = mockDocument;
// Mock console.error
global.console.error = vi.fn();
});
afterEach(() => {
vi.clearAllMocks();
});
it("should be reconstructable from toString() and executable", () => {
expect(() => reconstructedFn()).not.toThrow();
});
it("should not add any theme when no app-theme is found", () => {
reconstructedFn();
expect(mockRequestAnimationFrame).not.toHaveBeenCalled();
expect(addedClasses).toHaveLength(0);
});
it("should handle localStorage errors gracefully", () => {
// Make localStorage throw an error
mockLocalStorage.getItem = vi.fn(() => {
throw new Error("localStorage not available");
});
mockLocalStorage.key = vi.fn(() => {
throw new Error("localStorage not available");
});
Object.defineProperty(mockLocalStorage, "length", {
get: () => {
throw new Error("localStorage not available");
},
});
expect(() => reconstructedFn()).not.toThrow();
expect(addedClasses).toHaveLength(0);
});
it("should apply booking theme when app-theme exists and on booking page", () => {
const username = "testuser";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.window.location.pathname = `/${username}/meeting`;
mockLocalStorage.key = vi.fn((index: number) => {
if (index === 0) return `booking-theme:${username}`;
return null;
});
mockLocalStorage.getItem = vi.fn((key: string) => {
if (key === "app-theme") return "light";
if (key === `booking-theme:${username}`) return "dark";
return null;
});
Object.defineProperty(mockLocalStorage, "length", {
get: () => 1,
configurable: true,
});
reconstructedFn();
expect(addedClasses).toContain("dark");
});
it("should apply app theme when not on booking page", () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.window.location.pathname = "/some-other-page";
mockLocalStorage.key = vi.fn((index: number) => {
if (index === 0) return "booking-theme:testuser";
return null;
});
mockLocalStorage.getItem = vi.fn((key: string) => {
if (key === "app-theme") return "light";
if (key === "booking-theme:testuser") return "dark";
return null;
});
Object.defineProperty(mockLocalStorage, "length", {
get: () => 1,
configurable: true,
});
reconstructedFn();
expect(addedClasses).toContain("light");
});
it("should apply app theme when app-theme exists but no booking theme", () => {
mockLocalStorage.getItem = vi.fn((key: string) => {
if (key === "app-theme") return "dark";
return null;
});
Object.defineProperty(mockLocalStorage, "length", {
get: () => 0,
configurable: true,
});
reconstructedFn();
expect(addedClasses).toContain("dark");
});
});