@oslokommune/punkt-react 14.5.4 → 15.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/index.d.ts +64 -21
  3. package/dist/punkt-react.es.js +7202 -4676
  4. package/dist/punkt-react.umd.js +573 -569
  5. package/package.json +5 -5
  6. package/src/components/calendar/Calendar.accessibility.test.tsx +75 -0
  7. package/src/components/calendar/Calendar.constraints.test.tsx +84 -0
  8. package/src/components/calendar/Calendar.core.test.tsx +272 -0
  9. package/src/components/calendar/Calendar.interaction.test.tsx +96 -0
  10. package/src/components/calendar/Calendar.selection.test.tsx +227 -0
  11. package/src/components/calendar/Calendar.tsx +54 -0
  12. package/src/components/calendar/CalendarGrid.tsx +192 -0
  13. package/src/components/calendar/CalendarNav.tsx +111 -0
  14. package/src/components/calendar/calendar-utils.ts +90 -0
  15. package/src/components/calendar/types.ts +160 -0
  16. package/src/components/calendar/useCalendarState.ts +426 -0
  17. package/src/components/datepicker/DateTags.tsx +43 -0
  18. package/src/components/datepicker/Datepicker.accessibility.test.tsx +404 -0
  19. package/src/components/datepicker/Datepicker.core.test.tsx +270 -0
  20. package/src/components/datepicker/Datepicker.input.test.tsx +218 -0
  21. package/src/components/datepicker/Datepicker.selection.test.tsx +302 -0
  22. package/src/components/datepicker/Datepicker.tsx +69 -79
  23. package/src/components/datepicker/Datepicker.validation.test.tsx +317 -0
  24. package/src/components/datepicker/DatepickerInputs.tsx +184 -0
  25. package/src/components/datepicker/DatepickerPopup.tsx +90 -0
  26. package/src/components/datepicker/types.ts +142 -0
  27. package/src/components/datepicker/useDatepickerState.ts +514 -0
  28. package/src/components/index.ts +1 -0
  29. package/src/components/tag/Tag.tsx +1 -1
  30. package/src/components/datepicker/Datepicker.test.tsx +0 -395
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-react",
3
- "version": "14.5.4",
3
+ "version": "15.0.1",
4
4
  "description": "React komponentbibliotek til Punkt, et designsystem laget av Oslo Origo",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo Origo",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@lit-labs/ssr-dom-shim": "^1.2.1",
41
41
  "@lit/react": "^1.0.7",
42
- "@oslokommune/punkt-elements": "^14.5.4",
42
+ "@oslokommune/punkt-elements": "^15.0.1",
43
43
  "classnames": "^2.5.1",
44
44
  "prettier": "^3.3.3",
45
45
  "react-hook-form": "^7.53.0"
@@ -49,8 +49,8 @@
49
49
  "@eslint/compat": "^2.0.2",
50
50
  "@eslint/eslintrc": "^3.3.3",
51
51
  "@eslint/js": "^9.37.0",
52
- "@oslokommune/punkt-assets": "^14.1.1",
53
- "@oslokommune/punkt-css": "^14.5.3",
52
+ "@oslokommune/punkt-assets": "^15.0.0",
53
+ "@oslokommune/punkt-css": "^15.0.1",
54
54
  "@testing-library/jest-dom": "^6.5.0",
55
55
  "@testing-library/react": "^16.0.1",
56
56
  "@testing-library/user-event": "^14.5.2",
@@ -109,5 +109,5 @@
109
109
  "url": "https://github.com/oslokommune/punkt/issues"
110
110
  },
111
111
  "license": "MIT",
112
- "gitHead": "be4a01f06388571ca22a28c90fa518e1a6dff097"
112
+ "gitHead": "e4a75d4efe0a17688bdba0071e12cb789ae430c2"
113
113
  }
