Skip to content

Commit

Permalink
add tests for useDarkMode
Browse files Browse the repository at this point in the history
  • Loading branch information
konstantin-lukas committed Sep 8, 2024
1 parent 86bfac7 commit 6dbc58b
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/hooks/useDarkMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function useDarkMode({

return {
setTheme: (selectedTheme: "light" | "dark") => setTheme(selectedTheme),
toggleTheme: () => { setTheme(prevState => prevState === "light" ? "dark" : "light"); },
toggleTheme: () => setTheme(prevState => prevState === "light" ? "dark" : "light"),
theme,
};
}
Expand Down
128 changes: 128 additions & 0 deletions tests/useDarkMode.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { act, renderHook } from "@testing-library/react";
import { useDarkMode } from "../src";


describe("useDarkMode", () => {
let triggerChange: (e: { matches: boolean }) => void;
const defineMock = (defTheme: boolean) => {
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation(() => ({
matches: defTheme,
addEventListener: (_: string, callback: (e: { matches: boolean }) => void) => {
triggerChange = callback;
},
removeEventListener: jest.fn(),
})),
});
};

afterEach(() => {
localStorage.clear();
jest.clearAllMocks();
});

test("should use the current preferred scheme (light) by default", async () => {
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode());
});
expect(result.current.theme).toBe("light");
});

test("should use the current preferred scheme (dark) by default", async () => {
defineMock(true);
const { result } = await act(async () => {
return renderHook(() => useDarkMode());
});
expect(result.current.theme).toBe("dark");
});

test("should ignore the preferred theme if a value exists in local storage", async () => {
localStorage.setItem("anzol-dark-mode-hook", "light");
defineMock(true);
const { result } = await act(async () => {
return renderHook(() => useDarkMode());
});
expect(result.current.theme).toBe("light");
});

test("should ignore the preferred theme if a value exists in local storage unless configured otherwise", async () => {
localStorage.setItem("anzol-dark-mode-hook", "light");
defineMock(true);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ persistStateInLocalStorage: false }));
});
expect(result.current.theme).toBe("dark");
});

test("should ignore the value stored in local storage and used a specified default if configured to do so", async () => {
localStorage.setItem("anzol-dark-mode-hook", "light");
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ persistStateInLocalStorage: false, defaultTheme: "dark" }));
});
expect(result.current.theme).toBe("dark");
});

test("should ignore the selected default theme if a value exists in local storage", async () => {
localStorage.setItem("anzol-dark-mode-hook", "light");
defineMock(true);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ defaultTheme: "dark" }));
});
expect(result.current.theme).toBe("light");
});

test("should update its state when the preferred scheme changes", async () => {
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode());
});
expect(result.current.theme).toBe("light");
act(() => triggerChange({ matches: true }));
expect(result.current.theme).toBe("dark");
act(() => triggerChange({ matches: false }));
expect(result.current.theme).toBe("light");
});

test("should not update its state when the preferred scheme changes if configured to do so", async () => {
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ updateOnPreferredSchemeChange: false }));
});
expect(result.current.theme).toBe("light");
act(() => triggerChange({ matches: true }));
expect(result.current.theme).toBe("light");
act(() => triggerChange({ matches: false }));
expect(result.current.theme).toBe("light");
});

test("should allow setting the theme", async () => {
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ updateOnPreferredSchemeChange: false }));
});
expect(result.current.theme).toBe("light");
for (let i = 0; i < 2; i++) {
act(() => result.current.setTheme("dark"));
expect(result.current.theme).toBe("dark");
}
for (let i = 0; i < 2; i++) {
act(() => result.current.setTheme("light"));
expect(result.current.theme).toBe("light");
}
});

test("should allow toggling the theme", async () => {
defineMock(false);
const { result } = await act(async () => {
return renderHook(() => useDarkMode({ updateOnPreferredSchemeChange: false }));
});
expect(result.current.theme).toBe("light");
for (let i = 0; i < 5; i++) {
act(() => result.current.toggleTheme());
expect(result.current.theme).toBe(i % 2 === 0 ? "dark" : "light");
}
});
});
2 changes: 1 addition & 1 deletion tests/usePreferredScheme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("usePreferredScheme", () => {
expect(result.current).toBe("light");
});

test("should change use the current preferred scheme by default", async () => {
test("should use the current preferred scheme by default", async () => {
defineMock(true);
const { result } = await act(async () => {
return renderHook(() => usePreferredScheme());
Expand Down

0 comments on commit 6dbc58b

Please sign in to comment.