@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
274 lines (208 loc) • 9.22 kB
text/typescript
import '@testing-library/jest-dom'
import { fireEvent } from '@testing-library/dom'
import { parseISODateString } from 'shared-utils/date-utils'
import './calendar'
import { PktCalendar } from './calendar'
const waitForCustomElements = async () => {
await customElements.whenDefined('pkt-calendar')
}
// Helper function to create calendar markup
const createCalendar = async (calendarProps = '') => {
const container = document.createElement('div')
container.innerHTML = `
<pkt-calendar ${calendarProps}></pkt-calendar>
`
document.body.appendChild(container)
await waitForCustomElements()
return container
}
// Cleanup after each test
afterEach(() => {
document.body.innerHTML = ''
})
describe('PktCalendar', () => {
describe('Date selection functionality', () => {
test('selects single date correctly', async () => {
const container = await createCalendar()
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
// Find and click on a date
const availableDate = calendar.querySelector(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
expect(availableDate).toBeInTheDocument()
fireEvent.click(availableDate!)
await calendar.updateComplete
expect(availableDate).toHaveClass('pkt-calendar__date--selected')
})
test('handles multiple date selection', async () => {
const container = await createCalendar('multiple')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
// Find and click on multiple dates
const availableDates = calendar.querySelectorAll(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
expect(availableDates.length).toBeGreaterThan(1)
fireEvent.click(availableDates[0])
await calendar.updateComplete
fireEvent.click(availableDates[1])
await calendar.updateComplete
expect(availableDates[0]).toHaveClass('pkt-calendar__date--selected')
expect(availableDates[1]).toHaveClass('pkt-calendar__date--selected')
})
test('respects maxMultiple limit', async () => {
const container = await createCalendar('multiple max-multiple="2"')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
// Try to select more than maxMultiple dates
const availableDates = calendar.querySelectorAll(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
expect(availableDates.length).toBeGreaterThan(2)
// Select 3 dates but only 2 should be selected
fireEvent.click(availableDates[0])
await calendar.updateComplete
fireEvent.click(availableDates[1])
await calendar.updateComplete
fireEvent.click(availableDates[2])
await calendar.updateComplete
const selectedDates = calendar.querySelectorAll('.pkt-calendar__date--selected')
expect(selectedDates.length).toBeLessThanOrEqual(2)
})
test('handles pre-selected dates', async () => {
const preSelectedDates = '2024-06-15,2024-06-20'
const container = await createCalendar(
`selected="${preSelectedDates}" currentmonth="2024-06-01"`,
)
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
expect(calendar.selected).toEqual(['2024-06-15', '2024-06-20'])
const selectedDates = calendar.querySelectorAll('.pkt-calendar__date--selected')
expect(selectedDates.length).toBe(2)
})
test('toggles date selection when clicking same date twice', async () => {
const container = await createCalendar()
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const availableDate = calendar.querySelector(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
expect(availableDate).toBeInTheDocument()
// First click - select
fireEvent.click(availableDate!)
await calendar.updateComplete
expect(availableDate).toHaveClass('pkt-calendar__date--selected')
// Second click - deselect
fireEvent.click(availableDate!)
await calendar.updateComplete
expect(availableDate).not.toHaveClass('pkt-calendar__date--selected')
})
})
describe('Range selection functionality', () => {
test('handles range selection correctly', async () => {
const container = await createCalendar('range')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const availableDates = calendar.querySelectorAll(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
expect(availableDates.length).toBeGreaterThan(3)
// Select start date
fireEvent.click(availableDates[5])
await calendar.updateComplete
// Select end date
fireEvent.click(availableDates[10])
await calendar.updateComplete
// Check for range styling
const rangeStart = calendar.querySelector('.pkt-calendar__date--range-start')
const rangeEnd = calendar.querySelector('.pkt-calendar__date--range-end')
const rangeInBetween = calendar.querySelectorAll('.pkt-calendar__date--in-range')
expect(rangeStart).toBeInTheDocument()
expect(rangeEnd).toBeInTheDocument()
expect(rangeInBetween.length).toBeGreaterThan(0)
})
test('shows range hover preview', async () => {
const container = await createCalendar('range')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const availableDates = calendar.querySelectorAll(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
// Select start date
fireEvent.click(availableDates[5])
await calendar.updateComplete
// Hover over potential end date
fireEvent.mouseOver(availableDates[10])
await calendar.updateComplete
// Should show hover preview styling
const hoveredRanges = calendar.querySelectorAll('.pkt-calendar__date--in-range-hover')
expect(hoveredRanges.length).toBeGreaterThan(0)
})
test('clears range when selecting new start date', async () => {
const container = await createCalendar('range')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const availableDates = calendar.querySelectorAll(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
// Create initial range
fireEvent.click(availableDates[5])
await calendar.updateComplete
fireEvent.click(availableDates[10])
await calendar.updateComplete
// Select new start date
fireEvent.click(availableDates[2])
await calendar.updateComplete
// Old range should be cleared
const selectedDates = calendar.querySelectorAll('.pkt-calendar__date--selected')
expect(selectedDates.length).toBe(1)
})
})
describe('API methods', () => {
test('addToSelected method works correctly', async () => {
const container = await createCalendar('multiple')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const testDate = parseISODateString('2024-06-15')
calendar.addToSelected(testDate)
await calendar.updateComplete
expect(calendar['_selected']).toContainEqual(testDate)
})
test('removeFromSelected method works correctly', async () => {
const container = await createCalendar('multiple')
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const testDate = new Date('2024-06-15')
calendar.addToSelected(testDate)
await calendar.updateComplete
calendar.removeFromSelected(testDate)
await calendar.updateComplete
expect(calendar['_selected']).not.toContainEqual(testDate)
})
test('toggleSelected method works correctly', async () => {
const container = await createCalendar()
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
const testDate = parseISODateString('2024-06-15')
// Toggle on
calendar.toggleSelected(testDate)
await calendar.updateComplete
expect(calendar['_selected']).toContainEqual(testDate)
// Toggle off
calendar.toggleSelected(testDate)
await calendar.updateComplete
expect(calendar['_selected']).not.toContainEqual(testDate)
})
test('focusOnCurrentDate method works correctly', async () => {
const container = await createCalendar()
const calendar = container.querySelector('pkt-calendar') as PktCalendar
await calendar.updateComplete
calendar.focusOnCurrentDate()
await calendar.updateComplete
// Should focus on a date element
const focusedElement = document.activeElement
expect(focusedElement).toHaveClass('pkt-calendar__date')
})
})
})