// @vitest-environment jsdom import { afterEach, describe, expect, it } from 'vitest'; import { applyAppearanceToDocument, normalizeAccentColor, } from '../../src/state/appearance'; describe('normalizeAccentColor', () => { it('accepts six-digit hex colors and normalizes casing', () => { expect(normalizeAccentColor(' #4F46E5 ')).toBe('#4f46e5'); }); it('rejects invalid accent colors', () => { expect(normalizeAccentColor('blue')).toBeNull(); expect(normalizeAccentColor('#123')).toBeNull(); expect(normalizeAccentColor('#12345g')).toBeNull(); }); }); describe('applyAppearanceToDocument', () => { afterEach(() => { document.documentElement.removeAttribute('data-theme'); document.documentElement.style.removeProperty('--accent'); document.documentElement.style.removeProperty('--accent-strong'); document.documentElement.style.removeProperty('--accent-soft'); document.documentElement.style.removeProperty('--accent-tint'); document.documentElement.style.removeProperty('--accent-hover'); }); it('applies the saved theme and accent variables to the root element', () => { applyAppearanceToDocument({ theme: 'dark', accentColor: '#4F46E5' }); expect(document.documentElement.getAttribute('data-theme')).toBe('dark'); expect(document.documentElement.style.getPropertyValue('--accent')).toBe('#4f46e5'); expect(document.documentElement.style.getPropertyValue('--accent-hover')).toContain('#4f46e5'); }); it('applies accent variables while clearing an explicit theme for system mode', () => { document.documentElement.setAttribute('data-theme', 'dark'); applyAppearanceToDocument({ theme: 'system', accentColor: '#10B981' }); expect(document.documentElement.hasAttribute('data-theme')).toBe(false); expect(document.documentElement.style.getPropertyValue('--accent')).toBe('#10b981'); expect(document.documentElement.style.getPropertyValue('--accent-strong')).toContain('#10b981'); expect(document.documentElement.style.getPropertyValue('--accent-soft')).toContain('#10b981'); expect(document.documentElement.style.getPropertyValue('--accent-tint')).toContain('#10b981'); expect(document.documentElement.style.getPropertyValue('--accent-hover')).toContain('#10b981'); }); it('replaces existing accent variables when the saved color changes', () => { applyAppearanceToDocument({ theme: 'light', accentColor: '#4F46E5' }); applyAppearanceToDocument({ theme: 'light', accentColor: '#EF4444' }); expect(document.documentElement.style.getPropertyValue('--accent')).toBe('#ef4444'); expect(document.documentElement.style.getPropertyValue('--accent-strong')).toContain('#ef4444'); expect(document.documentElement.style.getPropertyValue('--accent-strong')).not.toContain('#4f46e5'); expect(document.documentElement.style.getPropertyValue('--accent-soft')).toContain('#ef4444'); expect(document.documentElement.style.getPropertyValue('--accent-tint')).toContain('#ef4444'); expect(document.documentElement.style.getPropertyValue('--accent-hover')).toContain('#ef4444'); }); it('clears accent overrides when no valid accent is configured', () => { document.documentElement.style.setProperty('--accent', '#4f46e5'); applyAppearanceToDocument({ theme: 'system', accentColor: 'not-a-color' }); expect(document.documentElement.hasAttribute('data-theme')).toBe(false); expect(document.documentElement.style.getPropertyValue('--accent')).toBe(''); }); });