@@ -0,0 +1,75 @@
1
+ import '@testing-library/jest-dom'
2
+ import { render, fireEvent } from '@testing-library/react'
3
+ import { axe, toHaveNoViolations } from 'jest-axe'
4
+
5
+ import { PktCalendar, IPktCalendar } from './Calendar'
6
+
7
+ expect.extend(toHaveNoViolations)
8
+
9
+ const createCalendar = (props: Partial<IPktCalendar> = {}) => {
10
+ return render(<PktCalendar {...props} />)
11
+ }
12
+
13
+ describe('PktCalendar', () => {
14
+ describe('Accessibility', () => {
15
+ test('has no accessibility violations', async () => {
16
+ const { container } = createCalendar({ withcontrols: true, weeknumbers: true })
17
+
18
+ const results = await axe(container)
19
+ expect(results).toHaveNoViolations()
20
+ })
21
+
22
+ test('has proper ARIA attributes', () => {
23
+ const { container } = createCalendar({ withcontrols: true })
24
+
25
+ const calendarTable = container.querySelector('.pkt-calendar__body')
26
+ expect(calendarTable).toHaveAttribute('role', 'grid')
27
+
28
+ const dateButtons = container.querySelectorAll('.pkt-calendar__date')
29
+ dateButtons.forEach((button) => {
30
+ expect(button).toHaveAttribute('aria-pressed')
31
+ expect(button).toHaveAttribute('tabindex')
32
+ })
33
+ })
34
+
35
+ test('navigation buttons have proper labels', () => {
36
+ const { container } = createCalendar({ withcontrols: true })
37
+
38
+ const prevButton = container.querySelector('.pkt-calendar__prev-month')
39
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
40
+
41
+ expect(prevButton).toHaveAttribute('aria-label')
42
+ expect(nextButton).toHaveAttribute('aria-label')
43
+ })
44
+
45
+ test('date buttons have proper accessible names', () => {
46
+ const { container } = createCalendar()
47
+
48
+ const dateButtons = container.querySelectorAll('.pkt-calendar__date')
49
+ dateButtons.forEach((button) => {
50
+ expect(button).toHaveAttribute('aria-label')
51
+ expect(button.getAttribute('aria-label')).toBeTruthy()
52
+ })
53
+ })
54
+
55
+ test('selected dates have proper ARIA state', () => {
56
+ const { container } = createCalendar()
57
+
58
+ const firstDate = container.querySelector(
59
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
60
+ )
61
+ fireEvent.click(firstDate!)
62
+
63
+ expect(firstDate).toHaveAttribute('aria-pressed', 'true')
64
+ })
65
+
66
+ test('disabled dates have proper ARIA state', () => {
67
+ const { container } = createCalendar({ excludeweekdays: ['0', '6'] })
68
+
69
+ const disabledDates = container.querySelectorAll('.pkt-calendar__date--disabled')
70
+ disabledDates.forEach((date) => {
71
+ expect(date).toHaveAttribute('disabled')
72
+ })
73
+ })
74
+ })
75
+ })
@@ -0,0 +1,84 @@
1
+ import '@testing-library/jest-dom'
2
+ import { render } from '@testing-library/react'
3
+
4
+ import { PktCalendar, IPktCalendar } from './Calendar'
5
+
6
+ const createCalendar = (props: Partial<IPktCalendar> = {}) => {
7
+ return render(<PktCalendar {...props} />)
8
+ }
9
+
10
+ describe('PktCalendar', () => {
11
+ describe('Date range functionality', () => {
12
+ test('handles earliest date property correctly', () => {
13
+ const { container } = createCalendar({
14
+ earliest: '2024-01-15',
15
+ currentmonth: '2024-01-01',
16
+ })
17
+
18
+ // Check that dates before earliest are disabled (dates 1-14 should be disabled)
19
+ const disabledDates = container.querySelectorAll('.pkt-calendar__date--disabled')
20
+ expect(disabledDates.length).toBeGreaterThan(0)
21
+ })
22
+
23
+ test('handles latest date property correctly', () => {
24
+ const { container } = createCalendar({ latest: '2024-12-15' })
25
+
26
+ // Should render without errors
27
+ expect(container.querySelector('.pkt-calendar')).toBeInTheDocument()
28
+ })
29
+
30
+ test('restricts selectable dates between earliest and latest', () => {
31
+ const { container } = createCalendar({
32
+ earliest: '2024-06-10',
33
+ latest: '2024-06-20',
34
+ currentmonth: '2024-06-01',
35
+ })
36
+
37
+ const enabledDates = container.querySelectorAll(
38
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
39
+ )
40
+ const disabledDates = container.querySelectorAll('.pkt-calendar__date--disabled')
41
+
42
+ expect(enabledDates.length).toBeGreaterThan(0)
43
+ expect(disabledDates.length).toBeGreaterThan(0)
44
+ })
45
+ })
46
+
47
+ describe('Date exclusion functionality', () => {
48
+ test('excludes specific dates correctly', () => {
49
+ const { container } = createCalendar({
50
+ excludedates: ['2024-06-15', '2024-06-20'],
51
+ currentmonth: '2024-06-01',
52
+ })
53
+
54
+ // The excluded dates should be disabled
55
+ const date15 = container.querySelector('button[data-date="2024-06-15"]')
56
+ const date20 = container.querySelector('button[data-date="2024-06-20"]')
57
+ expect(date15).toHaveClass('pkt-calendar__date--disabled')
58
+ expect(date20).toHaveClass('pkt-calendar__date--disabled')
59
+ })
60
+
61
+ test('excludes weekdays correctly', () => {
62
+ const { container } = createCalendar({ excludeweekdays: ['0', '6'] })
63
+
64
+ // Check that weekend dates are disabled
65
+ const disabledDates = container.querySelectorAll('.pkt-calendar__date--disabled')
66
+ expect(disabledDates.length).toBeGreaterThan(0)
67
+ })
68
+
69
+ test('excludes both specific dates and weekdays', () => {
70
+ const { container } = createCalendar({
71
+ excludedates: ['2024-06-15'],
72
+ excludeweekdays: ['0', '6'],
73
+ currentmonth: '2024-06-01',
74
+ })
75
+
76
+ // Both specific dates and weekends should be disabled
77
+ const disabledDates = container.querySelectorAll('.pkt-calendar__date--disabled')
78
+ expect(disabledDates.length).toBeGreaterThan(0)
79
+
80
+ const date15 = container.querySelector('button[data-date="2024-06-15"]')
81
+ expect(date15).toHaveClass('pkt-calendar__date--disabled')
82
+ })
83
+ })
84
+ })
@@ -0,0 +1,272 @@
1
+ import '@testing-library/jest-dom'
2
+ import { render, fireEvent } from '@testing-library/react'
3
+ import { parseISODateString } from 'shared-utils/date-utils'
4
+
5
+ import { PktCalendar, IPktCalendar } from './Calendar'
6
+
7
+ const createCalendar = (props: Partial<IPktCalendar> = {}) => {
8
+ return render(<PktCalendar {...props} />)
9
+ }
10
+
11
+ describe('PktCalendar', () => {
12
+ describe('Rendering and basic functionality', () => {
13
+ test('renders without errors', () => {
14
+ const { container } = createCalendar()
15
+
16
+ const calendarElement = container.querySelector('.pkt-calendar')
17
+ expect(calendarElement).toBeInTheDocument()
18
+ })
19
+
20
+ test('renders with correct structure', () => {
21
+ const { container } = createCalendar()
22
+
23
+ const calendarElement = container.querySelector('.pkt-calendar')
24
+ const calendarTable = container.querySelector('.pkt-cal-days')
25
+ const monthNav = container.querySelector('.pkt-cal-month-nav')
26
+
27
+ expect(calendarElement).toBeInTheDocument()
28
+ expect(calendarTable).toBeInTheDocument()
29
+ expect(monthNav).toBeInTheDocument()
30
+ })
31
+
32
+ test('renders month picker when withcontrols is true', () => {
33
+ const { container } = createCalendar({ withcontrols: true })
34
+
35
+ // Navigation buttons should always be present
36
+ const prevButton = container.querySelector('.pkt-calendar__prev-month')
37
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
38
+ expect(prevButton).toBeInTheDocument()
39
+ expect(nextButton).toBeInTheDocument()
40
+
41
+ // Should show month picker controls, not static title
42
+ const monthPicker = container.querySelector('.pkt-cal-month-picker')
43
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
44
+
45
+ expect(monthPicker).toBeInTheDocument()
46
+ expect(monthTitle).not.toBeInTheDocument()
47
+
48
+ // Should have month and year inputs
49
+ const monthSelect = monthPicker?.querySelector('select')
50
+ const yearInput = monthPicker?.querySelector('input[type="number"]')
51
+ expect(monthSelect).toBeInTheDocument()
52
+ expect(yearInput).toBeInTheDocument()
53
+ })
54
+
55
+ test('renders static month title when withcontrols is false', () => {
56
+ const { container } = createCalendar()
57
+
58
+ // Navigation buttons should always be present
59
+ const prevButton = container.querySelector('.pkt-calendar__prev-month')
60
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
61
+ expect(prevButton).toBeInTheDocument()
62
+ expect(nextButton).toBeInTheDocument()
63
+
64
+ // Should show static month title, not controls
65
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
66
+ const monthPicker = container.querySelector('.pkt-cal-month-picker')
67
+
68
+ expect(monthTitle).toBeInTheDocument()
69
+ expect(monthPicker).not.toBeInTheDocument()
70
+ })
71
+ })
72
+
73
+ describe('Properties and attributes', () => {
74
+ test('applies default properties correctly', () => {
75
+ const { container } = createCalendar()
76
+
77
+ // Verify defaults through DOM effects
78
+ const grid = container.querySelector('[role="grid"]')
79
+ expect(grid).not.toHaveAttribute('aria-multiselectable')
80
+
81
+ // No week numbers by default
82
+ const weekNumbers = container.querySelectorAll('.pkt-calendar__week-number')
83
+ expect(weekNumbers.length).toBe(0)
84
+
85
+ // No month picker by default
86
+ const monthPicker = container.querySelector('.pkt-cal-month-picker')
87
+ expect(monthPicker).not.toBeInTheDocument()
88
+
89
+ // No selected dates
90
+ const selectedDates = container.querySelectorAll('.pkt-calendar__date--selected')
91
+ expect(selectedDates.length).toBe(0)
92
+ })
93
+
94
+ test('handles multiple property correctly', () => {
95
+ const { container } = createCalendar({ multiple: true })
96
+
97
+ const grid = container.querySelector('[role="grid"]')
98
+ expect(grid).toHaveAttribute('aria-multiselectable', 'true')
99
+ })
100
+
101
+ test('handles range property correctly', () => {
102
+ const { container } = createCalendar({ range: true })
103
+
104
+ const grid = container.querySelector('[role="grid"]')
105
+ expect(grid).toHaveAttribute('aria-multiselectable', 'true')
106
+ })
107
+
108
+ test('handles weeknumbers property correctly', () => {
109
+ const { container } = createCalendar({ weeknumbers: true })
110
+
111
+ const weekNumbers = container.querySelectorAll('.pkt-calendar__week-number')
112
+ expect(weekNumbers.length).toBeGreaterThan(0)
113
+ })
114
+
115
+ test('handles maxMultiple property correctly', () => {
116
+ const { container } = createCalendar({ multiple: true, maxMultiple: 3 })
117
+
118
+ const grid = container.querySelector('[role="grid"]')
119
+ expect(grid).toHaveAttribute('aria-multiselectable', 'true')
120
+
121
+ // Select 3 dates - all should work
122
+ const availableDates = container.querySelectorAll(
123
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
124
+ )
125
+ expect(availableDates.length).toBeGreaterThan(3)
126
+
127
+ fireEvent.click(availableDates[0])
128
+ fireEvent.click(availableDates[1])
129
+ fireEvent.click(availableDates[2])
130
+
131
+ const selectedDates = container.querySelectorAll('.pkt-calendar__date--selected')
132
+ expect(selectedDates.length).toBe(3)
133
+ })
134
+
135
+ test('handles currentmonth property correctly', () => {
136
+ const { container } = createCalendar({ currentmonth: '2024-03-15' })
137
+
138
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
139
+ expect(monthTitle?.textContent).toContain('Mars')
140
+ expect(monthTitle?.textContent).toContain('2024')
141
+ })
142
+ })
143
+
144
+ describe('Month navigation', () => {
145
+ it('should navigate to previous month when clicking previous button', () => {
146
+ const { container } = createCalendar({ currentmonth: '2024-06-15' })
147
+
148
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
149
+ expect(monthTitle?.textContent).toContain('Juni')
150
+
151
+ const prevButton = container.querySelector('.pkt-calendar__prev-month')
152
+ fireEvent.click(prevButton!)
153
+
154
+ expect(monthTitle?.textContent).toContain('Mai')
155
+ })
156
+
157
+ it('should navigate to next month when clicking next button', () => {
158
+ const { container } = createCalendar({ currentmonth: '2024-06-15' })
159
+
160
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
161
+ expect(monthTitle?.textContent).toContain('Juni')
162
+
163
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
164
+ fireEvent.click(nextButton!)
165
+
166
+ expect(monthTitle?.textContent).toContain('Juli')
167
+ })
168
+
169
+ test('navigates to next month with controls', () => {
170
+ const { container } = createCalendar({ withcontrols: true, currentmonth: '2024-06-15' })
171
+
172
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
173
+ expect(nextButton).toBeInTheDocument()
174
+
175
+ const monthSelect = container.querySelector(
176
+ '.pkt-cal-month-picker select',
177
+ ) as HTMLSelectElement
178
+ const initialMonth = monthSelect?.value
179
+
180
+ fireEvent.click(nextButton!)
181
+
182
+ const newMonth = monthSelect?.value
183
+ expect(newMonth).not.toBe(initialMonth)
184
+ })
185
+
186
+ test('month navigation updates visible dates', () => {
187
+ const { container } = createCalendar({ withcontrols: true, currentmonth: '2024-06-15' })
188
+
189
+ const initialDates = Array.from(container.querySelectorAll('.pkt-calendar__date')).map(
190
+ (el) => el.textContent,
191
+ )
192
+
193
+ const nextButton = container.querySelector('.pkt-calendar__next-month')
194
+ fireEvent.click(nextButton!)
195
+
196
+ const newDates = Array.from(container.querySelectorAll('.pkt-calendar__date')).map(
197
+ (el) => el.textContent,
198
+ )
199
+ expect(newDates).not.toEqual(initialDates)
200
+ })
201
+ })
202
+
203
+ describe('Date formatting and localization', () => {
204
+ test('displays day names correctly', () => {
205
+ const { container } = createCalendar()
206
+
207
+ const dayHeaders = container.querySelectorAll('.pkt-calendar__day-name')
208
+ expect(dayHeaders.length).toBe(7)
209
+
210
+ dayHeaders.forEach((header) => {
211
+ expect(header.textContent).toBeTruthy()
212
+ expect(header.textContent!.length).toBeGreaterThan(0)
213
+ })
214
+ })
215
+
216
+ test('displays month names correctly', () => {
217
+ const { container } = createCalendar({ currentmonth: '2024-06-15' })
218
+
219
+ const monthTitle = container.querySelector('.pkt-calendar__month-title')
220
+ expect(monthTitle).toBeInTheDocument()
221
+ expect(monthTitle?.textContent).toBeTruthy()
222
+ })
223
+
224
+ test('handles custom day strings', () => {
225
+ const { container } = createCalendar({
226
+ strings: { daysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'] },
227
+ })
228
+
229
+ const dayHeaders = container.querySelectorAll('.pkt-calendar__day-name')
230
+ expect(dayHeaders[0].textContent?.trim()).toBe('S')
231
+ expect(dayHeaders[1].textContent?.trim()).toBe('M')
232
+ })
233
+
234
+ test('handles custom month strings', () => {
235
+ const { container } = createCalendar({
236
+ withcontrols: true,
237
+ strings: {
238
+ months: [
239
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
240
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
241
+ ],
242
+ },
243
+ })
244
+
245
+ const monthSelect = container.querySelector('.pkt-cal-month-picker select')
246
+ expect(monthSelect).toBeInTheDocument()
247
+
248
+ const options = monthSelect?.querySelectorAll('option')
249
+ expect(options?.[0]?.textContent).toContain('Jan')
250
+ })
251
+ })
252
+
253
+ describe('Today highlighting', () => {
254
+ test('highlights today date', () => {
255
+ const { container } = createCalendar()
256
+
257
+ const todayDate = container.querySelector('.pkt-calendar__date--today')
258
+ expect(todayDate).toBeInTheDocument()
259
+ })
260
+
261
+ test('today date is selectable unless excluded', () => {
262
+ const { container } = createCalendar()
263
+
264
+ const todayDate = container.querySelector('.pkt-calendar__date--today')
265
+
266
+ if (todayDate && !todayDate.classList.contains('pkt-calendar__date--disabled')) {
267
+ fireEvent.click(todayDate)
268
+ expect(todayDate).toHaveClass('pkt-calendar__date--selected')
269
+ }
270
+ })
271
+ })
272
+ })
@@ -0,0 +1,96 @@
1
+ import '@testing-library/jest-dom'
2
+ import { render, fireEvent, act } from '@testing-library/react'
3
+
4
+ import { PktCalendar, IPktCalendar } from './Calendar'
5
+
6
+ const createCalendar = (props: Partial<IPktCalendar> = {}) => {
7
+ return render(<PktCalendar {...props} />)
8
+ }
9
+
10
+ describe('PktCalendar', () => {
11
+ describe('Keyboard navigation', () => {
12
+ test('handles arrow key navigation', () => {
13
+ const { container } = createCalendar()
14
+
15
+ const firstDate = container.querySelector(
16
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
17
+ ) as HTMLElement
18
+
19
+ act(() => {
20
+ firstDate?.focus()
21
+ fireEvent.keyDown(firstDate!, { key: 'ArrowRight' })
22
+ })
23
+
24
+ // Check that focus moved (implementation dependent)
25
+ expect(document.activeElement).toBeTruthy()
26
+ })
27
+
28
+ test('handles enter key for date selection', () => {
29
+ const { container } = createCalendar()
30
+
31
+ const firstDate = container.querySelector(
32
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
33
+ ) as HTMLElement
34
+
35
+ act(() => {
36
+ firstDate?.focus()
37
+ fireEvent.keyDown(firstDate!, { key: 'Enter' })
38
+ })
39
+
40
+ expect(firstDate).toHaveClass('pkt-calendar__date--selected')
41
+ })
42
+
43
+ test('handles escape key', () => {
44
+ const onClose = jest.fn()
45
+ const { container } = createCalendar({ onClose })
46
+
47
+ const calendarEl = container.querySelector('.pkt-calendar') as HTMLElement
48
+ fireEvent.keyDown(calendarEl, { key: 'Escape' })
49
+
50
+ // Should trigger close callback
51
+ expect(onClose).toHaveBeenCalled()
52
+ })
53
+ })
54
+
55
+ describe('Edge cases and error handling', () => {
56
+ test('handles invalid date formats gracefully', () => {
57
+ const { container } = createCalendar({ earliest: 'invalid-date', latest: 'also-invalid' })
58
+
59
+ // Should not crash and render normally
60
+ expect(container.querySelector('.pkt-calendar')).toBeInTheDocument()
61
+ const calendarBody = container.querySelector('.pkt-calendar__body')
62
+ expect(calendarBody).toBeInTheDocument()
63
+ })
64
+
65
+ test('handles empty selected dates array', () => {
66
+ const { container } = createCalendar({ selected: [] })
67
+
68
+ const selectedDates = container.querySelectorAll('.pkt-calendar__date--selected')
69
+ expect(selectedDates.length).toBe(0)
70
+ })
71
+
72
+ test('handles conflicting properties gracefully', () => {
73
+ // Both multiple and range shouldn't typically be used together
74
+ const { container } = createCalendar({ multiple: true, range: true })
75
+
76
+ // Should still render without errors
77
+ expect(container.querySelector('.pkt-calendar')).toBeInTheDocument()
78
+ })
79
+
80
+ test('handles very early dates', () => {
81
+ const { container } = createCalendar({ currentmonth: '1900-01-01' })
82
+
83
+ expect(container.querySelector('.pkt-calendar')).toBeInTheDocument()
84
+ const calendarBody = container.querySelector('.pkt-calendar__body')
85
+ expect(calendarBody).toBeInTheDocument()
86
+ })
87
+
88
+ test('handles far future dates', () => {
89
+ const { container } = createCalendar({ currentmonth: '2100-12-31' })
90
+
91
+ expect(container.querySelector('.pkt-calendar')).toBeInTheDocument()
92
+ const calendarBody = container.querySelector('.pkt-calendar__body')
93
+ expect(calendarBody).toBeInTheDocument()
94
+ })
95
+ })
96
+ })