Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 50 additions & 46 deletions test/themes.test.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,93 @@
/**
* Tests for src/lib/themes.ts
*
* Coverage
* --------
* isThemeId -- valid IDs, invalid strings, null/undefined
* getThemeDefinition -- known theme, unknown ID returns DEFAULT_THEME
* isDarkTheme -- dark themes, light themes
* nextThemeId -- normal advance, wraps around, unknown ID
*/

import { describe, it, expect } from "vitest";
import {
THEME_OPTIONS,
DEFAULT_THEME,
isThemeId,
getThemeDefinition,
isDarkTheme,
nextThemeId,
DEFAULT_THEME,
THEME_OPTIONS,
} from "../src/lib/themes";
import type { ThemeId } from "../src/lib/themes";

describe("isThemeId", () => {
it("returns true for each valid theme ID", () => {
for (const theme of THEME_OPTIONS) {
expect(isThemeId(theme.id)).toBe(true);
}
describe("THEME_OPTIONS", () => {
it("has 4 theme options", () => {
expect(THEME_OPTIONS).toHaveLength(4);
});

it("returns false for invalid strings", () => {
expect(isThemeId("not-a-theme")).toBe(false);
expect(isThemeId("classic-dark-extra")).toBe(false);
expect(isThemeId("")).toBe(false);
it("includes classic-dark as default", () => {
expect(THEME_OPTIONS.some((t) => t.id === "classic-dark")).toBe(true);
});
});

it("returns false for null and undefined", () => {
describe("DEFAULT_THEME", () => {
it("is classic-dark", () => {
expect(DEFAULT_THEME).toBe("classic-dark");
});
});

describe("isThemeId", () => {
it("returns true for valid theme IDs", () => {
expect(isThemeId("classic-dark")).toBe(true);
expect(isThemeId("modern-light-blue")).toBe(true);
expect(isThemeId("nordic-frost")).toBe(true);
expect(isThemeId("cyberpunk-matrix")).toBe(true);
});

it("returns false for invalid theme IDs", () => {
expect(isThemeId("invalid")).toBe(false);
expect(isThemeId("")).toBe(false);
expect(isThemeId(null)).toBe(false);
expect(isThemeId(undefined)).toBe(false);
});

it("returns false for non-string", () => {
expect(isThemeId(42 as any)).toBe(false);
});
});

describe("getThemeDefinition", () => {
it("returns the correct definition for a known theme", () => {
it("returns definition for known theme", () => {
const def = getThemeDefinition("nordic-frost");
expect(def.id).toBe("nordic-frost");
expect(def.name).toBe("Nordic Frost");
expect(def.mode).toBe("dark");
});

it("returns DEFAULT_THEME definition for an unknown ID", () => {
const def = getThemeDefinition("unknown-id" as any);
expect(def.id).toBe(DEFAULT_THEME);
});

it("returns DEFAULT_THEME for empty string", () => {
const def = getThemeDefinition("" as any);
expect(def.id).toBe(DEFAULT_THEME);
it("falls back to classic-dark for unknown ID", () => {
const def = getThemeDefinition("not-a-theme" as ThemeId);
expect(def.id).toBe("classic-dark");
});
});

describe("isDarkTheme", () => {
it("returns true for dark-mode themes", () => {
it("returns true for dark mode themes", () => {
expect(isDarkTheme("classic-dark")).toBe(true);
expect(isDarkTheme("nordic-frost")).toBe(true);
expect(isDarkTheme("cyberpunk-matrix")).toBe(true);
});

it("returns false for light-mode themes", () => {
it("returns false for light mode themes", () => {
expect(isDarkTheme("modern-light-blue")).toBe(false);
});
});

describe("nextThemeId", () => {
it("advances to the next theme in order", () => {
expect(nextThemeId("classic-dark")).toBe("modern-light-blue");
expect(nextThemeId("modern-light-blue")).toBe("nordic-frost");
expect(nextThemeId("nordic-frost")).toBe("cyberpunk-matrix");
expect(nextThemeId("cyberpunk-matrix")).toBe("classic-dark");
it("cycles through all themes", () => {
const ids = THEME_OPTIONS.map((t) => t.id);
for (let i = 0; i < ids.length; i++) {
const next = nextThemeId(ids[i]);
expect(ids).toContain(next);
expect(next).not.toBe(ids[i]);
}
});

it("wraps from last theme back to first", () => {
const lastTheme = THEME_OPTIONS[THEME_OPTIONS.length - 1].id;
expect(nextThemeId(lastTheme)).toBe(THEME_OPTIONS[0].id);
it("wraps from last to first", () => {
const lastId = THEME_OPTIONS[THEME_OPTIONS.length - 1].id;
const next = nextThemeId(lastId);
expect(next).toBe(THEME_OPTIONS[0].id);
});

it("uses index 0 as fallback for unknown ID", () => {
// an unknown ID falls back to index 0, so next is index 1
expect(nextThemeId("not-a-theme" as any)).toBe(THEME_OPTIONS[1].id);
it("falls back to first theme for unknown input", () => {
const next = nextThemeId("unknown-theme" as ThemeId);
expect(THEME_OPTIONS.some((t) => t.id === next)).toBe(true);
});
});
Loading