The default has moved four times, so the risk is not which way it points but that a flip silently overrides people who chose. The previous reader was getItem(KEY) === "true", which conflates "never chose" with "chose off" — under it, flipping the default re-enables the native path for everyone who had deliberately turned it off. The three cases are pinned separately so that conflation cannot come back.
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import { describe, it, expect, beforeEach, beforeAll, afterAll, vi } from "vitest";
|
|
import { get } from "svelte/store";
|
|
|
|
/**
|
|
* The stored value of the native-video preference, and what it means.
|
|
*
|
|
* The default has moved four times (see the history on `load()` in
|
|
* nativeVideo.ts), so the risk here is not "which way is it pointing" — it is
|
|
* that a flip silently overrides people who chose. The old reader was
|
|
* `getItem(KEY) === "true"`, which conflates "never chose" with "chose off";
|
|
* flipping the default under that reader re-enables the native path for
|
|
* everyone who deliberately turned it off. So the three cases are pinned
|
|
* separately rather than through the default alone.
|
|
*
|
|
* TRACES: UR-003, UR-004 | DR-188
|
|
*/
|
|
|
|
const STORAGE_KEY = "jellytau-experimental-native-video";
|
|
|
|
// jsdom here doesn't expose localStorage; stand in a minimal implementation,
|
|
// matching the viewMode/searchGroupOrder store tests.
|
|
const backing = new Map<string, string>();
|
|
const localStorageShim = {
|
|
getItem: (key: string) => backing.get(key) ?? null,
|
|
setItem: (key: string, value: string) => void backing.set(key, value),
|
|
removeItem: (key: string) => void backing.delete(key),
|
|
clear: () => backing.clear(),
|
|
};
|
|
|
|
beforeAll(() => {
|
|
vi.stubGlobal("localStorage", localStorageShim);
|
|
});
|
|
|
|
afterAll(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
async function freshStore() {
|
|
// The default is read at module init, so each case needs a fresh module.
|
|
vi.resetModules();
|
|
return await import("./nativeVideo");
|
|
}
|
|
|
|
describe("experimentalNativeVideo default", () => {
|
|
beforeEach(() => {
|
|
localStorage.clear();
|
|
});
|
|
|
|
it("defaults to ON when the user has never chosen", async () => {
|
|
const { experimentalNativeVideo } = await freshStore();
|
|
expect(get(experimentalNativeVideo)).toBe(true);
|
|
});
|
|
|
|
it("stays OFF for someone who deliberately turned it off", async () => {
|
|
// The regression the null check exists for: an explicit opt-out must
|
|
// survive the default flip, not be re-enabled by it.
|
|
localStorage.setItem(STORAGE_KEY, "false");
|
|
const { experimentalNativeVideo } = await freshStore();
|
|
expect(get(experimentalNativeVideo)).toBe(false);
|
|
});
|
|
|
|
it("stays ON for someone who deliberately turned it on", async () => {
|
|
localStorage.setItem(STORAGE_KEY, "true");
|
|
const { experimentalNativeVideo } = await freshStore();
|
|
expect(get(experimentalNativeVideo)).toBe(true);
|
|
});
|
|
|
|
it("persists an explicit choice in both directions", async () => {
|
|
const { experimentalNativeVideo } = await freshStore();
|
|
experimentalNativeVideo.set(false);
|
|
expect(localStorage.getItem(STORAGE_KEY)).toBe("false");
|
|
experimentalNativeVideo.set(true);
|
|
expect(localStorage.getItem(STORAGE_KEY)).toBe("true");
|
|
});
|
|
});
|