UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

213 lines (180 loc) 6.8 kB
import '@testing-library/jest-dom' import { axe, toHaveNoViolations } from 'jest-axe' import { fireEvent } from '@testing-library/dom' import { vi } from 'vitest' import { createElementTest, BaseTestConfig } from '../../tests/test-framework' import { CustomElementFor } from '../../tests/component-registry' import { type IPktTag } from './tag' import './tag' export interface TagTestConfig extends Partial<IPktTag>, BaseTestConfig {} // Use shared framework export const createTagTest = async (config: TagTestConfig = {}) => { const { container, element } = await createElementTest< CustomElementFor<'pkt-tag'>, TagTestConfig >('pkt-tag', config) return { container, tag: element, } } expect.extend(toHaveNoViolations) // Test data constants const VALID_SKINS = [ 'blue', 'blue-dark', 'blue-light', 'green', 'red', 'yellow', 'beige', 'gray', 'grey', ] as const const VALID_SIZES = ['small', 'medium', 'large'] as const const VALID_TYPES = ['button', 'reset', 'submit'] as const afterEach(() => { document.body.innerHTML = '' }) describe('PktTag', () => { describe('Basic Rendering', () => { test('renders without errors', async () => { const { tag } = await createTagTest() expect(tag).toBeInTheDocument() }) test('renders with default properties', async () => { const { tag } = await createTagTest() expect(tag.closeTag).toBe(false) expect(tag.size).toBe('medium') expect(tag.skin).toBe('blue') expect(tag.type).toBe('button') }) test('renders content in slot', async () => { const content = 'Test Tag Content' const { tag } = await createTagTest({ content }) expect(tag.textContent?.trim()).toBe(content) }) }) describe('Skin Variations', () => { test('applies different skin classes correctly', async () => { for (const skin of VALID_SKINS) { const { tag } = await createTagTest({ skin }) // For non-closeable tags, check the span element const tagElement = tag.querySelector('span') || tag.querySelector('button') expect(tagElement).toHaveClass(`pkt-tag--${skin}`) } }) }) describe('Size Variations', () => { test('applies different size classes correctly', async () => { for (const size of VALID_SIZES) { const { tag } = await createTagTest({ size }) // For non-closeable tags, check the span element const tagElement = tag.querySelector('span') || tag.querySelector('button') expect(tagElement).toHaveClass(`pkt-tag--${size}`) } }) }) describe('Type Variations', () => { test('sets correct type attribute', async () => { for (const type of VALID_TYPES) { const { tag } = await createTagTest({ type }) expect(tag.type).toBe(type) } }) }) describe('Icon Functionality', () => { test('renders icon when iconName provided', async () => { const { tag } = await createTagTest({ iconName: 'arrow-right' }) const icon = tag.querySelector('pkt-icon') expect(icon).toBeInTheDocument() expect(icon?.getAttribute('name')).toBe('arrow-right') }) test('does not render icon when iconName not provided', async () => { const { tag } = await createTagTest() const icon = tag.querySelector('pkt-icon') expect(icon).not.toBeInTheDocument() }) }) describe('Close Functionality', () => { test('renders close button when closeTag is true', async () => { const { tag } = await createTagTest({ closeTag: true }) const closeIcon = tag.querySelector('.pkt-tag__close-btn') expect(closeIcon).toBeInTheDocument() }) test('does not render close button when closeTag is false', async () => { const { tag } = await createTagTest({ closeTag: false }) const closeIcon = tag.querySelector('.pkt-tag__close-btn') expect(closeIcon).not.toBeInTheDocument() }) test('dispatches close event when close button is clicked', async () => { const { tag } = await createTagTest({ closeTag: true }) const closeSpy = vi.fn() tag.addEventListener('close', closeSpy) const button = tag.querySelector('button') as HTMLButtonElement fireEvent.click(button) expect(closeSpy).toHaveBeenCalled() }) test('hides tag when closed', async () => { const { tag } = await createTagTest({ closeTag: true }) const button = tag.querySelector('button') as HTMLButtonElement fireEvent.click(button) await tag.updateComplete expect(button).toHaveClass('pkt-hide') }) }) describe('Text Style', () => { test('applies text style class when provided', async () => { const { tag } = await createTagTest({ textStyle: 'thin-text' }) const tagElement = tag.querySelector('span') || tag.querySelector('button') expect(tagElement).toHaveClass('pkt-tag--thin-text') }) }) describe('Accessibility', () => { test('applies aria-label when provided', async () => { const { tag } = await createTagTest({ closeTag: true, ariaLabel: 'Close tag' }) const button = tag.querySelector('button') expect(button?.getAttribute('aria-label')).toBe('Close tag') }) test('tag is accessible', async () => { const { tag } = await createTagTest({ content: 'Accessible Tag', closeTag: true, ariaLabel: 'Close tag', }) const results = await axe(tag) expect(results).toHaveNoViolations() }) }) describe('Complex Configurations', () => { test('renders with all properties set', async () => { const config: TagTestConfig = { content: 'Complete Tag', closeTag: true, size: 'large', skin: 'green', iconName: 'check', type: 'submit', textStyle: 'thin-text', ariaLabel: 'Complete tag', } const { tag } = await createTagTest(config) expect(tag.textContent?.trim()).toBe(config.content) expect(tag.closeTag).toBe(config.closeTag) expect(tag.size).toBe(config.size) expect(tag.skin).toBe(config.skin) expect(tag.iconName).toBe(config.iconName) expect(tag.type).toBe(config.type) expect(tag.textStyle).toBe(config.textStyle) expect(tag.ariaLabel).toBe(config.ariaLabel) const button = tag.querySelector('button') expect(button).toHaveClass(`pkt-tag--${config.size}`) expect(button).toHaveClass(`pkt-tag--${config.skin}`) expect(button).toHaveClass(`pkt-tag--${config.textStyle}`) const icon = tag.querySelector('pkt-icon') expect(icon?.getAttribute('name')).toBe(config.iconName) const closeIcon = tag.querySelector('.pkt-tag__close-btn') expect(closeIcon).toBeInTheDocument() }) }) })