UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

229 lines (179 loc) 7.05 kB
import '@testing-library/jest-dom' import { axe, toHaveNoViolations } from 'jest-axe' import { vi } from 'vitest' import { createElementTest, BaseTestConfig } from '../../tests/test-framework' import { CustomElementFor } from '../../tests/component-registry' import { type IPktSelect, type TSelectOption } from './select' import './select' export interface SelectTestConfig extends Partial<IPktSelect>, BaseTestConfig { id?: string label?: string disabled?: boolean required?: boolean hasError?: boolean errorMessage?: string helptext?: string fullwidth?: boolean ariaLabelledby?: string | null ariaDescribedBy?: string | null counter?: boolean inline?: boolean useWrapper?: boolean | string } export const createSelectTest = async (config: SelectTestConfig = {}) => { const { options, ...htmlConfig } = config const { container, element } = await createElementTest< CustomElementFor<'pkt-select'>, Omit<SelectTestConfig, 'options'> >('pkt-select', htmlConfig) if (options) { element.options = options await element.updateComplete } return { container, select: element, } } expect.extend(toHaveNoViolations) describe('pkt-select', () => { afterEach(() => { document.body.innerHTML = '' }) test('renders with basic properties', async () => { const { select } = await createSelectTest({ label: 'Test Select', id: 'test-select', }) expect(select).toBeInTheDocument() expect(select.getAttribute('id')).toBe('test-select') expect(select.label).toBe('Test Select') }) test('displays correct label in input wrapper', async () => { const { select } = await createSelectTest({ label: 'Choose Option', }) const inputWrapper = select.querySelector('pkt-input-wrapper') expect(inputWrapper).toBeInTheDocument() expect(inputWrapper?.getAttribute('label')).toBe('Choose Option') }) test('renders select element with correct attributes', async () => { const { select } = await createSelectTest({ id: 'my-select', disabled: true, value: 'option2', }) const selectElement = select.querySelector('select') expect(selectElement).toBeInTheDocument() expect(selectElement?.getAttribute('id')).toBe('my-select-input') expect(selectElement?.hasAttribute('disabled')).toBe(true) expect(selectElement?.getAttribute('value')).toBe('option2') }) test('handles options array property', async () => { const options: TSelectOption[] = [ { value: '1', label: 'Option 1' }, { value: '2', label: 'Option 2' }, { value: '3', label: 'Option 3', disabled: true }, ] const { select } = await createSelectTest({ options }) const optionElements = select.querySelectorAll('option') expect(optionElements).toHaveLength(3) expect(optionElements[0].value).toBe('1') expect(optionElements[0].textContent?.trim()).toBe('Option 1') expect(optionElements[2].hasAttribute('disabled')).toBe(true) }) test('updates value on selection', async () => { const options: TSelectOption[] = [ { value: 'a', label: 'Option A' }, { value: 'b', label: 'Option B' }, ] const { select } = await createSelectTest({ options }) const selectElement = select.querySelector('select') as HTMLSelectElement expect(selectElement.options.length).toBe(2) expect(selectElement.options[0].value).toBe('a') expect(selectElement.options[1].value).toBe('b') expect(select.value).toBe('a') selectElement.selectedIndex = 1 selectElement.dispatchEvent(new Event('change', { bubbles: true })) await select.updateComplete expect(select.value).toBe('b') expect(select.touched).toBe(true) }) test('handles error state correctly', async () => { const { select } = await createSelectTest({ hasError: true, errorMessage: 'Selection required', }) const inputWrapper = select.querySelector('pkt-input-wrapper') expect(inputWrapper?.hasAttribute('hasError')).toBe(true) expect(inputWrapper?.getAttribute('errorMessage')).toBe('Selection required') const selectElement = select.querySelector('select') expect(selectElement?.getAttribute('aria-invalid')).toBe('true') }) test('renders helptext when provided', async () => { const { select } = await createSelectTest({ helptext: 'Choose your preferred option', }) const inputWrapper = select.querySelector('pkt-input-wrapper') expect(inputWrapper?.getAttribute('helptext')).toBe('Choose your preferred option') }) test('handles fullwidth styling', async () => { const { select } = await createSelectTest({ fullwidth: true, }) const selectElement = select.querySelector('select') expect(selectElement?.className).toContain('pkt-input--fullwidth') }) test('manages focus events correctly', async () => { const { select } = await createSelectTest() const focusSpy = vi.spyOn(select, 'onFocus') const blurSpy = vi.spyOn(select, 'onBlur') const selectElement = select.querySelector('select') as HTMLSelectElement selectElement.dispatchEvent(new FocusEvent('focus')) expect(focusSpy).toHaveBeenCalled() selectElement.dispatchEvent(new FocusEvent('blur')) expect(blurSpy).toHaveBeenCalled() }) test('passes through accessibility attributes', async () => { const { select } = await createSelectTest({ ariaLabelledby: 'external-label', ariaDescribedBy: 'external-description', }) const selectElement = select.querySelector('select') expect(selectElement?.getAttribute('aria-labelledby')).toBe('external-label') const inputWrapper = select.querySelector('pkt-input-wrapper') expect(inputWrapper?.getAttribute('ariaDescribedBy')).toBe('external-description') }) test('handles input wrapper properties', async () => { const { select } = await createSelectTest({ counter: true, inline: true, }) const inputWrapper = select.querySelector('pkt-input-wrapper') expect(inputWrapper?.hasAttribute('counter')).toBe(true) expect(inputWrapper?.hasAttribute('inline')).toBe(true) }) test('handles useWrapper false', async () => { const { select } = await createSelectTest() // Set useWrapper property directly on the element select.useWrapper = false await select.updateComplete // When useWrapper is false, verify the behavior expect(select.useWrapper).toBe(false) // Confirm that there's a label with class pkt-sr-only in the markup const srOnlyLabel = select.querySelector('label.pkt-sr-only') expect(srOnlyLabel).toBeInTheDocument() }) test('meets accessibility standards', async () => { const options: TSelectOption[] = [ { value: '1', label: 'Option 1' }, { value: '2', label: 'Option 2' }, ] const { select } = await createSelectTest({ label: 'Accessible Select', options, }) const results = await axe(select) expect(results).toHaveNoViolations() }) })