UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

274 lines (218 loc) 8.19 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 './radiobutton' export interface RadioButtonTestConfig extends BaseTestConfig { value?: string checkHelptext?: string | null defaultChecked?: boolean hasTile?: boolean checked?: boolean | string | null type?: string tagText?: string | null optionalTag?: boolean optionalText?: string requiredTag?: boolean requiredText?: string id?: string name?: string label?: string disabled?: boolean readonly?: boolean required?: boolean hasError?: boolean inline?: boolean ariaDescribedBy?: string | null ariaLabelledby?: string | null } export const createRadioButtonTest = async (config: RadioButtonTestConfig = {}) => { const { container, element } = await createElementTest< CustomElementFor<'pkt-radiobutton'>, RadioButtonTestConfig >('pkt-radiobutton', config) if (config.label) { element.label = config.label await element.updateComplete } return { container, radiobutton: element, } } expect.extend(toHaveNoViolations) describe('pkt-radiobutton', () => { afterEach(() => { document.body.innerHTML = '' }) test('renders with basic properties', async () => { const { radiobutton } = await createRadioButtonTest({ id: 'test', name: 'test', value: 'test', }) expect(radiobutton).toBeInTheDocument() expect(radiobutton.tagName).toBe('PKT-RADIOBUTTON') }) test('renders input element with correct attributes', async () => { const { radiobutton } = await createRadioButtonTest({ id: 'test', name: 'test', value: 'test', }) const input = radiobutton.querySelector('input[type="radio"]') as HTMLInputElement expect(input).toBeInTheDocument() expect(input.type).toBe('radio') expect(input.id).toBe('test-internal') expect(input.name).toBe('test-internal') }) test('displays label correctly', async () => { const { radiobutton } = await createRadioButtonTest({ id: 'test', label: 'Test Radio', }) const label = radiobutton.querySelector('label') expect(label).toBeInTheDocument() expect(label?.textContent?.trim()).toContain('Test Radio') expect(label?.getAttribute('for')).toBe('test-internal') }) test('handles checked state correctly', async () => { const { radiobutton } = await createRadioButtonTest() expect(radiobutton.checked).toBe(null) radiobutton.checked = true await radiobutton.updateComplete const input = radiobutton.querySelector('input') as HTMLInputElement expect(input.checked).toBe(true) expect(radiobutton.checked).toBe(true) }) test('updates checked state on user interaction', async () => { const { radiobutton } = await createRadioButtonTest({ label: 'Test Option', }) const input = radiobutton.querySelector('input') as HTMLInputElement expect(input.checked).toBe(false) expect(radiobutton.touched).toBe(false) fireEvent.click(input) await radiobutton.updateComplete expect(input.checked).toBe(true) expect(radiobutton.touched).toBe(true) }) test('handles disabled state correctly', async () => { const { radiobutton } = await createRadioButtonTest({ disabled: true, }) const input = radiobutton.querySelector('input') as HTMLInputElement expect(input.disabled).toBe(true) const label = radiobutton.querySelector('.pkt-input-check__input-label') expect(label).toHaveClass('pkt-input-check__input-label--disabled') }) test('renders tile variant correctly', async () => { const { radiobutton } = await createRadioButtonTest({ hasTile: true, }) const container = radiobutton.querySelector('.pkt-input-check__input') expect(container).toHaveClass('pkt-input-check__input--tile') }) test('renders disabled tile variant correctly', async () => { const { radiobutton } = await createRadioButtonTest({ hasTile: true, disabled: true, }) const container = radiobutton.querySelector('.pkt-input-check__input') expect(container).toHaveClass('pkt-input-check__input--tile-disabled') }) test('renders helptext when provided', async () => { const { radiobutton } = await createRadioButtonTest({ checkHelptext: 'This is helpful information', }) const helptext = radiobutton.querySelector('.pkt-input-check__input-helptext') expect(helptext).toBeInTheDocument() expect(helptext?.textContent).toBe('This is helpful information') }) test('handles error state correctly', async () => { const { radiobutton } = await createRadioButtonTest({ hasError: true, }) const input = radiobutton.querySelector('input') expect(input).toHaveClass('pkt-input-check__input-checkbox--error') }) test('renders tag text when provided', async () => { const { radiobutton } = await createRadioButtonTest({ tagText: 'Tag', }) const tag = radiobutton.querySelector('.pkt-tag--gray') expect(tag).toBeInTheDocument() expect(tag?.textContent).toBe('Tag') }) test('renders optional tag when enabled', async () => { const { radiobutton } = await createRadioButtonTest({ optionalTag: true, }) const tag = radiobutton.querySelector('.pkt-tag--blue-light') expect(tag).toBeInTheDocument() expect(tag?.textContent).toBe('Valgfritt') }) test('renders required tag when enabled', async () => { const { radiobutton } = await createRadioButtonTest({ requiredTag: true, }) const tag = radiobutton.querySelector('.pkt-tag--beige') expect(tag).toBeInTheDocument() expect(tag?.textContent).toBe('Må fylles ut') }) test('manages focus events correctly', async () => { const { radiobutton } = await createRadioButtonTest() const focusSpy = vi.fn() const blurSpy = vi.fn() radiobutton.addEventListener('focus', focusSpy) radiobutton.addEventListener('blur', blurSpy) const input = radiobutton.querySelector('input') as HTMLInputElement fireEvent.focus(input) expect(focusSpy).toHaveBeenCalled() fireEvent.blur(input) expect(blurSpy).toHaveBeenCalled() }) test('works with radio button groups', async () => { const container = document.createElement('form') document.body.appendChild(container) const radio1Container = document.createElement('div') radio1Container.innerHTML = '<pkt-radiobutton name="group" value="1"></pkt-radiobutton>' container.appendChild(radio1Container) await customElements.whenDefined('pkt-radiobutton') const radio1 = radio1Container.querySelector( 'pkt-radiobutton', ) as CustomElementFor<'pkt-radiobutton'> radio1.label = 'Option 1' await radio1.updateComplete const radio2Container = document.createElement('div') radio2Container.innerHTML = '<pkt-radiobutton name="group" value="2"></pkt-radiobutton>' container.appendChild(radio2Container) const radio2 = radio2Container.querySelector( 'pkt-radiobutton', ) as CustomElementFor<'pkt-radiobutton'> radio2.label = 'Option 2' await radio2.updateComplete const input1 = radio1.querySelector('input') as HTMLInputElement const input2 = radio2.querySelector('input') as HTMLInputElement expect(input1.checked).toBe(false) expect(input2.checked).toBe(false) fireEvent.click(input1) await radio1.updateComplete expect(input1.checked).toBe(true) expect(radio1.touched).toBe(true) fireEvent.click(input2) await radio2.updateComplete expect(input2.checked).toBe(true) expect(radio2.touched).toBe(true) document.body.removeChild(container) }) test('meets accessibility standards', async () => { const { radiobutton } = await createRadioButtonTest({ label: 'Accessible Radio Button', }) const results = await axe(radiobutton) expect(results).toHaveNoViolations() }) })