@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
217 lines • 10.7 kB
JavaScript
import { createComponent, flushUpdates } from '@furystack/shades';
import { describe, expect, it } from 'vitest';
import { Timeline, TimelineItem } from './timeline.js';
describe('TimelineItem', () => {
it('should be defined', () => {
expect(TimelineItem).toBeDefined();
expect(typeof TimelineItem).toBe('function');
});
it('should create a timeline item element', () => {
const el = (createComponent(TimelineItem, null));
expect(el).toBeDefined();
expect(el.tagName?.toLowerCase()).toBe('shade-timeline-item');
});
it('should pass children as content', () => {
const el = (createComponent(TimelineItem, null, "Event happened"));
expect(el).toBeDefined();
});
it('should set props correctly', () => {
const el = (createComponent(TimelineItem, { color: "success", label: "2024-01-01" }));
expect(el.props.color).toBe('success');
expect(el.props.label).toBe('2024-01-01');
});
it('should render dot and content', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, null,
createComponent("span", null, "Event content"))));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
expect(item.querySelector('.timeline-dot')).not.toBeNull();
expect(item.querySelector('.timeline-content')).not.toBeNull();
expect(item.querySelector('.timeline-tail')).not.toBeNull();
});
it('should render a label when provided', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, { label: "Jan 2024" }, "Event")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
const label = item.querySelector('.timeline-label');
expect(label).not.toBeNull();
expect(label.textContent).toBe('Jan 2024');
});
it('should set custom dot when dot prop is provided', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, { dot: createComponent("span", null, "\uD83C\uDF89") }, "Party!")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
const dot = item.querySelector('.timeline-dot');
expect(dot.hasAttribute('data-custom')).toBe(true);
});
it('should not set data-custom when dot prop is not provided', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, null, "Event")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
const dot = item.querySelector('.timeline-dot');
expect(dot.hasAttribute('data-custom')).toBe(false);
});
it('should set CSS custom property for dot color', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, { color: "success" }, "Done")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
expect(item.style.getPropertyValue('--timeline-dot-color')).toBe('var(--shades-theme-palette-success-main)');
});
it('should default to primary color', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, null, "Event")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
expect(item.style.getPropertyValue('--timeline-dot-color')).toBe('var(--shades-theme-palette-primary-main)');
});
it('should render dashed tail when data-pending attribute is set', async () => {
const el = (createComponent("div", null,
createComponent(TimelineItem, { "data-pending": "" }, "Event")));
const item = el.firstElementChild;
item.updateComponent();
await flushUpdates();
const tail = item.querySelector('.timeline-tail');
expect(tail.hasAttribute('data-pending')).toBe(true);
});
});
describe('Timeline', () => {
it('should be defined', () => {
expect(Timeline).toBeDefined();
expect(typeof Timeline).toBe('function');
});
it('should create a timeline element', () => {
const el = (createComponent(Timeline, null));
expect(el).toBeDefined();
expect(el.tagName?.toLowerCase()).toBe('shade-timeline');
});
it('should set props correctly', () => {
const el = (createComponent(Timeline, { mode: "alternate", pending: true }));
expect(el.props.mode).toBe('alternate');
expect(el.props.pending).toBe(true);
});
it('should render timeline items as children', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, null,
createComponent(TimelineItem, null, "First"),
createComponent(TimelineItem, null, "Second"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
const items = timeline.querySelectorAll('shade-timeline-item');
expect(items.length).toBe(2);
});
it('should set data-mode attribute', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { mode: "alternate" },
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.getAttribute('data-mode')).toBe('alternate');
});
it('should default mode to left', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, null,
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.getAttribute('data-mode')).toBe('left');
});
it('should add pending item when pending is true', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { pending: true },
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
const items = timeline.querySelectorAll('shade-timeline-item');
expect(items.length).toBe(2);
});
describe('orientation', () => {
it('should not set data-orientation when orientation is not specified (defaults to vertical)', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, null,
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.hasAttribute('data-orientation')).toBe(false);
});
it('should not set data-orientation when orientation is "vertical"', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "vertical" },
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.hasAttribute('data-orientation')).toBe(false);
});
it('should set data-orientation="horizontal" when orientation is "horizontal"', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "horizontal" },
createComponent(TimelineItem, null, "Event"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.getAttribute('data-orientation')).toBe('horizontal');
});
it('should render children in horizontal mode', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "horizontal" },
createComponent(TimelineItem, null, "First"),
createComponent(TimelineItem, null, "Second"),
createComponent(TimelineItem, null, "Third"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
const items = timeline.querySelectorAll('shade-timeline-item');
expect(items.length).toBe(3);
});
it('should support horizontal with mode="alternate"', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "horizontal", mode: "alternate" },
createComponent(TimelineItem, null, "First"),
createComponent(TimelineItem, null, "Second"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.getAttribute('data-orientation')).toBe('horizontal');
expect(timeline.getAttribute('data-mode')).toBe('alternate');
});
it('should support horizontal with mode="right"', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "horizontal", mode: "right" },
createComponent(TimelineItem, null, "First"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
expect(timeline.getAttribute('data-orientation')).toBe('horizontal');
expect(timeline.getAttribute('data-mode')).toBe('right');
});
it('should add pending item in horizontal mode', async () => {
const el = (createComponent("div", null,
createComponent(Timeline, { orientation: "horizontal", pending: "Loading..." },
createComponent(TimelineItem, null, "Step 1"),
createComponent(TimelineItem, null, "Step 2"))));
const timeline = el.firstElementChild;
timeline.updateComponent();
await flushUpdates();
const items = timeline.querySelectorAll('shade-timeline-item');
expect(items.length).toBe(3);
expect(timeline.getAttribute('data-orientation')).toBe('horizontal');
});
});
});
//# sourceMappingURL=timeline.spec.js.map