@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
325 lines (243 loc) • 11.7 kB
text/typescript
import '@testing-library/jest-dom'
import { toHaveNoViolations } from 'jest-axe'
import { fireEvent } from '@testing-library/dom'
import { parseISODateString } from 'shared-utils/date-utils'
expect.extend(toHaveNoViolations)
import './datepicker'
import '../calendar/calendar'
import { PktDatepicker } from './datepicker'
import { PktCalendar } from '../calendar/calendar'
import { PktDatepickerPopup } from './datepicker-popup'
const waitForCustomElements = async () => {
await customElements.whenDefined('pkt-datepicker')
await customElements.whenDefined('pkt-calendar')
}
// Helper function to create datepicker markup
const createDatepicker = async (datepickerProps = '') => {
const container = document.createElement('div')
container.innerHTML = `
<pkt-datepicker ${datepickerProps}></pkt-datepicker>
`
document.body.appendChild(container)
await waitForCustomElements()
return container
}
// Cleanup after each test
afterEach(() => {
document.body.innerHTML = ''
})
describe('PktDatepicker', () => {
describe('Rendering and basic functionality', () => {
test('renders without errors', async () => {
const container = await createDatepicker()
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
expect(datepicker).toBeInTheDocument()
await datepicker.updateComplete
expect(datepicker).toBeTruthy()
})
test('renders with correct structure', async () => {
const container = await createDatepicker('label="Test Datepicker"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
const inputWrapper = datepicker.querySelector('pkt-input-wrapper')
const input = datepicker.querySelector('input')
const calendarButton = datepicker.querySelector('button[type="button"]')
expect(inputWrapper).toBeInTheDocument()
expect(input).toBeInTheDocument()
expect(calendarButton).toBeInTheDocument()
})
test('renders calendar when opened', async () => {
const container = await createDatepicker('label="Test Datepicker"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
const calendar = datepicker.querySelector('pkt-calendar')
expect(calendar).toBeInTheDocument()
})
test('closes calendar when clicking outside', async () => {
const container = await createDatepicker('label="Test Datepicker"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
// Open calendar
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
// Click outside
fireEvent.click(document.body)
await datepicker.updateComplete
expect(datepicker.calendarOpen).toBe(false)
})
test('closes calendar when clicking outside', async () => {
const container = await createDatepicker('label="Test Datepicker"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
// Open calendar
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
// Click outside
fireEvent.click(document.body)
await datepicker.updateComplete
expect(datepicker.calendarOpen).toBe(false)
})
})
describe('Properties and attributes', () => {
test('applies default properties correctly', async () => {
const container = await createDatepicker('name="test" id="test"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.value).toBe('')
expect(datepicker.label).toBe('Datovelger')
expect(datepicker.multiple).toBe(false)
expect(datepicker.range).toBe(false)
expect(datepicker.maxlength).toBe(null)
expect(datepicker.showRangeLabels).toBe(false)
})
test('handles value property correctly', async () => {
const testDate = '2024-06-15'
const container = await createDatepicker(`value="${testDate}"`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.value).toBe(testDate)
const input = datepicker.querySelector('input') as HTMLInputElement
expect(input.value).toBeTruthy()
})
test('handles multiple values correctly', async () => {
const testDates = '2024-06-15,2024-06-20,2024-06-25'
const container = await createDatepicker(`value="${testDates}" multiple`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.value).toBe(testDates)
expect(datepicker.multiple).toBe(true)
// Should show tags for multiple values
const tags = datepicker.querySelectorAll('pkt-tag')
expect(tags.length).toBe(3)
})
test('handles range values correctly', async () => {
const rangeValue = '2024-06-15,2024-06-20'
const container = await createDatepicker(`value="${rangeValue}" range`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.value).toBe(rangeValue)
expect(datepicker.range).toBe(true)
})
test('handles label property correctly', async () => {
const testLabel = 'Select your date'
const container = await createDatepicker(`label="${testLabel}"`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.label).toBe(testLabel)
const label = datepicker.querySelector('label')
expect(label?.textContent).toContain(testLabel)
})
test('handles dateformat property correctly', async () => {
const customFormat = 'MM/dd/yyyy'
const container = await createDatepicker(
`dateformat="${customFormat}" value="2024-06-15" multiple`,
)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.dateformat).toBe(customFormat)
// Multiple mode input should be empty (for new input)
const input = datepicker.querySelector('input') as HTMLInputElement
expect(input.value).toBe('')
// Selected dates should show in tags with custom format
const tag = datepicker.querySelector('pkt-tag time')
expect(tag).toBeInTheDocument()
if (tag) {
expect(tag.textContent).toMatch(/\d{2}\/\d{2}\/\d{4}/)
}
})
test('handles maxlength property correctly', async () => {
const container = await createDatepicker('multiple maxlength="3"')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.maxlength).toBe(3)
})
test('handles disabled property correctly', async () => {
const container = await createDatepicker('disabled')
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
expect(datepicker.disabled).toBe(true)
const input = datepicker.querySelector('input') as HTMLInputElement
const calendarButton = datepicker.querySelector('button[type="button"]') as HTMLButtonElement
expect(input.disabled).toBe(true)
expect(calendarButton.disabled).toBe(true)
})
test('handles currentmonth property correctly', async () => {
const testMonth = '2024-03-01'
const container = await createDatepicker(`currentmonth="${testMonth}"`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
// Open calendar to see the month
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
const calendar = datepicker.querySelector('pkt-calendar') as PktCalendar
expect(calendar.currentmonth).toEqual(parseISODateString(testMonth))
})
})
describe('Calendar integration', () => {
test('passes properties to calendar correctly', async () => {
const container = await createDatepicker(
'min="2024-06-01" max="2024-06-30" excludeweekdays="0,6"',
)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
// Open calendar
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
const calendar = datepicker.querySelector('pkt-calendar') as PktCalendar
expect(calendar.earliest).toBe('2024-06-01')
expect(calendar.latest).toBe('2024-06-30')
expect(calendar.excludeweekdays).toEqual(['0', '6'])
})
test('syncs selected dates between input and calendar', async () => {
const testDate = '2024-06-15'
const container = await createDatepicker(`value="${testDate}" calendar-open`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
const popup = datepicker.querySelector('pkt-datepicker-popup') as PktDatepickerPopup
await popup?.updateComplete
const calendar = datepicker.querySelector('pkt-calendar') as PktCalendar
await calendar?.updateComplete
expect(calendar.selected).toContain(testDate)
const selectedDate = datepicker.querySelector('.pkt-calendar__date--selected')
expect(selectedDate).toBeInTheDocument()
})
test('updates input when date selected in calendar', async () => {
const container = await createDatepicker()
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
// Open calendar
const calendarButton = datepicker.querySelector('button[type="button"]')
fireEvent.click(calendarButton!)
await datepicker.updateComplete
// Select a date
const availableDate = datepicker.querySelector(
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
)
fireEvent.click(availableDate!)
await datepicker.updateComplete
// Input should be updated
const input = datepicker.querySelector('input') as HTMLInputElement
expect(input.value).toBeTruthy()
expect(datepicker.value).toBeTruthy()
})
test('shows current month correctly in calendar', async () => {
const currentMonth = '2024-06-01'
const container = await createDatepicker(`currentmonth="${currentMonth}" calendar-open`)
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
await datepicker.updateComplete
const popup = datepicker.querySelector('pkt-datepicker-popup') as PktDatepickerPopup
await popup?.updateComplete
const calendar = datepicker.querySelector('pkt-calendar') as PktCalendar
await calendar?.updateComplete
const monthTitle = datepicker.querySelector('.pkt-calendar__month-title')
expect(monthTitle?.textContent).toContain('2024')
})
})
})