Files
mangabaka-seeder/test/dark-reader.test.ts
T
Lucas WintherandClaude Opus 5.5 a64b2009df fix(web): use the page's own dark theme when Dark Reader is on
Dark Reader marks <html data-darkreader-scheme="dark">; the page then sets
data-theme="dark" and adds <meta name="darkreader-lock"> so Dark Reader
removes its generated styles.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 11:07:43 +02:00

73 lines
2.5 KiB
TypeScript

import { expect, test } from "bun:test";
import { followDarkReader, type ThemeDocument } from "../src/web/dark-reader";
type Fake = ThemeDocument & { attrs: Map<string, string>; metas: string[]; fire(): void; disconnected: boolean };
function fakeDocument(scheme?: string): Fake {
const attrs = new Map<string, string>();
if (scheme) attrs.set("data-darkreader-scheme", scheme);
const metas: string[] = [];
let callback = () => {};
const doc: Fake = {
attrs,
metas,
disconnected: false,
fire: () => callback(),
documentElement: {
getAttribute: (name) => attrs.get(name) ?? null,
setAttribute: (name, value) => void attrs.set(name, value),
},
addLockMeta: () => void metas.push("darkreader-lock"),
observeRoot: (onChange) => {
callback = onChange;
return () => {
doc.disconnected = true;
};
},
};
return doc;
}
test("Dark Reader already dark at start: our dark theme, and Dark Reader is told to stand down", () => {
const doc = fakeDocument("dark");
followDarkReader(doc);
expect(doc.attrs.get("data-theme")).toBe("dark");
expect(doc.metas).toEqual(["darkreader-lock"]);
expect(doc.disconnected).toBe(true);
});
test("Dark Reader turning on after load is followed once", () => {
const doc = fakeDocument();
followDarkReader(doc);
expect(doc.attrs.has("data-theme")).toBe(false);
doc.attrs.set("data-darkreader-scheme", "dark");
doc.fire();
expect(doc.attrs.get("data-theme")).toBe("dark");
expect(doc.disconnected).toBe(true);
doc.fire();
expect(doc.metas).toEqual(["darkreader-lock"]);
});
test("no Dark Reader, or its dimmed (light) scheme: the page keeps following the system", () => {
for (const doc of [fakeDocument(), fakeDocument("dimmed")]) {
followDarkReader(doc);
doc.fire();
expect(doc.attrs.has("data-theme")).toBe(false);
expect(doc.metas).toEqual([]);
expect(doc.disconnected).toBe(false);
}
});
test("the forced dark theme uses exactly the system dark tokens", async () => {
const css = await Bun.file("src/web/styles.css").text();
const block = (start: string) => {
const at = css.indexOf(start);
expect(at).toBeGreaterThan(-1);
const open = css.indexOf("{", css.indexOf(".mbseed-page", at));
return css.slice(open + 1, css.indexOf("}", open)).replace(/\s+/g, " ").trim();
};
const system = block("@media (prefers-color-scheme: dark)");
expect(system).toContain("--mb-page: #2a2520;");
expect(block(':root[data-theme="dark"]')).toBe(system);
});