UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

241 lines (185 loc) 8.12 kB
import '@testing-library/jest-dom' import { axe, toHaveNoViolations } from 'jest-axe' import { createElementTest, BaseTestConfig } from '../../tests/test-framework' import { CustomElementFor } from '../../tests/component-registry' import './backlink' expect.extend(toHaveNoViolations) export interface BacklinkTestConfig extends BaseTestConfig { href?: string text?: string ariaLabel?: string } // Use shared framework export const createBacklinkTest = async (config: BacklinkTestConfig = {}) => { const { container, element } = await createElementTest< CustomElementFor<'pkt-backlink'>, BacklinkTestConfig >('pkt-backlink', config) return { container, backlink: element, } } describe('PktBackLink', () => { describe('Rendering and basic functionality', () => { test('renders without errors', async () => { const { backlink } = await createBacklinkTest() expect(backlink).toBeInTheDocument() expect(backlink).toBeTruthy() const nav = backlink.querySelector('nav') expect(nav).toBeInTheDocument() }) test('renders with correct structure', async () => { const { backlink } = await createBacklinkTest() const nav = backlink.querySelector('nav') const link = nav?.querySelector('a') const icon = link?.querySelector('pkt-icon') const textSpan = link?.querySelector('.pkt-back-link__text') expect(nav).toHaveClass('pkt-back-link') expect(link).toHaveClass('pkt-link') expect(link).toHaveClass('pkt-link--icon-left') expect(icon).toHaveClass('pkt-back-link__icon') expect(icon).toHaveClass('pkt-icon') expect(icon).toHaveClass('pkt-link__icon') expect(textSpan).toHaveClass('pkt-back-link__text') }) test('renders icon correctly', async () => { const { backlink } = await createBacklinkTest() const icon = backlink.querySelector('pkt-icon') expect(icon).toBeInTheDocument() expect(icon?.getAttribute('name')).toBe('chevron-thin-left') expect(icon?.getAttribute('aria-hidden')).toBe('true') }) }) describe('Properties and attributes', () => { test('applies default properties correctly', async () => { const { backlink } = await createBacklinkTest() expect(backlink.href).toBe('') expect(backlink.text).toBe('Forsiden') expect(backlink.ariaLabel).toBe('') const nav = backlink.querySelector('nav') const link = nav?.querySelector('a') const textSpan = link?.querySelector('.pkt-back-link__text') expect(link?.getAttribute('href')).toBe('/') expect(textSpan?.textContent).toBe('Forsiden') expect(nav?.getAttribute('aria-label')).toBe('Gå tilbake til forrige side') }) test('handles href property correctly', async () => { const { backlink } = await createBacklinkTest({ href: '/previous-page' }) expect(backlink.href).toBe('/previous-page') const link = backlink.querySelector('a') expect(link?.getAttribute('href')).toBe('/previous-page') // Test href updates backlink.href = '/another-page' await backlink.updateComplete expect(link?.getAttribute('href')).toBe('/another-page') }) test('handles text property correctly', async () => { const { backlink } = await createBacklinkTest({ text: 'Back to Home' }) expect(backlink.text).toBe('Back to Home') // The text attribute should be removed from the custom element expect(backlink.getAttribute('text')).toBe(null) const textSpan = backlink.querySelector('.pkt-back-link__text') expect(textSpan?.textContent).toBe('Back to Home') // Test text updates backlink.text = 'Return to Start' await backlink.updateComplete expect(textSpan?.textContent).toBe('Return to Start') }) test('handles ariaLabel property correctly', async () => { const { backlink } = await createBacklinkTest({ ariaLabel: 'Navigate back to previous section', }) expect(backlink.ariaLabel).toBe('Navigate back to previous section') const nav = backlink.querySelector('nav') expect(nav?.getAttribute('aria-label')).toBe('Navigate back to previous section') // Test ariaLabel updates backlink.ariaLabel = 'Go back to main menu' await backlink.updateComplete expect(nav?.getAttribute('aria-label')).toBe('Go back to main menu') }) test('uses default aria-label when none provided', async () => { const { backlink } = await createBacklinkTest() expect(backlink.ariaLabel).toBe('') const nav = backlink.querySelector('nav') expect(nav?.getAttribute('aria-label')).toBe('Gå tilbake til forrige side') }) test('handles empty href by defaulting to "/"', async () => { const { backlink } = await createBacklinkTest({ href: '' }) expect(backlink.href).toBe('') const link = backlink.querySelector('a') expect(link?.getAttribute('href')).toBe('/') }) }) describe('Attribute cleanup', () => { test('removes reflected attributes from the element', async () => { const { backlink } = await createBacklinkTest({ href: '/test', text: 'Test Text' }) // The attributeChangedCallback should remove these attributes from the element // (this is implementation-specific behavior in the component) expect(backlink.hasAttribute('href')).toBe(false) expect(backlink.hasAttribute('text')).toBe(false) expect(backlink.hasAttribute('arialabel')).toBe(false) }) }) describe('Link functionality', () => { test('creates clickable link with correct href', async () => { const { backlink } = await createBacklinkTest({ href: '/dashboard', text: 'Back to Dashboard', }) const link = backlink.querySelector('a') expect(link).toBeInTheDocument() expect(link?.getAttribute('href')).toBe('/dashboard') expect(link?.textContent?.trim()).toContain('Back to Dashboard') }) test('handles complex URLs correctly', async () => { const complexUrl = 'https://example.com/path?query=value#section' const { backlink } = await createBacklinkTest({ href: complexUrl }) const link = backlink.querySelector('a') expect(link?.getAttribute('href')).toBe(complexUrl) }) }) describe('Accessibility', () => { test('has correct ARIA attributes', async () => { const { backlink } = await createBacklinkTest({ text: 'Home', ariaLabel: 'Return to main page', }) const nav = backlink.querySelector('nav') const icon = backlink.querySelector('pkt-icon') expect(nav?.getAttribute('aria-label')).toBe('Return to main page') expect(icon?.getAttribute('aria-hidden')).toBe('true') }) test('provides semantic navigation structure', async () => { const { backlink } = await createBacklinkTest() const nav = backlink.querySelector('nav') const link = nav?.querySelector('a') expect(nav).toBeInTheDocument() expect(link).toBeInTheDocument() expect(nav?.tagName.toLowerCase()).toBe('nav') expect(link?.tagName.toLowerCase()).toBe('a') }) test('renders with no WCAG errors with axe - default backlink', async () => { const { container } = await createBacklinkTest() const results = await axe(container) expect(results).toHaveNoViolations() }) test('renders with no WCAG errors with axe - custom backlink', async () => { const { container } = await createBacklinkTest({ href: '/categories', text: 'Back to Categories', ariaLabel: 'Navigate back to category listing', }) const results = await axe(container) expect(results).toHaveNoViolations() }) test('renders with no WCAG errors with axe - external link', async () => { const { container } = await createBacklinkTest({ href: 'https://example.com', text: 'Back to External Site', }) const results = await axe(container) expect(results).toHaveNoViolations() }) }) })