@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/CHANGELOG.md +18 -0
- package/dist/calendar-32W9p9uc.cjs +115 -0
- package/dist/{calendar-DevQhOup.js → calendar-CJSxvwAq.js} +353 -340
- package/dist/{datepicker-CYOn3tRm.js → datepicker-BJKJBoy_.js} +102 -59
- package/dist/datepicker-CmTrG5GE.cjs +164 -0
- package/dist/index.d.ts +6 -2
- package/dist/pkt-calendar.cjs +1 -1
- package/dist/pkt-calendar.js +1 -1
- package/dist/pkt-datepicker.cjs +1 -1
- package/dist/pkt-datepicker.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +3 -3
- package/package.json +3 -3
- package/src/components/calendar/calendar.accessibility.test.ts +111 -0
- package/src/components/calendar/calendar.constraints.test.ts +110 -0
- package/src/components/calendar/calendar.core.test.ts +367 -0
- package/src/components/calendar/calendar.interaction.test.ts +139 -0
- package/src/components/calendar/calendar.selection.test.ts +273 -0
- package/src/components/calendar/calendar.ts +74 -42
- package/src/components/card/card.test.ts +19 -5
- package/src/components/datepicker/datepicker.accessibility.test.ts +193 -0
- package/src/components/datepicker/datepicker.core.test.ts +322 -0
- package/src/components/datepicker/datepicker.input.test.ts +268 -0
- package/src/components/datepicker/datepicker.selection.test.ts +286 -0
- package/src/components/datepicker/datepicker.ts +121 -19
- package/src/components/datepicker/datepicker.validation.test.ts +176 -0
- package/dist/calendar-BZe2D4Sr.cjs +0 -108
- package/dist/datepicker-B9rhz_AF.cjs +0 -154
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-
|
|
6
|
-
import { P as D } from "./calendar-
|
|
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-
|
|
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.
|
|
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.
|
|
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": "
|
|
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
|
+
})
|