UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

335 lines (259 loc) 10.7 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 './alert' expect.extend(toHaveNoViolations) export interface AlertTestConfig extends BaseTestConfig { skin?: string compact?: boolean title?: string date?: string closeAlert?: boolean ariaLive?: string } // Use shared framework export const createAlertTest = async (config: AlertTestConfig = {}) => { const { container, element } = await createElementTest< CustomElementFor<'pkt-alert'>, AlertTestConfig >('pkt-alert', config) return { container, alert: element, } } // Cleanup after each test afterEach(() => { document.body.innerHTML = '' }) describe('PktAlert', () => { describe('Rendering and basic functionality', () => { test('renders without errors', async () => { const { alert } = await createAlertTest({ content: 'Test alert content', }) expect(alert).toBeInTheDocument() await alert.updateComplete expect(alert).toBeTruthy() const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv).toBeInTheDocument() }) test('renders with correct structure', async () => { const { alert } = await createAlertTest({ title: 'Test Title', content: 'Test alert message', }) await alert.updateComplete const alertDiv = alert.querySelector('.pkt-alert') const grid = alertDiv?.querySelector('.pkt-alert__grid') const icon = alert.querySelector('.pkt-alert__icon') const title = alert.querySelector('.pkt-alert__title') const text = alert.querySelector('.pkt-alert__text') expect(alertDiv).toHaveClass('pkt-alert') expect(grid).toHaveClass('pkt-alert__grid') expect(icon).toBeInTheDocument() expect(title).toBeInTheDocument() expect(text).toBeInTheDocument() expect(title?.textContent).toContain('Test Title') }) test('renders icon correctly based on skin', async () => { const skins = ['error', 'success', 'warning', 'info'] as const for (const skin of skins) { const { alert } = await createAlertTest({ skin }) await alert.updateComplete const icon = alert.querySelector('pkt-icon') const expectedIconName = skin === 'info' ? 'alert-information' : `alert-${skin}` expect(icon?.getAttribute('name')).toBe(expectedIconName) expect(icon?.getAttribute('aria-hidden')).toBe('true') } }) }) describe('Properties and attributes', () => { test('applies default properties correctly', async () => { const { alert } = await createAlertTest() await alert.updateComplete expect(alert.skin).toBe('info') expect(alert.compact).toBe(false) expect(alert.closeAlert).toBe(false) expect(alert.title).toBe('') expect(alert.date).toBe(null) expect(alert.role).toBe('status') const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv).toHaveClass('pkt-alert') expect(alertDiv).toHaveClass('pkt-alert--info') expect(alertDiv).not.toHaveClass('pkt-alert--compact') }) test('applies different skin properties correctly', async () => { const skins = ['error', 'success', 'warning', 'info'] as const for (const skin of skins) { const { alert } = await createAlertTest({ skin }) await alert.updateComplete expect(alert.skin).toBe(skin) expect(alert.getAttribute('skin')).toBe(skin) const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv).toHaveClass(`pkt-alert--${skin}`) } }) test('applies compact property correctly', async () => { const { alert } = await createAlertTest({ compact: true }) await alert.updateComplete expect(alert.compact).toBe(true) const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv).toHaveClass('pkt-alert--compact') }) test('handles title property', async () => { const { alert } = await createAlertTest({ title: 'Alert Title' }) await alert.updateComplete expect(alert.title).toBe('Alert Title') expect(alert.getAttribute('title')).toBe('Alert Title') const title = alert.querySelector('.pkt-alert__title') expect(title).toBeInTheDocument() expect(title?.textContent).toBe('Alert Title') // Test title updates alert.title = 'Updated Title' await alert.updateComplete expect(title?.textContent).toBe('Updated Title') }) test('handles date property', async () => { const { alert } = await createAlertTest({ date: '2024-01-15' }) await alert.updateComplete expect(alert.date).toBe('2024-01-15') expect(alert.getAttribute('date')).toBe('2024-01-15') const dateElement = alert.querySelector('.pkt-alert__date') expect(dateElement).toBeInTheDocument() expect(dateElement?.textContent).toContain('2024-01-15') }) test('handles aria-live property', async () => { const { alert } = await createAlertTest({ ariaLive: 'assertive' }) await alert.updateComplete // The component uses the ariaLive property value that was set expect(alert.ariaLiveAttr).toBe('assertive') const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv?.getAttribute('aria-live')).toBe('assertive') }) }) describe('Close functionality', () => { test('renders close button when closeAlert is true', async () => { const { alert } = await createAlertTest({ closeAlert: true }) await alert.updateComplete expect(alert.closeAlert).toBe(true) const closeDiv = alert.querySelector('.pkt-alert__close') const closeButton = alert.querySelector('pkt-button') expect(closeDiv).toBeInTheDocument() expect(closeButton).toBeInTheDocument() expect(closeButton?.getAttribute('aria-label')).toBe('close') expect(closeButton?.getAttribute('skin')).toBe('tertiary') expect(closeButton?.getAttribute('variant')).toBe('icon-only') }) test('does not render close button when closeAlert is false', async () => { const { alert } = await createAlertTest({ closeAlert: false }) await alert.updateComplete expect(alert.closeAlert).toBe(false) const closeDiv = alert.querySelector('.pkt-alert__close') const closeButton = alert.querySelector('pkt-button') expect(closeDiv).not.toBeInTheDocument() expect(closeButton).not.toBeInTheDocument() }) test('closes alert when close button is clicked', async () => { const { alert } = await createAlertTest({ closeAlert: true }) await alert.updateComplete // Listen for close events const closeSpy = vi.fn() const onCloseSpy = vi.fn() alert.addEventListener('close', closeSpy) alert.addEventListener('on-close', onCloseSpy) const closeButton = alert.querySelector('pkt-button') expect(closeButton).toBeInTheDocument() // Click the close button fireEvent.click(closeButton!) await alert.updateComplete // Alert should be hidden const alertDiv = alert.querySelector('.pkt-alert') expect(alertDiv).toHaveClass('pkt-hide') expect(alert).toHaveClass('pkt-hide') // Events should be dispatched expect(closeSpy).toHaveBeenCalledWith( expect.objectContaining({ type: 'close', detail: expect.objectContaining({ origin: expect.any(Object), }), }), ) expect(onCloseSpy).toHaveBeenCalledWith( expect.objectContaining({ type: 'on-close', detail: expect.objectContaining({ origin: expect.any(Object), }), }), ) }) }) describe('Grid layout classes', () => { test('applies correct grid classes based on content', async () => { // Test with no title and no date const { alert: alert1 } = await createAlertTest() await alert1.updateComplete const grid1 = alert1.querySelector('.pkt-alert__grid') expect(grid1).toHaveClass('pkt-alert__noTitle') expect(grid1).toHaveClass('pkt-alert__noDate') // Test with title but no date const { alert: alert2 } = await createAlertTest({ title: 'Test Title' }) await alert2.updateComplete const grid2 = alert2.querySelector('.pkt-alert__grid') expect(grid2).not.toHaveClass('pkt-alert__noTitle') expect(grid2).toHaveClass('pkt-alert__noDate') // Test with both title and date const { alert: alert3 } = await createAlertTest({ title: 'Test Title', date: '2024-01-15' }) await alert3.updateComplete const grid3 = alert3.querySelector('.pkt-alert__grid') expect(grid3).not.toHaveClass('pkt-alert__noTitle') expect(grid3).not.toHaveClass('pkt-alert__noDate') }) }) describe('Accessibility', () => { test('has correct ARIA attributes', async () => { const { alert } = await createAlertTest({ ariaLive: 'polite' }) await alert.updateComplete const alertDiv = alert.querySelector('.pkt-alert') const icon = alert.querySelector('pkt-icon') expect(alertDiv?.getAttribute('aria-live')).toBe('polite') expect(alert.role).toBe('status') expect(icon?.getAttribute('aria-hidden')).toBe('true') }) test('renders with no WCAG errors with axe - simple alert', async () => { const { container } = await createAlertTest({ title: 'Test Alert', content: 'This is a test alert message.', }) const results = await axe(container) expect(results).toHaveNoViolations() }) test('renders with no WCAG errors with axe - complex alert', async () => { const { container } = await createAlertTest({ skin: 'error', title: 'Error Alert', date: '2024-01-15', closeAlert: true, ariaLive: 'assertive', content: '<p>This is an error message with <a href="#">a link</a>.</p>', }) const results = await axe(container) expect(results).toHaveNoViolations() }) test('renders with no WCAG errors with axe - compact alert', async () => { const { container } = await createAlertTest({ skin: 'success', compact: true, closeAlert: true, content: 'Success message', }) const results = await axe(container) expect(results).toHaveNoViolations() }) }) })