@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
226 lines (189 loc) • 6.57 kB
text/typescript
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 './link'
expect.extend(toHaveNoViolations)
export interface LinkTestConfig extends BaseTestConfig {
href?: string
target?: string
skin?: string
variant?: string
iconName?: string
iconPosition?: string
openInNewTab?: boolean
external?: boolean
}
// Use shared framework
export const createLinkTest = async (config: LinkTestConfig = {}) => {
const { container, element } = await createElementTest<
CustomElementFor<'pkt-link'>,
LinkTestConfig
>('pkt-link', config)
return {
container,
link: element,
}
}
describe('PktLink', () => {
describe('Rendering and basic functionality', () => {
test('renders without errors', async () => {
const { link } = await createLinkTest()
expect(link).toBeInTheDocument()
await link.updateComplete
expect(link).toBeTruthy()
})
test('renders with correct structure', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
content: 'Click me',
})
await link.updateComplete
expect(link).toBeInTheDocument()
const anchor = link.querySelector('a')
expect(anchor).toBeInTheDocument()
expect(anchor?.href).toBe('https://example.com/')
expect(anchor?.textContent).toContain('Click me')
})
})
describe('Properties and attributes', () => {
test('applies default properties correctly', async () => {
const { link } = await createLinkTest()
await link.updateComplete
expect(link.href).toBe('#')
expect(link.external).toBe(false)
expect(link.iconName).toBeUndefined()
expect(link.target).toBe('_self')
})
test('sets href property correctly', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
})
await link.updateComplete
expect(link.href).toBe('https://example.com')
const anchor = link.querySelector('a')
expect(anchor?.href).toBe('https://example.com/')
})
test('sets external property correctly', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
external: true,
})
await link.updateComplete
expect(link.external).toBe(true)
})
})
describe('Icon functionality', () => {
test('renders icon when iconName is provided', async () => {
const { link } = await createLinkTest({
href: '#',
iconName: 'arrow-right',
})
await link.updateComplete
const icon = link.querySelector('pkt-icon')
expect(icon).toBeInTheDocument()
expect(icon?.getAttribute('name')).toBe('arrow-right')
})
test('positions icon correctly', async () => {
const { link } = await createLinkTest({
href: '#',
iconName: 'arrow-right',
iconPosition: 'right',
})
await link.updateComplete
const anchor = link.querySelector('a')
expect(anchor?.classList.contains('pkt-link--icon-right')).toBe(true)
})
})
describe('External link functionality', () => {
test('applies external class and rel attribute', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
external: true,
})
await link.updateComplete
const anchor = link.querySelector('a')
expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
expect(anchor?.rel).toBe('noopener noreferrer')
})
test('does not set rel attribute for internal links', async () => {
const { link } = await createLinkTest({
href: '/internal-page',
})
await link.updateComplete
const anchor = link.querySelector('a')
expect(anchor?.rel).toBe('')
})
})
describe('Event handling', () => {
test('handles click events', async () => {
const { link } = await createLinkTest({
href: '#test',
})
await link.updateComplete
const anchor = link.querySelector('a')
const clickHandler = vi.fn()
anchor?.addEventListener('click', clickHandler)
fireEvent.click(anchor!)
expect(clickHandler).toHaveBeenCalled()
})
})
describe('Dynamic updates', () => {
test('updates href dynamically', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
})
await link.updateComplete
link.href = 'https://updated.com'
await link.updateComplete
expect(link.href).toBe('https://updated.com')
const anchor = link.querySelector('a')
expect(anchor?.href).toBe('https://updated.com/')
})
test('updates external property dynamically', async () => {
const { link } = await createLinkTest({
href: 'https://example.com',
})
await link.updateComplete
link.external = true
await link.updateComplete
expect(link.external).toBe(true)
const anchor = link.querySelector('a')
expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
expect(anchor?.rel).toBe('noopener noreferrer')
})
})
describe('Accessibility', () => {
test('basic link is accessible', async () => {
const { container } = await createLinkTest({
href: 'https://example.com',
content: 'Accessible Link',
})
await new Promise((resolve) => setTimeout(resolve, 100))
const results = await axe(container)
expect(results).toHaveNoViolations()
})
})
describe('Integration scenarios', () => {
test('works with complex configurations', async () => {
const { link } = await createLinkTest({
href: 'https://external-site.com',
iconName: 'external',
iconPosition: 'right',
external: true,
target: '_blank',
content: 'Complex External Link',
})
await link.updateComplete
expect(link.href).toBe('https://external-site.com')
expect(link.iconName).toBe('external')
expect(link.external).toBe(true)
expect(link.target).toBe('_blank')
const anchor = link.querySelector('a')
expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
expect(anchor?.classList.contains('pkt-link--icon-right')).toBe(true)
})
})
})