import '@testing-library/jest-dom' import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { axe, toHaveNoViolations } from 'jest-axe' import { vi } from 'vitest' import { createRef } from 'react' import { useForm } from 'react-hook-form' import { PktButton } from './Button' expect.extend(toHaveNoViolations) // Mock Form Component const MockForm = ({ buttonPosition }: { buttonPosition: 'inside' | 'outside' }) => { const { register, handleSubmit, reset } = useForm() const onSubmit = vi.fn() return ( <>
{buttonPosition === 'inside' && Submit} {buttonPosition === 'inside' && ( reset()}> Reset )}
{buttonPosition === 'outside' && ( Submit )} {buttonPosition === 'outside' && ( reset()}> Reset )} ) } // Ligger button utenfor form i React Hook Form må bruker sende inn reset selv // dette gjelder ikke native knapper som er assosiert med native form elementer, men de fleste brukerene våre // bruker nok også våre input elementer også //https://react-hook-form.com/api/useform/reset describe('PktButton Form Behavior', () => { test('PktButton submits form when inside form element', async () => { render() await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe') await userEvent.click(screen.getByText('Submit')) expect(screen.getByPlaceholderText('Name')).toHaveValue('Shawn Joe') }) test('PktButton resets form when inside form element', async () => { render() await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe') await userEvent.click(screen.getByText('Reset')) expect(screen.getByPlaceholderText('Name')).toHaveValue('') }) test('PktButton submits form when outside but linked via form attribute', async () => { render() await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe') await userEvent.click(screen.getByText('Submit')) expect(screen.getByPlaceholderText('Name')).toHaveValue('Shawn Joe') }) test('PktButton resets form when outside but linked via form attribute', async () => { render() await userEvent.type(screen.getByPlaceholderText('Name'), 'Shawn Joe') await userEvent.click(screen.getByText('Reset')) // Wait for the form state update await screen.findByPlaceholderText('Name') expect(screen.getByPlaceholderText('Name')).toHaveValue('') }) }) test('forwardRef works correctly', async () => { const ref = createRef() render(Click me) await userEvent.click(screen.getByText('Click me')) expect(ref.current).toBe(screen.getByRole('button')) }) test('PktButton triggers click when focused and enter is pressed', async () => { const handleClick = vi.fn() render(trøkk her) const button = screen.getByRole('button', { name: /trøkk her/i }) button.focus() expect(button).toHaveFocus() await userEvent.keyboard('{Enter}') expect(handleClick).toHaveBeenCalledTimes(1) }) test('PktButton triggers click when focused and space is pressed', async () => { const handleClick = vi.fn() render(Trøkk igjen) const button = screen.getByRole('button') button.focus() expect(button).toHaveFocus() await userEvent.keyboard(' ') expect(handleClick).toHaveBeenCalledTimes(1) }) describe('accessibility', () => { it('renders with no wcag errors with axe', async () => { const { container } = render() const results = await axe(container) expect(results).toHaveNoViolations() }) }) describe('PktButton icon paths', () => { test('passes iconPath to PktIcon when provided', () => { const customPath = 'https://custom-cdn.example.com/icons/' render( Test Button , ) const icon = document.querySelector('.pkt-btn__icon:not(.pkt-btn__spinner)') as HTMLElement & { path?: string } expect(icon?.path).toBe(customPath) }) test('does not set path property when iconPath is not provided', () => { render( Test Button , ) const icon = document.querySelector('.pkt-btn__icon:not(.pkt-btn__spinner)') as HTMLElement & { path?: string } // When not provided, path uses PktIcon's default expect(icon?.path).toBe('https://punkt-cdn.oslo.kommune.no/latest/icons/') }) test('passes secondIconPath to second PktIcon when provided', () => { const customPath = 'https://custom-cdn.example.com/icons/' render( Test Button , ) const icons = document.querySelectorAll('.pkt-btn__icon:not(.pkt-btn__spinner)') as NodeListOf< HTMLElement & { path?: string } > expect(icons).toHaveLength(2) expect(icons[1]?.path).toBe(customPath) }) test('handles both iconPath and secondIconPath independently', () => { const iconPath = 'https://custom-cdn.example.com/icons/' const secondIconPath = 'https://another-cdn.example.com/icons/' render( Test Button , ) const icons = document.querySelectorAll('.pkt-btn__icon:not(.pkt-btn__spinner)') as NodeListOf< HTMLElement & { path?: string } > expect(icons).toHaveLength(2) expect(icons[0]?.path).toBe(iconPath) expect(icons[1]?.path).toBe(secondIconPath) }) })