Files
HIPCTF2/tests/frontend/bootstrap-theme.spec.ts
T
2026-07-22 13:41:06 +00:00

105 lines
3.7 KiB
TypeScript

import {
applyThemeToCss,
clearThemeCss,
Theme,
} from '../../frontend/src/app/core/services/bootstrap.types';
function makeClassicTheme(): Theme {
return {
id: 'classic',
name: 'Classic',
tokens: {
primary: '#3b82f6',
secondary: '#64748b',
accent: '#f59e0b',
surface: '#ffffff',
text: '#0f172a',
success: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
fontFamily: 'system-ui, sans-serif',
radii: { sm: '4px', md: '8px', lg: '16px' },
spacingScale: [4, 8, 12, 16, 24, 32, 48],
},
};
}
function makeMonochromeTheme(): Theme {
return {
id: 'monochrome',
name: 'Monochrome',
tokens: {
primary: '#000000',
secondary: '#525252',
accent: '#a3a3a3',
surface: '#ffffff',
text: '#0a0a0a',
success: '#404040',
warning: '#737373',
danger: '#171717',
fontFamily: 'system-ui, sans-serif',
radii: { sm: '0', md: '0', lg: '0' },
spacingScale: [4, 8, 12, 16, 24, 32, 48],
},
};
}
describe('applyThemeToCss', () => {
beforeEach(() => {
clearThemeCss();
});
it('writes all CSS custom properties from the Classic theme tokens', () => {
applyThemeToCss(makeClassicTheme());
const root = document.documentElement.style;
expect(root.getPropertyValue('--color-primary')).toBe('#3b82f6');
expect(root.getPropertyValue('--color-secondary')).toBe('#64748b');
expect(root.getPropertyValue('--color-accent')).toBe('#f59e0b');
expect(root.getPropertyValue('--color-surface')).toBe('#ffffff');
expect(root.getPropertyValue('--color-text')).toBe('#0f172a');
expect(root.getPropertyValue('--color-success')).toBe('#10b981');
expect(root.getPropertyValue('--color-warning')).toBe('#f59e0b');
expect(root.getPropertyValue('--color-danger')).toBe('#ef4444');
expect(root.getPropertyValue('--font-family')).toBe('system-ui, sans-serif');
expect(root.getPropertyValue('--radius-sm')).toBe('4px');
expect(root.getPropertyValue('--radius-md')).toBe('8px');
expect(root.getPropertyValue('--radius-lg')).toBe('16px');
});
it('returns false and is a no-op when the theme is missing tokens', () => {
expect(applyThemeToCss(null)).toBe(false);
expect(applyThemeToCss(undefined)).toBe(false);
expect(applyThemeToCss({ id: 'x', name: 'X' } as unknown as Theme)).toBe(false);
const root = document.documentElement.style;
expect(root.getPropertyValue('--color-primary')).toBe('');
expect(root.getPropertyValue('--radius-md')).toBe('');
});
it('replaces Classic tokens with Monochrome tokens when re-applied', () => {
applyThemeToCss(makeClassicTheme());
applyThemeToCss(makeMonochromeTheme());
const root = document.documentElement.style;
expect(root.getPropertyValue('--color-primary')).toBe('#000000');
expect(root.getPropertyValue('--color-text')).toBe('#0a0a0a');
expect(root.getPropertyValue('--radius-md')).toBe('0');
expect(root.getPropertyValue('--radius-sm')).toBe('0');
expect(root.getPropertyValue('--radius-lg')).toBe('0');
});
it('treats the zero-valued Monochrome radius as a valid applied value', () => {
applyThemeToCss(makeMonochromeTheme());
expect(document.documentElement.style.getPropertyValue('--radius-md')).toBe('0');
});
});
describe('clearThemeCss', () => {
it('removes every theme CSS custom property set by applyThemeToCss', () => {
applyThemeToCss(makeClassicTheme());
clearThemeCss();
const root = document.documentElement.style;
expect(root.getPropertyValue('--color-primary')).toBe('');
expect(root.getPropertyValue('--color-text')).toBe('');
expect(root.getPropertyValue('--radius-md')).toBe('');
expect(root.getPropertyValue('--font-family')).toBe('');
});
});