- Spotify playlist, library, album and artist browsing with in-app playback - Song, playlist and album downloads via spotdl with YouTube and Bandcamp fallbacks - Electron desktop app (castLabs Widevine) with a permanent sidebar layout - Linux and Windows packaging scripts
118 lines
3.9 KiB
TypeScript
118 lines
3.9 KiB
TypeScript
import { switchToDarkMode, switchToLightMode, switchToAutoMode, getCurrentThemeMode } from "./themeMode";
|
|
|
|
function createMediaQueryList(initialMatches: boolean, query = "(prefers-color-scheme: dark)") {
|
|
let currentMatches = initialMatches;
|
|
const mql: Partial<MediaQueryList> = {
|
|
get matches() {
|
|
return currentMatches;
|
|
},
|
|
media: query,
|
|
onchange: null,
|
|
addListener: () => {},
|
|
removeListener: () => {},
|
|
addEventListener: () => {},
|
|
removeEventListener: () => {},
|
|
dispatchEvent: () => false,
|
|
};
|
|
return Object.assign(mql, {
|
|
setMatches(newMatches: boolean) {
|
|
currentMatches = newMatches;
|
|
},
|
|
}) as MediaQueryList & { setMatches: (matches: boolean) => void };
|
|
}
|
|
|
|
describe("themeMode helper", () => {
|
|
let originalMatchMedia: typeof window.matchMedia;
|
|
|
|
beforeAll(() => {
|
|
originalMatchMedia = window.matchMedia;
|
|
});
|
|
|
|
afterAll(() => {
|
|
window.matchMedia = originalMatchMedia;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
document.body.className = "";
|
|
});
|
|
|
|
it("should add the 'dark' class when switching to dark mode", () => {
|
|
switchToDarkMode();
|
|
expect(document.body.classList.contains("dark")).toBeTrue();
|
|
});
|
|
|
|
it("should remove the 'dark' class when switching to light mode", () => {
|
|
document.body.classList.add("dark");
|
|
switchToLightMode();
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
});
|
|
|
|
it("should apply dark mode automatically when user prefers dark", () => {
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(true, query);
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeTrue();
|
|
});
|
|
|
|
it("should apply light mode automatically when user does not prefer dark", () => {
|
|
document.body.classList.add("dark");
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(false, query);
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
});
|
|
|
|
it("should update theme when system preference changes in auto mode upon re-calling switchToAutoMode", () => {
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(false, query);
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(true, query);
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeTrue();
|
|
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(false, query);
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
});
|
|
|
|
it("should update theme when media query change event is triggered", () => {
|
|
const dummyMediaQuery = createMediaQueryList(false);
|
|
window.matchMedia = (query: string): MediaQueryList => dummyMediaQuery;
|
|
|
|
switchToAutoMode();
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
|
|
dummyMediaQuery.setMatches(true);
|
|
if (dummyMediaQuery.onchange) {
|
|
dummyMediaQuery.onchange({ matches: true } as MediaQueryListEvent);
|
|
}
|
|
expect(document.body.classList.contains("dark")).toBeTrue();
|
|
|
|
dummyMediaQuery.setMatches(false);
|
|
if (dummyMediaQuery.onchange) {
|
|
dummyMediaQuery.onchange({ matches: false } as MediaQueryListEvent);
|
|
}
|
|
expect(document.body.classList.contains("dark")).toBeFalse();
|
|
});
|
|
|
|
it("getCurrentThemeMode should return 'dark' when dark mode is set manually", () => {
|
|
switchToDarkMode();
|
|
expect(getCurrentThemeMode()).toBe("dark");
|
|
});
|
|
|
|
it("getCurrentThemeMode should return 'light' when light mode is set manually", () => {
|
|
switchToLightMode();
|
|
expect(getCurrentThemeMode()).toBe("light");
|
|
});
|
|
|
|
it("getCurrentThemeMode should return 'auto' when auto mode is enabled", () => {
|
|
window.matchMedia = (query: string): MediaQueryList =>
|
|
createMediaQueryList(true, query);
|
|
switchToAutoMode();
|
|
expect(getCurrentThemeMode()).toBe("auto");
|
|
});
|
|
}); |