import { act, assertEquals, cleanup, fireEvent, render } from "./setup.ts";
import ThemeToggle from "../../islands/ThemeToggle.tsx";
function resetState() {
document.documentElement.classList.remove("dark");
localStorage.removeItem("theme");
}
Deno.test({
name: "ThemeToggle - renders moon icon in light mode by default",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
assertEquals(icon.classList.contains("bi-moon-stars"), true);
assertEquals(icon.classList.contains("bi-sun"), false);
cleanup();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - renders sun icon when dark class is present",
fn() {
resetState();
document.documentElement.classList.add("dark");
let container: HTMLElement;
act(() => {
({ container } = render());
});
const icon = container!.querySelector("i")!;
assertEquals(icon.classList.contains("bi-sun"), true);
assertEquals(icon.classList.contains("bi-moon-stars"), false);
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - click adds dark class to documentElement",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
act(() => {
fireEvent.click(icon);
});
assertEquals(document.documentElement.classList.contains("dark"), true);
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - click toggles icon from moon to sun",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
assertEquals(icon.classList.contains("bi-moon-stars"), true);
act(() => {
fireEvent.click(icon);
});
const updatedIcon = container.querySelector("i")!;
assertEquals(updatedIcon.classList.contains("bi-sun"), true);
assertEquals(updatedIcon.classList.contains("bi-moon-stars"), false);
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - second click removes dark class",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
act(() => {
fireEvent.click(icon);
});
assertEquals(document.documentElement.classList.contains("dark"), true);
act(() => {
fireEvent.click(container.querySelector("i")!);
});
assertEquals(document.documentElement.classList.contains("dark"), false);
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - click persists 'dark' to localStorage",
fn() {
resetState();
const { container } = render();
act(() => {
fireEvent.click(container.querySelector("i")!);
});
assertEquals(localStorage.getItem("theme"), "dark");
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - second click persists 'light' to localStorage",
fn() {
resetState();
const { container } = render();
act(() => {
fireEvent.click(container.querySelector("i")!);
});
act(() => {
fireEvent.click(container.querySelector("i")!);
});
assertEquals(localStorage.getItem("theme"), "light");
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - click dispatches ThemeChange event",
fn() {
resetState();
let eventDetail: boolean | null = null;
const listener = (e: Event) => {
eventDetail = (e as CustomEvent).detail;
};
document.addEventListener("ThemeChange", listener);
const { container } = render();
act(() => {
fireEvent.click(container.querySelector("i")!);
});
assertEquals(eventDetail, true);
document.removeEventListener("ThemeChange", listener);
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - has hover classes for both themes",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
assertEquals(icon.className.includes("hover:text-blue-600"), true);
assertEquals(icon.className.includes("dark:hover:text-blue-400"), true);
cleanup();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - has correct title attribute in light mode",
fn() {
resetState();
const { container } = render();
const icon = container.querySelector("i")!;
assertEquals(icon.getAttribute("title"), "Switch to dark mode");
cleanup();
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "ThemeToggle - has correct title attribute in dark mode",
fn() {
resetState();
document.documentElement.classList.add("dark");
let container: HTMLElement;
act(() => {
({ container } = render());
});
const icon = container!.querySelector("i")!;
assertEquals(icon.getAttribute("title"), "Switch to light mode");
cleanup();
resetState();
},
sanitizeResources: false,
sanitizeOps: false,
});