@oslokommune/punkt-elements 13.4.2 → 13.5.0

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.
package/dist/pkt-index.js CHANGED
@@ -2,8 +2,8 @@ import { P as A } from "./alert-B07oUpkq.js";
2
2
  import { P as B, a as E } from "./accordionitem-C9T3nlM0.js";
3
3
  import { P as O } from "./backlink-C2jbzu0U.js";
4
4
  import { P as T } from "./button-DhispFOY.js";
5
- import { c as f } from "./calendar-DevQhOup.js";
6
- import { P as D } from "./calendar-DevQhOup.js";
5
+ import { c as f } from "./calendar-CJSxvwAq.js";
6
+ import { P as D } from "./calendar-CJSxvwAq.js";
7
7
  import { P as G } from "./card-Dtw26f7i.js";
8
8
  import { P as K } from "./combobox-yE4aYhTi.js";
9
9
  import { P as U } from "./consent-BpcQFvbi.js";
@@ -12,7 +12,7 @@ import { P as k, t as h, x as P, n, a as c } from "./element-CgEWt74-.js";
12
12
  import { P as x } from "./pkt-slot-controller-BPGj-LC5.js";
13
13
  import { e as m, n as d } from "./ref-BBYSqgeW.js";
14
14
  import { e as u } from "./class-map-BpTj9gtz.js";
15
- import { P as F } from "./datepicker-CYOn3tRm.js";
15
+ import { P as F } from "./datepicker-BJKJBoy_.js";
16
16
  import { P as Q } from "./helptext-B7eI0iBQ.js";
17
17
  import { P as X } from "./heading-D6jXE_Mz.js";
18
18
  import { P as Z } from "./icon-CC1js8eR.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "13.4.2",
3
+ "version": "13.5.0",
4
4
  "description": "Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo Origo",
@@ -37,7 +37,7 @@
37
37
  "devDependencies": {
38
38
  "@babel/preset-env": "^7.28.3",
39
39
  "@oslokommune/punkt-assets": "^13.3.1",
40
- "@oslokommune/punkt-css": "^13.3.1",
40
+ "@oslokommune/punkt-css": "^13.5.0",
41
41
  "@testing-library/jest-dom": "^6.6.3",
42
42
  "jest": "^29.7.0",
43
43
  "jest-axe": "^9.0.0",
@@ -69,5 +69,5 @@
69
69
  "url": "https://github.com/oslokommune/punkt/issues"
70
70
  },
71
71
  "license": "MIT",
72
- "gitHead": "b8dc1a2d10d756fb0fc6babb0f3b03b4d8eea95a"
72
+ "gitHead": "5838a97cda7abfca773d36181a7ebf47343880e4"
73
73
  }
