UNPKG

@furystack/shades

Version:

A lightweight UI framework for FuryStack with JSX support

179 lines 9.08 kB
import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { Shade } from './shade.js'; import { StyleManager } from './style-manager.js'; describe('StyleManager', () => { beforeEach(() => { StyleManager.clear(); }); afterEach(() => { StyleManager.clear(); }); describe('registerComponentStyles', () => { it('should register styles for a component', () => { const result = StyleManager.registerComponentStyles('test-component', { color: 'red', padding: '10px', }); expect(result).toBe(true); expect(StyleManager.isRegistered('test-component')).toBe(true); }); it('should inject CSS into a style element', () => { StyleManager.registerComponentStyles('test-component', { color: 'red', }); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement).not.toBeNull(); expect(styleElement?.textContent).toContain('test-component'); expect(styleElement?.textContent).toContain('color: red'); }); it('should not register the same component twice', () => { const result1 = StyleManager.registerComponentStyles('test-component', { color: 'red', }); const result2 = StyleManager.registerComponentStyles('test-component', { color: 'blue', }); expect(result1).toBe(true); expect(result2).toBe(false); // Should only have the first style const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('color: red'); expect(styleElement?.textContent).not.toContain('color: blue'); }); it('should handle pseudo-selectors', () => { StyleManager.registerComponentStyles('test-button', { backgroundColor: 'blue', '&:hover': { backgroundColor: 'darkblue' }, }); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('test-button:hover'); expect(styleElement?.textContent).toContain('background-color: darkblue'); }); it('should return false for empty CSS object', () => { const result = StyleManager.registerComponentStyles('empty-component', {}); expect(result).toBe(false); expect(StyleManager.isRegistered('empty-component')).toBe(false); }); it('should add comments with component name', () => { StyleManager.registerComponentStyles('my-component', { color: 'red', }); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('/* my-component */'); }); it('should generate attribute selector for customized built-in elements', () => { StyleManager.registerComponentStyles('my-link', { color: 'blue', textDecoration: 'none', }, 'a'); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('a[is="my-link"]'); expect(styleElement?.textContent).toContain('color: blue'); expect(styleElement?.textContent).toContain('text-decoration: none'); }); it('should handle pseudo-selectors for customized built-in elements', () => { StyleManager.registerComponentStyles('my-button', { backgroundColor: 'gray', '&:hover': { backgroundColor: 'darkgray' }, '&:active': { transform: 'scale(0.98)' }, }, 'button'); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('button[is="my-button"]'); expect(styleElement?.textContent).toContain('button[is="my-button"]:hover'); expect(styleElement?.textContent).toContain('button[is="my-button"]:active'); }); }); describe('isRegistered', () => { it('should return true for registered components', () => { StyleManager.registerComponentStyles('test-component', { color: 'red' }); expect(StyleManager.isRegistered('test-component')).toBe(true); }); it('should return false for unregistered components', () => { expect(StyleManager.isRegistered('unknown-component')).toBe(false); }); }); describe('getRegisteredComponents', () => { it('should return all registered component names', () => { StyleManager.registerComponentStyles('component-a', { color: 'red' }); StyleManager.registerComponentStyles('component-b', { color: 'blue' }); const registered = StyleManager.getRegisteredComponents(); expect(registered.has('component-a')).toBe(true); expect(registered.has('component-b')).toBe(true); expect(registered.size).toBe(2); }); it('should return empty set when no components registered', () => { const registered = StyleManager.getRegisteredComponents(); expect(registered.size).toBe(0); }); }); describe('clear', () => { it('should clear all registered components', () => { StyleManager.registerComponentStyles('test-component', { color: 'red' }); expect(StyleManager.isRegistered('test-component')).toBe(true); StyleManager.clear(); expect(StyleManager.isRegistered('test-component')).toBe(false); expect(StyleManager.getRegisteredComponents().size).toBe(0); }); it('should remove style element on clear', () => { StyleManager.registerComponentStyles('test-component', { color: 'red' }); let styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement).not.toBeNull(); StyleManager.clear(); styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement).toBeNull(); }); }); describe('reusing style element', () => { it('should use the same style element for multiple components', () => { StyleManager.registerComponentStyles('component-a', { color: 'red' }); StyleManager.registerComponentStyles('component-b', { color: 'blue' }); const styleElements = document.querySelectorAll('[data-shades-styles]'); expect(styleElements.length).toBe(1); const styleElement = styleElements[0]; expect(styleElement?.textContent).toContain('component-a'); expect(styleElement?.textContent).toContain('component-b'); }); }); describe('Shade integration', () => { it('should register CSS styles when Shade component is created with css property', () => { Shade({ customElementName: 'shade-css-test-component', css: { color: 'red', padding: '10px', '&:hover': { color: 'blue' }, }, render: () => null, }); expect(StyleManager.isRegistered('shade-css-test-component')).toBe(true); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('shade-css-test-component'); expect(styleElement?.textContent).toContain('color: red'); expect(styleElement?.textContent).toContain('shade-css-test-component:hover'); }); it('should register CSS with attribute selector for customized built-in elements', () => { Shade({ customElementName: 'shade-css-test-button', elementBase: HTMLButtonElement, elementBaseName: 'button', css: { backgroundColor: 'blue', '&:hover': { backgroundColor: 'darkblue' }, }, render: () => null, }); expect(StyleManager.isRegistered('shade-css-test-button')).toBe(true); const styleElement = document.querySelector('[data-shades-styles]'); expect(styleElement?.textContent).toContain('button[is="shade-css-test-button"]'); expect(styleElement?.textContent).toContain('button[is="shade-css-test-button"]:hover'); }); it('should not register styles when Shade component has no css property', () => { Shade({ customElementName: 'shade-no-css-component', render: () => null, }); expect(StyleManager.isRegistered('shade-no-css-component')).toBe(false); }); }); }); //# sourceMappingURL=style-manager.spec.js.map