85 lines
3.5 KiB
TypeScript
85 lines
3.5 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { Browser } from "happy-dom";
|
|
import { renderThemeRuntime, resolveThemeConfig } from "../src/theme.ts";
|
|
|
|
test("shared preferences replace stale host cookies and update another open app", async () => {
|
|
const browser = new Browser({ settings: { disableCSSFileLoading: true } });
|
|
try {
|
|
const first = browser.newPage();
|
|
first.url = "https://account.example.com/";
|
|
const second = browser.newPage();
|
|
second.url = "https://link.example.com/";
|
|
const a = first.mainFrame.window;
|
|
const b = second.mainFrame.window;
|
|
// Happy DOM coalesces equal-name host/domain cookies. Model their distinct
|
|
// browser storage keys so the legacy-shadow migration is exercised.
|
|
const jar = new Map<
|
|
string,
|
|
{ name: string; value: string; domain: string; hostOnly: boolean }
|
|
>();
|
|
function cookies(win: typeof a) {
|
|
Object.defineProperty(win.document, "cookie", {
|
|
get() {
|
|
return [...jar.values()]
|
|
.filter((c) =>
|
|
c.hostOnly
|
|
? c.domain === win.location.hostname
|
|
: win.location.hostname === c.domain ||
|
|
win.location.hostname.endsWith("." + c.domain),
|
|
)
|
|
.map((c) => `${c.name}=${c.value}`)
|
|
.join("; ");
|
|
},
|
|
set(raw: string) {
|
|
const [pair, ...options] = raw.split(";");
|
|
const split = pair!.indexOf("=");
|
|
const name = pair!.slice(0, split),
|
|
value = pair!.slice(split + 1);
|
|
const domainOption = options.find((v) => v.trim().toLowerCase().startsWith("domain="));
|
|
const domain = domainOption
|
|
? domainOption.trim().slice(7).replace(/^\./, "")
|
|
: win.location.hostname;
|
|
const key = `${name}|${domain}`;
|
|
if (options.some((v) => v.trim().toLowerCase() === "max-age=0")) jar.delete(key);
|
|
else jar.set(key, { name, value, domain, hostOnly: !domainOption });
|
|
},
|
|
});
|
|
}
|
|
cookies(a);
|
|
cookies(b);
|
|
a.document.cookie = "wrn-theme=light;path=/";
|
|
b.document.cookie = "wrn-theme=light;path=/";
|
|
a.document.cookie = "wrn-theme=dark;path=/;domain=.example.com;secure";
|
|
a.document.cookie = "wrn-accent=rose;path=/;domain=.example.com;secure";
|
|
const js = renderThemeRuntime(
|
|
resolveThemeConfig(
|
|
{ palette: "emerald" },
|
|
{ defaults: { domain: ".example.com", secure: true } },
|
|
),
|
|
);
|
|
for (const win of [a, b]) {
|
|
win.document.documentElement.setAttribute("data-theme", "light");
|
|
win.document.documentElement.setAttribute("data-accent", "emerald");
|
|
win.eval(js);
|
|
expect(win.document.documentElement.getAttribute("data-theme")).toBe("dark");
|
|
expect(win.document.cookie.match(/wrn-theme=/g)?.length).toBe(1);
|
|
}
|
|
a.eval(
|
|
'wrnTheme.set("light");wrnAccent.set("violet");wrnCookies.set("wrn-lang","hi","language")',
|
|
);
|
|
expect(b.document.cookie).toContain("wrn-theme-mode=manual");
|
|
b.dispatchEvent(new b.Event("focus"));
|
|
expect(b.document.documentElement.getAttribute("data-theme")).toBe("light");
|
|
expect(b.document.documentElement.getAttribute("data-accent")).toBe("violet");
|
|
expect(b.document.cookie).toContain("wrn-lang=hi");
|
|
a.eval("wrnTheme.followSystem()");
|
|
expect(b.document.cookie).toContain("wrn-theme-mode=system");
|
|
const outsider = browser.newPage();
|
|
outsider.url = "https://unrelated.example.net/";
|
|
cookies(outsider.mainFrame.window);
|
|
expect(outsider.mainFrame.window.document.cookie).toBe("");
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
});
|