@@ -0,0 +1,111 @@
1
+ import '@testing-library/jest-dom'
2
+ import { axe, toHaveNoViolations } from 'jest-axe'
3
+ import { fireEvent } from '@testing-library/dom'
4
+
5
+ expect.extend(toHaveNoViolations)
6
+
7
+ import './calendar'
8
+ import { PktCalendar } from './calendar'
9
+
10
+ const waitForCustomElements = async () => {
11
+ await customElements.whenDefined('pkt-calendar')
12
+ }
13
+
14
+ // Helper function to create calendar markup
15
+ const createCalendar = async (calendarProps = '') => {
16
+ const container = document.createElement('div')
17
+ container.innerHTML = `
18
+ <pkt-calendar ${calendarProps}></pkt-calendar>
19
+ `
20
+ document.body.appendChild(container)
21
+ await waitForCustomElements()
22
+ return container
23
+ }
24
+
25
+ // Cleanup after each test
26
+ afterEach(() => {
27
+ document.body.innerHTML = ''
28
+ })
29
+
30
+ describe('PktCalendar', () => {
31
+ describe('Accessibility', () => {
32
+ test('has no accessibility violations', async () => {
33
+ const container = await createCalendar('withcontrols weeknumbers')
34
+
35
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
36
+ await calendar.updateComplete
37
+
38
+ const results = await axe(calendar)
39
+ expect(results).toHaveNoViolations()
40
+ })
41
+
42
+ test('has proper ARIA attributes', async () => {
43
+ const container = await createCalendar('withcontrols')
44
+
45
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
46
+ await calendar.updateComplete
47
+
48
+ const calendarTable = calendar.querySelector('.pkt-calendar__body')
49
+ expect(calendarTable).toHaveAttribute('role', 'grid')
50
+
51
+ const dateButtons = calendar.querySelectorAll('.pkt-calendar__date')
52
+ dateButtons.forEach((button) => {
53
+ expect(button).toHaveAttribute('aria-pressed')
54
+ expect(button).toHaveAttribute('tabindex')
55
+ })
56
+ })
57
+
58
+ test('navigation buttons have proper labels', async () => {
59
+ const container = await createCalendar('withcontrols')
60
+
61
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
62
+ await calendar.updateComplete
63
+
64
+ const prevButton = calendar.querySelector('.pkt-calendar__prev-month')
65
+ const nextButton = calendar.querySelector('.pkt-calendar__next-month')
66
+
67
+ expect(prevButton).toHaveAttribute('aria-label')
68
+ expect(nextButton).toHaveAttribute('aria-label')
69
+ })
70
+
71
+ test('date buttons have proper accessible names', async () => {
72
+ const container = await createCalendar()
73
+
74
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
75
+ await calendar.updateComplete
76
+
77
+ const dateButtons = calendar.querySelectorAll('.pkt-calendar__date')
78
+ dateButtons.forEach((button) => {
79
+ expect(button).toHaveAttribute('aria-label')
80
+ expect(button.getAttribute('aria-label')).toBeTruthy()
81
+ })
82
+ })
83
+
84
+ test('selected dates have proper ARIA state', async () => {
85
+ const container = await createCalendar()
86
+
87
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
88
+ await calendar.updateComplete
89
+
90
+ const firstDate = calendar.querySelector(
91
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
92
+ )
93
+ fireEvent.click(firstDate!)
94
+ await calendar.updateComplete
95
+
96
+ expect(firstDate).toHaveAttribute('aria-pressed', 'true')
97
+ })
98
+
99
+ test('disabled dates have proper ARIA state', async () => {
100
+ const container = await createCalendar('excludeweekdays="0,6"')
101
+
102
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
103
+ await calendar.updateComplete
104
+
105
+ const disabledDates = calendar.querySelectorAll('.pkt-calendar__date--disabled')
106
+ disabledDates.forEach((date) => {
107
+ expect(date).toHaveAttribute('disabled')
108
+ })
109
+ })
110
+ })
111
+ })
@@ -0,0 +1,110 @@
1
+ import '@testing-library/jest-dom'
2
+ import { parseISODateString } from '@/utils/dateutils'
3
+
4
+ import './calendar'
5
+ import { PktCalendar } from './calendar'
6
+
7
+ const waitForCustomElements = async () => {
8
+ await customElements.whenDefined('pkt-calendar')
9
+ }
10
+
11
+ // Helper function to create calendar markup
12
+ const createCalendar = async (calendarProps = '') => {
13
+ const container = document.createElement('div')
14
+ container.innerHTML = `
15
+ <pkt-calendar ${calendarProps}></pkt-calendar>
16
+ `
17
+ document.body.appendChild(container)
18
+ await waitForCustomElements()
19
+ return container
20
+ }
21
+
22
+ // Cleanup after each test
23
+ afterEach(() => {
24
+ document.body.innerHTML = ''
25
+ })
26
+
27
+ describe('PktCalendar', () => {
28
+ describe('Date range functionality', () => {
29
+ test('handles earliest date property correctly', async () => {
30
+ const earliestDate = '2024-01-15'
31
+ // Set current month to January 2024 so we can see disabled dates before the 15th
32
+ const container = await createCalendar(`earliest="${earliestDate}" currentmonth="2024-01-01"`)
33
+
34
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
35
+ await calendar.updateComplete
36
+
37
+ expect(calendar.earliest).toBe(earliestDate)
38
+
39
+ // Check that dates before earliest are disabled (dates 1-14 should be disabled)
40
+ const disabledDates = calendar.querySelectorAll('.pkt-calendar__date--disabled')
41
+ expect(disabledDates.length).toBeGreaterThan(0)
42
+ })
43
+
44
+ test('handles latest date property correctly', async () => {
45
+ const latestDate = '2024-12-15'
46
+ const container = await createCalendar(`latest="${latestDate}"`)
47
+
48
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
49
+ await calendar.updateComplete
50
+
51
+ expect(calendar.latest).toBe(latestDate)
52
+ })
53
+
54
+ test('restricts selectable dates between earliest and latest', async () => {
55
+ // Set current month to June 2024 so we can see the date range restrictions
56
+ const container = await createCalendar(
57
+ 'earliest="2024-06-10" latest="2024-06-20" currentmonth="2024-06-01"',
58
+ )
59
+
60
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
61
+ await calendar.updateComplete
62
+
63
+ const enabledDates = calendar.querySelectorAll(
64
+ '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
65
+ )
66
+ const disabledDates = calendar.querySelectorAll('.pkt-calendar__date--disabled')
67
+
68
+ expect(enabledDates.length).toBeGreaterThan(0)
69
+ expect(disabledDates.length).toBeGreaterThan(0)
70
+ })
71
+ })
72
+
73
+ describe('Date exclusion functionality', () => {
74
+ test('excludes specific dates correctly', async () => {
75
+ const excludedDates = '2024-06-15,2024-06-20'
76
+ const container = await createCalendar(`excludedates="${excludedDates}"`)
77
+
78
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
79
+ await calendar.updateComplete
80
+
81
+ expect(calendar.excludedates).toHaveLength(2)
82
+ expect(calendar.excludedates[0]).toEqual(parseISODateString('2024-06-15'))
83
+ expect(calendar.excludedates[1]).toEqual(parseISODateString('2024-06-20'))
84
+ })
85
+
86
+ test('excludes weekdays correctly', async () => {
87
+ // Exclude weekends (Saturday=6, Sunday=0)
88
+ const container = await createCalendar('excludeweekdays="0,6"')
89
+
90
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
91
+ await calendar.updateComplete
92
+
93
+ expect(calendar.excludeweekdays).toEqual(['0', '6'])
94
+
95
+ // Check that weekend dates are disabled
96
+ const disabledDates = calendar.querySelectorAll('.pkt-calendar__date--disabled')
97
+ expect(disabledDates.length).toBeGreaterThan(0)
98
+ })
99
+
100
+ test('excludes both specific dates and weekdays', async () => {
101
+ const container = await createCalendar('excludedates="2024-06-15" excludeweekdays="0,6"')
102
+
103
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
104
+ await calendar.updateComplete
105
+
106
+ expect(calendar.excludedates).toHaveLength(1)
107
+ expect(calendar.excludeweekdays).toEqual(['0', '6'])
108
+ })
109
+ })
110
+ })
@@ -0,0 +1,367 @@
1
+ import '@testing-library/jest-dom'
2
+ import { fireEvent } from '@testing-library/dom'
3
+ import { parseISODateString } from '@/utils/dateutils'
4
+
5
+ import './calendar'
6
+ import { PktCalendar } from './calendar'
7
+
8
+ const waitForCustomElements = async () => {
9
+ await customElements.whenDefined('pkt-calendar')
10
+ }
11
+
12
+ // Helper function to create calendar markup
13
+ const createCalendar = async (calendarProps = '') => {
14
+ const container = document.createElement('div')
15
+ container.innerHTML = `
16
+ <pkt-calendar ${calendarProps}></pkt-calendar>
17
+ `
18
+ document.body.appendChild(container)
19
+ await waitForCustomElements()
20
+ return container
21
+ }
22
+
23
+ // Cleanup after each test
24
+ afterEach(() => {
25
+ document.body.innerHTML = ''
26
+ })
27
+
28
+ describe('PktCalendar', () => {
29
+ describe('Rendering and basic functionality', () => {
30
+ test('renders without errors', async () => {
31
+ const container = await createCalendar()
32
+
33
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
34
+ expect(calendar).toBeInTheDocument()
35
+
36
+ await calendar.updateComplete
37
+ expect(calendar).toBeTruthy()
38
+ })
39
+
40
+ test('renders with correct structure', async () => {
41
+ const container = await createCalendar()
42
+
43
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
44
+ await calendar.updateComplete
45
+
46
+ const calendarElement = calendar.querySelector('.pkt-calendar')
47
+ const calendarTable = calendar.querySelector('.pkt-cal-days')
48
+ const monthNav = calendar.querySelector('.pkt-cal-month-nav')
49
+
50
+ expect(calendarElement).toBeInTheDocument()
51
+ expect(calendarTable).toBeInTheDocument()
52
+ expect(monthNav).toBeInTheDocument()
53
+ })
54
+
55
+ test('renders month picker when withcontrols is true', async () => {
56
+ const container = await createCalendar('withcontrols')
57
+
58
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
59
+ await calendar.updateComplete
60
+
61
+ // Navigation buttons should always be present
62
+ const prevButton = calendar.querySelector('.pkt-calendar__prev-month')
63
+ const nextButton = calendar.querySelector('.pkt-calendar__next-month')
64
+ expect(prevButton).toBeInTheDocument()
65
+ expect(nextButton).toBeInTheDocument()
66
+
67
+ // Should show month picker controls, not static title
68
+ const monthPicker = calendar.querySelector('.pkt-cal-month-picker')
69
+ const monthTitle = calendar.querySelector('.pkt-calendar__month-title')
70
+
71
+ expect(monthPicker).toBeInTheDocument()
72
+ expect(monthTitle).not.toBeInTheDocument()
73
+
74
+ // Should have month and year inputs
75
+ const monthSelect = monthPicker?.querySelector('select')
76
+ const yearInput = monthPicker?.querySelector('input[type="number"]')
77
+ expect(monthSelect).toBeInTheDocument()
78
+ expect(yearInput).toBeInTheDocument()
79
+ })
80
+
81
+ test('renders static month title when withcontrols is false', async () => {
82
+ const container = await createCalendar()
83
+
84
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
85
+ await calendar.updateComplete
86
+
87
+ // Navigation buttons should always be present
88
+ const prevButton = calendar.querySelector('.pkt-calendar__prev-month')
89
+ const nextButton = calendar.querySelector('.pkt-calendar__next-month')
90
+ expect(prevButton).toBeInTheDocument()
91
+ expect(nextButton).toBeInTheDocument()
92
+
93
+ // Should show static month title, not controls
94
+ const monthTitle = calendar.querySelector('.pkt-calendar__month-title')
95
+ const monthPicker = calendar.querySelector('.pkt-cal-month-picker')
96
+
97
+ expect(monthTitle).toBeInTheDocument()
98
+ expect(monthPicker).not.toBeInTheDocument()
99
+ })
100
+ })
101
+
102
+ describe('Properties and attributes', () => {
103
+ test('applies default properties correctly', async () => {
104
+ const container = await createCalendar()
105
+
106
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
107
+ await calendar.updateComplete
108
+
109
+ expect(calendar.multiple).toBe(false)
110
+ expect(calendar.range).toBe(false)
111
+ expect(calendar.weeknumbers).toBe(false)
112
+ expect(calendar.withcontrols).toBe(false)
113
+ expect(calendar.selected).toEqual([])
114
+ expect(calendar.earliest).toBe(null)
115
+ expect(calendar.latest).toBe(null)
116
+ })
117
+
118
+ test('handles multiple property correctly', async () => {
119
+ const container = await createCalendar('multiple')
120
+
121
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
122
+ await calendar.updateComplete
123
+
124
+ expect(calendar.multiple).toBe(true)
125
+ })
126
+
127
+ test('handles range property correctly', async () => {
128
+ const container = await createCalendar('range')
129
+
130
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
131
+ await calendar.updateComplete
132
+
133
+ expect(calendar.range).toBe(true)
134
+ })
135
+
136
+ test('handles weeknumbers property correctly', async () => {
137
+ const container = await createCalendar('weeknumbers')
138
+
139
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
140
+ await calendar.updateComplete
141
+
142
+ expect(calendar.weeknumbers).toBe(true)
143
+
144
+ const weekNumbers = calendar.querySelectorAll('.pkt-calendar__week-number')
145
+ expect(weekNumbers.length).toBeGreaterThan(0)
146
+ })
147
+
148
+ test('handles maxMultiple property correctly', async () => {
149
+ const container = await createCalendar('multiple maxMultiple="3"')
150
+
151
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
152
+ await calendar.updateComplete
153
+
154
+ expect(calendar.maxMultiple).toBe(3)
155
+ })
156
+
157
+ test('handles currentmonth property correctly', async () => {
158
+ const testDate = '2024-03-15'
159
+ const container = await createCalendar(`currentmonth="${testDate}"`)
160
+
161
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
162
+ await calendar.updateComplete
163
+
164
+ expect(calendar.currentmonth).toEqual(parseISODateString(testDate))
165
+ })
166
+ })
167
+
168
+ describe('Month navigation', () => {
169
+ it('should navigate to previous month when clicking previous button', async () => {
170
+ const calendar = document.createElement('pkt-calendar') as PktCalendar
171
+ document.body.appendChild(calendar)
172
+ await waitForCustomElements()
173
+
174
+ const navElement = calendar.querySelector('.pkt-cal-month-nav')
175
+ const prevButton = navElement?.querySelector('button')
176
+
177
+ expect(prevButton).toBeInTheDocument()
178
+
179
+ const initialMonth = calendar.currentmonth!.getMonth()
180
+ const initialYear = calendar.currentmonth!.getFullYear()
181
+ fireEvent.click(prevButton!)
182
+ await calendar.updateComplete
183
+
184
+ // Should go to previous month (or December of previous year if we're in January)
185
+ if (initialMonth === 0) {
186
+ expect(calendar.currentmonth!.getMonth()).toBe(11)
187
+ expect(calendar.currentmonth!.getFullYear()).toBe(initialYear - 1)
188
+ } else {
189
+ expect(calendar.currentmonth!.getMonth()).toBe(initialMonth - 1)
190
+ expect(calendar.currentmonth!.getFullYear()).toBe(initialYear)
191
+ }
192
+
193
+ document.body.removeChild(calendar)
194
+ })
195
+
196
+ it('should navigate to next month when clicking next button', async () => {
197
+ const calendar = document.createElement('pkt-calendar') as PktCalendar
198
+ document.body.appendChild(calendar)
199
+ await waitForCustomElements()
200
+
201
+ const navElement = calendar.querySelector('.pkt-cal-month-nav')
202
+ const buttons = navElement?.querySelectorAll('button')
203
+ const nextButton = buttons?.[1] // Second button is next
204
+
205
+ expect(nextButton).toBeInTheDocument()
206
+
207
+ const initialMonth = calendar.currentmonth!.getMonth()
208
+ const initialYear = calendar.currentmonth!.getFullYear()
209
+ fireEvent.click(nextButton!)
210
+ await calendar.updateComplete
211
+
212
+ // Should go to next month (or January of next year if we're in December)
213
+ if (initialMonth === 11) {
214
+ expect(calendar.currentmonth!.getMonth()).toBe(0)
215
+ expect(calendar.currentmonth!.getFullYear()).toBe(initialYear + 1)
216
+ } else {
217
+ expect(calendar.currentmonth!.getMonth()).toBe(initialMonth + 1)
218
+ expect(calendar.currentmonth!.getFullYear()).toBe(initialYear)
219
+ }
220
+
221
+ document.body.removeChild(calendar)
222
+ })
223
+
224
+ test('navigates to next month', async () => {
225
+ const container = await createCalendar('withcontrols currentmonth="2024-06-15"')
226
+
227
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
228
+ await calendar.updateComplete
229
+
230
+ const nextButton = calendar.querySelector('.pkt-calendar__next-month')
231
+ expect(nextButton).toBeInTheDocument()
232
+
233
+ // With controls=true, check the month select dropdown instead of title
234
+ const monthSelect = calendar.querySelector(
235
+ '.pkt-cal-month-picker select',
236
+ ) as HTMLSelectElement
237
+ const initialMonth = monthSelect?.value
238
+
239
+ fireEvent.click(nextButton!)
240
+ await calendar.updateComplete
241
+
242
+ const newMonth = monthSelect?.value
243
+ expect(newMonth).not.toBe(initialMonth)
244
+ })
245
+
246
+ test('month navigation updates visible dates', async () => {
247
+ const container = await createCalendar('withcontrols currentmonth="2024-06-15"')
248
+
249
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
250
+ await calendar.updateComplete
251
+
252
+ const initialDates = Array.from(calendar.querySelectorAll('.pkt-calendar__date')).map(
253
+ (el) => el.textContent,
254
+ )
255
+
256
+ const nextButton = calendar.querySelector('.pkt-calendar__next-month')
257
+ fireEvent.click(nextButton!)
258
+ await calendar.updateComplete
259
+
260
+ const newDates = Array.from(calendar.querySelectorAll('.pkt-calendar__date')).map(
261
+ (el) => el.textContent,
262
+ )
263
+ expect(newDates).not.toEqual(initialDates)
264
+ })
265
+ })
266
+
267
+ describe('Date formatting and localization', () => {
268
+ test('displays day names correctly', async () => {
269
+ const container = await createCalendar()
270
+
271
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
272
+ await calendar.updateComplete
273
+
274
+ const dayHeaders = calendar.querySelectorAll('.pkt-calendar__day-name')
275
+ expect(dayHeaders.length).toBe(7)
276
+
277
+ // Check that day names are displayed
278
+ dayHeaders.forEach((header) => {
279
+ expect(header.textContent).toBeTruthy()
280
+ expect(header.textContent!.length).toBeGreaterThan(0)
281
+ })
282
+ })
283
+
284
+ test('displays month names correctly', async () => {
285
+ const container = await createCalendar('currentmonth="2024-06-15"')
286
+
287
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
288
+ await calendar.updateComplete
289
+
290
+ const monthTitle = calendar.querySelector('.pkt-calendar__month-title')
291
+ expect(monthTitle).toBeInTheDocument()
292
+ expect(monthTitle?.textContent).toBeTruthy()
293
+ })
294
+
295
+ test('handles custom day strings', async () => {
296
+ const container = await createCalendar()
297
+
298
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
299
+
300
+ // Set custom day strings
301
+ calendar.dayStrings = ['S', 'M', 'T', 'W', 'T', 'F', 'S']
302
+ await calendar.updateComplete
303
+
304
+ const dayHeaders = calendar.querySelectorAll('.pkt-calendar__day-name')
305
+ expect(dayHeaders[0].textContent?.trim()).toBe('S')
306
+ expect(dayHeaders[1].textContent?.trim()).toBe('M')
307
+ })
308
+
309
+ test('handles custom month strings', async () => {
310
+ const container = await createCalendar('withcontrols')
311
+
312
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
313
+
314
+ // Set custom month strings
315
+ calendar.monthStrings = [
316
+ 'Jan',
317
+ 'Feb',
318
+ 'Mar',
319
+ 'Apr',
320
+ 'May',
321
+ 'Jun',
322
+ 'Jul',
323
+ 'Aug',
324
+ 'Sep',
325
+ 'Oct',
326
+ 'Nov',
327
+ 'Dec',
328
+ ]
329
+ await calendar.updateComplete
330
+
331
+ // When withcontrols=true, check the month select dropdown instead of title
332
+ const monthSelect = calendar.querySelector('.pkt-cal-month-picker select')
333
+ expect(monthSelect).toBeInTheDocument()
334
+
335
+ // Check that the custom month string appears in the dropdown options
336
+ const options = monthSelect?.querySelectorAll('option')
337
+ expect(options?.[0]?.textContent).toContain('Jan')
338
+ })
339
+ })
340
+
341
+ describe('Today highlighting', () => {
342
+ test('highlights today date', async () => {
343
+ const container = await createCalendar()
344
+
345
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
346
+ await calendar.updateComplete
347
+
348
+ const todayDate = calendar.querySelector('.pkt-calendar__date--today')
349
+ expect(todayDate).toBeInTheDocument()
350
+ })
351
+
352
+ test('today date is selectable unless excluded', async () => {
353
+ const container = await createCalendar()
354
+
355
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
356
+ await calendar.updateComplete
357
+
358
+ const todayDate = calendar.querySelector('.pkt-calendar__date--today')
359
+
360
+ if (todayDate && !todayDate.classList.contains('pkt-calendar__date--disabled')) {
361
+ fireEvent.click(todayDate)
362
+ await calendar.updateComplete
363
+ expect(todayDate).toHaveClass('pkt-calendar__date--selected')
364
+ }
365
+ })
366
+ })
367
+ })