UNPKG

@furystack/shades

Version:

A lightweight UI framework for FuryStack with JSX support

230 lines (186 loc) 8.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) }) }) })