UNPKG

@furystack/shades

Version:

A lightweight UI framework for FuryStack with JSX support

162 lines 7.4 kB
import { describe, expect, it } from 'vitest'; import { camelToKebab, generateCSS, generateCSSRule, isSelectorKey, propertiesToCSSString } from './css-generator.js'; describe('css-generator', () => { describe('camelToKebab', () => { it('should convert camelCase to kebab-case', () => { expect(camelToKebab('backgroundColor')).toBe('background-color'); expect(camelToKebab('fontSize')).toBe('font-size'); expect(camelToKebab('borderTopLeftRadius')).toBe('border-top-left-radius'); }); it('should handle single word properties', () => { expect(camelToKebab('color')).toBe('color'); expect(camelToKebab('margin')).toBe('margin'); }); it('should handle empty string', () => { expect(camelToKebab('')).toBe(''); }); }); describe('isSelectorKey', () => { it('should return true for selector keys starting with &', () => { expect(isSelectorKey('&:hover')).toBe(true); expect(isSelectorKey('&:active')).toBe(true); expect(isSelectorKey('& .className')).toBe(true); expect(isSelectorKey('& > div')).toBe(true); }); it('should return false for regular CSS property keys', () => { expect(isSelectorKey('color')).toBe(false); expect(isSelectorKey('backgroundColor')).toBe(false); expect(isSelectorKey('fontSize')).toBe(false); }); }); describe('propertiesToCSSString', () => { it('should convert CSS properties object to CSS string', () => { const result = propertiesToCSSString({ color: 'red', backgroundColor: 'blue', }); expect(result).toBe('color: red; background-color: blue'); }); it('should skip undefined and null values', () => { const result = propertiesToCSSString({ color: 'red', backgroundColor: undefined, }); expect(result).toBe('color: red'); }); it('should skip empty string values', () => { const result = propertiesToCSSString({ color: 'red', backgroundColor: '', }); expect(result).toBe('color: red'); }); it('should return empty string for empty object', () => { const result = propertiesToCSSString({}); expect(result).toBe(''); }); it('should ignore selector keys', () => { // Type assertion needed to test mixed object with selectors const mixedObject = { color: 'red', '&:hover': { color: 'blue' }, }; const result = propertiesToCSSString(mixedObject); expect(result).toBe('color: red'); }); it('should filter out non-string values', () => { // Type assertion to test edge case with non-string values const mixedObject = { color: 'red', opacity: 0.5, // number - should be filtered display: 'flex', hidden: true, // boolean - should be filtered }; const result = propertiesToCSSString(mixedObject); expect(result).toBe('color: red; display: flex'); }); }); describe('generateCSSRule', () => { it('should generate a complete CSS rule', () => { const result = generateCSSRule('my-component', { color: 'red', padding: '10px', }); expect(result).toBe('my-component { color: red; padding: 10px; }'); }); it('should return empty string for empty properties', () => { const result = generateCSSRule('my-component', {}); expect(result).toBe(''); }); }); describe('generateCSS', () => { it('should generate CSS for base properties only', () => { const result = generateCSS('my-component', { color: 'red', padding: '10px', }); expect(result).toBe('my-component { color: red; padding: 10px; }'); }); it('should generate CSS with pseudo-selectors', () => { const result = generateCSS('my-component', { color: 'red', '&:hover': { color: 'blue' }, }); expect(result).toContain('my-component { color: red; }'); expect(result).toContain('my-component:hover { color: blue; }'); }); it('should generate CSS with nested class selectors', () => { const result = generateCSS('my-component', { padding: '10px', '& .inner': { fontWeight: 'bold' }, }); expect(result).toContain('my-component { padding: 10px; }'); expect(result).toContain('my-component .inner { font-weight: bold; }'); }); it('should generate CSS with child selectors', () => { const result = generateCSS('my-component', { display: 'flex', '& > div': { margin: '5px' }, }); expect(result).toContain('my-component { display: flex; }'); expect(result).toContain('my-component > div { margin: 5px; }'); }); it('should handle multiple pseudo-selectors', () => { const result = generateCSS('my-button', { backgroundColor: 'blue', '&:hover': { backgroundColor: 'darkblue' }, '&:active': { backgroundColor: 'navy' }, '&:disabled': { opacity: '0.5' }, }); expect(result).toContain('my-button { background-color: blue; }'); expect(result).toContain('my-button:hover { background-color: darkblue; }'); expect(result).toContain('my-button:active { background-color: navy; }'); expect(result).toContain('my-button:disabled { opacity: 0.5; }'); }); it('should handle empty css object', () => { const result = generateCSS('my-component', {}); expect(result).toBe(''); }); it('should handle css object with only selectors', () => { const result = generateCSS('my-component', { '&:hover': { color: 'blue' }, }); expect(result).toBe('my-component:hover { color: blue; }'); }); it('should skip selector keys with non-object values', () => { // Type assertion to test edge case with invalid selector values const cssObject = { color: 'red', '&:hover': 'invalid', // string instead of object - should be skipped '&:active': null, // null - should be skipped '&:focus': { backgroundColor: 'blue' }, // valid - should be included }; const result = generateCSS('my-component', cssObject); expect(result).toContain('my-component { color: red; }'); expect(result).toContain('my-component:focus { background-color: blue; }'); expect(result).not.toContain('invalid'); expect(result).not.toContain(':hover'); expect(result).not.toContain(':active'); }); }); }); //# sourceMappingURL=css-generator.spec.js.map