@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
107 lines • 4.66 kB
JavaScript
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