UNPKG

@furystack/shades-common-components

Version:

Common UI components for FuryStack Shades

107 lines 4.66 kB
import { createInjector } from '@furystack/inject'; import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'; import { usingAsync } from '@furystack/utils'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { cssVariableTheme } from '../services/css-variable-theme.js'; import { Fab } from './fab.js'; describe('Fab', () => { beforeEach(() => { document.body.innerHTML = '<div id="root"></div>'; }); afterEach(() => { document.body.innerHTML = ''; }); const renderFab = async (children) => { const injector = createInjector(); const root = document.getElementById('root'); initializeShadeRoot({ injector, rootElement: root, jsxElement: createComponent(Fab, null, children), }); await flushUpdates(); return { injector, fab: root.querySelector('button[is="shade-fab"]'), [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](), }; }; describe('rendering', () => { it('should render a button element', async () => { await usingAsync(await renderFab(), async ({ fab }) => { expect(fab).toBeTruthy(); expect(fab.tagName.toLowerCase()).toBe('button'); expect(fab.getAttribute('is')).toBe('shade-fab'); }); }); }); describe('positioning', () => { it('should have fixed positioning', async () => { await usingAsync(await renderFab(), async ({ fab }) => { const computedStyle = window.getComputedStyle(fab); expect(computedStyle.position).toBe('fixed'); }); }); it('should be positioned at bottom-right corner', async () => { await usingAsync(await renderFab(), async ({ fab }) => { const computedStyle = window.getComputedStyle(fab); expect(computedStyle.bottom).toBe(cssVariableTheme.spacing.xl); expect(computedStyle.right).toBe(cssVariableTheme.spacing.xl); }); }); }); describe('children', () => { it('should render text children', async () => { await usingAsync(await renderFab(['+']), async ({ fab }) => { expect(fab.textContent).toContain('+'); }); }); it('should render element children', async () => { await usingAsync(await renderFab([createComponent("span", null, "\uD83D\uDE80")]), async ({ fab }) => { expect(fab.textContent).toContain('🚀'); }); }); }); describe('styling', () => { it('should have circular shape', async () => { await usingAsync(await renderFab(), async () => { const styleEl = document.querySelector('style[data-shades-styles]'); const cssText = styleEl?.textContent ?? ''; expect(cssText).toContain(`border-radius: ${cssVariableTheme.shape.borderRadius.full}`); }); }); it('should have fixed dimensions', async () => { await usingAsync(await renderFab(), async ({ fab }) => { const computedStyle = window.getComputedStyle(fab); expect(computedStyle.width).toBe('64px'); expect(computedStyle.height).toBe('64px'); }); }); it('should center content with flexbox', async () => { await usingAsync(await renderFab(), async ({ fab }) => { const computedStyle = window.getComputedStyle(fab); expect(computedStyle.display).toBe('flex'); expect(computedStyle.justifyContent).toBe('center'); expect(computedStyle.alignItems).toBe('center'); }); }); }); describe('button functionality', () => { it('should trigger onclick handler when clicked', async () => { await usingAsync(createInjector(), async (injector) => { const handleClick = vi.fn(); const root = document.getElementById('root'); initializeShadeRoot({ injector, rootElement: root, jsxElement: createComponent(Fab, { onclick: handleClick }, "+"), }); await flushUpdates(); const fab = root.querySelector('button[is="shade-fab"]'); fab.click(); expect(handleClick).toHaveBeenCalledTimes(1); }); }); }); }); //# sourceMappingURL=fab.spec.js.map