Files
sofarr/tests/frontend/ui/theme.test.js
T
gronod 95bd703b26
Docs Check / Markdown lint (push) Successful in 1m14s
Build and Push Docker Image / build (push) Successful in 1m52s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m55s
CI / Security audit (push) Successful in 2m25s
Docs Check / Mermaid diagram parse check (push) Successful in 3m6s
CI / Swagger Validation & Coverage (push) Successful in 3m22s
CI / Tests & coverage (push) Successful in 3m45s
chore: bump version to 1.7.22 and update CHANGELOG, tests and docs
2026-05-27 17:42:41 +01:00

95 lines
3.3 KiB
JavaScript

// Copyright (c) 2026 Gordon Bolton. MIT License.
/**
* @vitest-environment jsdom
* Tests for client/src/ui/theme.js
*
* Verifies DOM actions for theme switcher button clicks, attributes, and storage calls.
*/
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { initThemeSwitcher, setTheme } from '../../../client/src/ui/theme.js';
import * as storage from '../../../client/src/utils/storage.js';
vi.mock('../../../client/src/utils/storage.js', () => {
let store = {};
return {
getTheme: vi.fn(() => store.theme || 'light'),
saveTheme: vi.fn((theme) => { store.theme = theme; })
};
});
describe('theme switcher', () => {
let lightBtn, darkBtn, monoBtn;
beforeEach(() => {
vi.clearAllMocks();
document.documentElement.removeAttribute('data-theme');
// Create mock theme buttons
document.body.innerHTML = `
<div class="theme-switcher">
<button class="theme-btn" data-theme="light">Light</button>
<button class="theme-btn" data-theme="dark">Dark</button>
<button class="theme-btn" data-theme="mono">Mono</button>
</div>
`;
lightBtn = document.querySelector('[data-theme="light"]');
darkBtn = document.querySelector('[data-theme="dark"]');
monoBtn = document.querySelector('[data-theme="mono"]');
});
it('initThemeSwitcher sets active class based on saved theme on load', () => {
vi.spyOn(storage, 'getTheme').mockReturnValue('dark');
initThemeSwitcher();
expect(storage.getTheme).toHaveBeenCalled();
expect(darkBtn.classList.contains('active')).toBe(true);
expect(lightBtn.classList.contains('active')).toBe(false);
expect(monoBtn.classList.contains('active')).toBe(false);
});
it('initThemeSwitcher defaults to light theme if no theme is saved', () => {
vi.spyOn(storage, 'getTheme').mockReturnValue(null);
initThemeSwitcher();
expect(lightBtn.classList.contains('active')).toBe(true);
expect(darkBtn.classList.contains('active')).toBe(false);
});
it('clicking theme button switches the document theme and persists choice', () => {
initThemeSwitcher();
// Initial active button should be light
expect(lightBtn.classList.contains('active')).toBe(true);
// Click Dark
darkBtn.click();
expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
expect(storage.saveTheme).toHaveBeenCalledWith('dark');
expect(darkBtn.classList.contains('active')).toBe(true);
expect(lightBtn.classList.contains('active')).toBe(false);
// Click Mono
monoBtn.click();
expect(document.documentElement.getAttribute('data-theme')).toBe('mono');
expect(storage.saveTheme).toHaveBeenCalledWith('mono');
expect(monoBtn.classList.contains('active')).toBe(true);
expect(darkBtn.classList.contains('active')).toBe(false);
});
it('setTheme directly sets document attribute and updates button classes if present', () => {
initThemeSwitcher(); // binds buttons
setTheme('mono');
expect(document.documentElement.getAttribute('data-theme')).toBe('mono');
expect(storage.saveTheme).toHaveBeenCalledWith('mono');
expect(monoBtn.classList.contains('active')).toBe(true);
expect(lightBtn.classList.contains('active')).toBe(false);
});
});