@cnamts/synapse 1.0.22 → 1.0.23
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/{DateFilter-B5n-ZkLi.js → DateFilter-Dc-gSGwk.js} +1 -1
- package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-vP38Wp6j.js} +1 -1
- package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-Ba1uYUnT.js} +1 -1
- package/dist/{SelectFilter-BOYlF7rX.js → SelectFilter-BioGT6Nn.js} +1 -1
- package/dist/{TextFilter-BOFRNfcX.js → TextFilter-B84dpnoq.js} +1 -1
- package/dist/components/Accordion/Accordion.d.ts +13 -2
- package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +16 -16
- package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +1 -1
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +22 -1
- package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
- package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -1
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -1
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -1
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +5 -2
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +13 -9
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +7 -5
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +2 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
- package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
- package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
- package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
- package/dist/components/FileUpload/validateFiles.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
- package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +2 -1
- package/dist/components/MonthPicker/MonthPicker.d.ts +1939 -0
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1899 -0
- package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
- package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
- package/dist/components/MonthPicker/locales.d.ts +12 -0
- package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
- package/dist/components/NirField/NirField.d.ts +3 -1
- package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
- package/dist/components/PasswordField/PasswordField.d.ts +1 -1
- package/dist/components/PeriodField/PeriodField.d.ts +29 -21
- package/dist/components/PhoneField/PhoneField.d.ts +2 -1
- package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
- package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
- package/dist/components/SyHeading/SyHeading.d.ts +4 -2
- package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +1 -1
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
- package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
- package/dist/components/Tables/common/SyTablePagination.d.ts +6 -6
- package/dist/components/index.d.ts +1 -0
- package/dist/design-system-v3.js +102 -99
- package/dist/design-system-v3.umd.cjs +126 -126
- package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
- package/dist/{main-CEl4J8_T.js → main-aLKwdMi1.js} +11167 -10522
- package/dist/main.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +10 -4
- package/src/assets/apTokens.scss +2 -2
- package/src/assets/overrides/_btns.scss +8 -0
- package/src/assets/overrides/_forms.scss +9 -0
- package/src/assets/overrides/_icons.scss +38 -9
- package/src/assets/overrides/_tables.scss +19 -0
- package/src/components/Accordion/Accordion.mdx +23 -9
- package/src/components/Accordion/Accordion.stories.ts +153 -3
- package/src/components/Accordion/Accordion.vue +7 -6
- package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
- package/src/components/Accordion/composables/useAccordionState.ts +3 -4
- package/src/components/Accordion/tests/accordion.spec.ts +131 -19
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
- package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
- package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
- package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
- package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +2 -110
- package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +133 -10
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +144 -83
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
- package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +234 -9
- package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +13 -3
- package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
- package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -3
- package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
- package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
- package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
- package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
- package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
- package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
- package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
- package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
- package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
- package/src/components/Customs/SyTextField/SyTextField.vue +20 -2
- package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
- package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +15 -0
- package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +36 -0
- package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
- package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
- package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
- package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
- package/src/components/ErrorPage/ErrorPage.vue +17 -2
- package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
- package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
- package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
- package/src/components/FileList/FileList.stories.ts +51 -1
- package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
- package/src/components/FileList/UploadItem/locales.ts +3 -12
- package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
- package/src/components/FileUpload/FileUpload.vue +2 -1
- package/src/components/FileUpload/FileUploadContent.vue +2 -1
- package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
- package/src/components/FileUpload/validateFiles.ts +5 -2
- package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
- package/src/components/HeaderBar/HeaderBar.vue +2 -1
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
- package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
- package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
- package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
- package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
- package/src/components/MonthPicker/MonthPicker.mdx +35 -0
- package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
- package/src/components/MonthPicker/MonthPicker.vue +79 -0
- package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
- package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
- package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
- package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
- package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
- package/src/components/MonthPicker/locales.ts +12 -0
- package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
- package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1248 -0
- package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
- package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
- package/src/components/NirField/NirField.mdx +1 -2
- package/src/components/NirField/NirField.stories.ts +66 -6
- package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
- package/src/components/NotificationBar/Notification/Notification.vue +3 -1
- package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
- package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
- package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
- package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
- package/src/components/StatusPage/StatusPage.stories.ts +118 -0
- package/src/components/StatusPage/StatusPage.vue +5 -3
- package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
- package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
- package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
- package/src/components/SyAlert/SyAlert.vue +1 -0
- package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
- package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
- package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
- package/src/components/SyHeading/SyHeading.test.ts +115 -0
- package/src/components/SyHeading/SyHeading.vue +5 -3
- package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
- package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
- package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
- package/src/components/index.ts +1 -0
- package/src/composables/useFormFieldErrorHandling.ts +11 -2
- package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
- package/src/main.ts +2 -0
|
@@ -0,0 +1,1248 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import { describe, afterEach, expect, it, vi } from 'vitest'
|
|
3
|
+
import MonthPicker from '../MonthPicker.vue'
|
|
4
|
+
import { nextTick } from 'vue'
|
|
5
|
+
|
|
6
|
+
describe('mounthpicker', () => {
|
|
7
|
+
it('should render mounthpicker', () => {
|
|
8
|
+
const wrapper = mount(MonthPicker, {
|
|
9
|
+
props: {
|
|
10
|
+
label: 'Début du projet',
|
|
11
|
+
modelValue: '11/2025',
|
|
12
|
+
},
|
|
13
|
+
attachTo: document.body,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
expect(wrapper.find('.month-picker').exists()).toBeTruthy()
|
|
17
|
+
expect(wrapper).toMatchSnapshot()
|
|
18
|
+
wrapper.unmount()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('should open the menu when clicking on the input', async () => {
|
|
22
|
+
vi.useFakeTimers()
|
|
23
|
+
const wrapper = mount(MonthPicker, {
|
|
24
|
+
props: {
|
|
25
|
+
label: 'Début du projet',
|
|
26
|
+
modelValue: '12/2026',
|
|
27
|
+
},
|
|
28
|
+
attachTo: document.body,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
32
|
+
await nextTick()
|
|
33
|
+
await nextTick()
|
|
34
|
+
|
|
35
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
36
|
+
await toggleBtn.trigger('click')
|
|
37
|
+
|
|
38
|
+
const monthPickerVisualWrapper = document.body.querySelector('.month-picker-menu') as HTMLElement
|
|
39
|
+
expect(monthPickerVisualWrapper).toBeTruthy()
|
|
40
|
+
expect(monthPickerVisualWrapper).toMatchSnapshot()
|
|
41
|
+
|
|
42
|
+
wrapper.unmount()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('MonthPickerInput', () => {
|
|
46
|
+
it('should emit update:modelValue when the input value changes', async () => {
|
|
47
|
+
const wrapper = mount(MonthPicker, {
|
|
48
|
+
props: {
|
|
49
|
+
label: 'Début du projet',
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const input = wrapper.find('input')
|
|
54
|
+
await input.setValue('01/2027')
|
|
55
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['01/2027']])
|
|
56
|
+
|
|
57
|
+
wrapper.unmount()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should emit multiple update:modelValue when the input value changes multiple times', async () => {
|
|
61
|
+
const wrapper = mount(MonthPicker, {
|
|
62
|
+
props: {
|
|
63
|
+
label: 'Début du projet',
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
const input = wrapper.find('input')
|
|
67
|
+
|
|
68
|
+
await input.setValue('01/2027')
|
|
69
|
+
await input.setValue('02/2027')
|
|
70
|
+
await input.setValue('03/2030')
|
|
71
|
+
|
|
72
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['01/2027'], ['02/2027'], ['03/2030']])
|
|
73
|
+
|
|
74
|
+
wrapper.unmount()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('shows the correct value in the input when modelValue prop changes', async () => {
|
|
78
|
+
const wrapper = mount(MonthPicker, {
|
|
79
|
+
props: {
|
|
80
|
+
label: 'Début du projet',
|
|
81
|
+
modelValue: '11/2025',
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
expect(wrapper.find('input').element.value).toBe('11/2025')
|
|
86
|
+
|
|
87
|
+
await wrapper.setProps({ modelValue: '12/2026' })
|
|
88
|
+
expect(wrapper.find('input').element.value).toBe('12/2026')
|
|
89
|
+
|
|
90
|
+
wrapper.unmount()
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
describe('MonthPickerVisual', () => {
|
|
95
|
+
it('should emit update:modelValue when a month is selected and a year is selected', async () => {
|
|
96
|
+
const wrapper = mount(MonthPicker, {
|
|
97
|
+
props: {
|
|
98
|
+
label: 'Début du projet',
|
|
99
|
+
modelValue: '11/2025',
|
|
100
|
+
},
|
|
101
|
+
attachTo: document.body,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
105
|
+
await nextTick()
|
|
106
|
+
await nextTick()
|
|
107
|
+
|
|
108
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
109
|
+
await toggleBtn.trigger('click')
|
|
110
|
+
|
|
111
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
112
|
+
await monthButton.trigger('click')
|
|
113
|
+
|
|
114
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
115
|
+
await yearButton.trigger('click')
|
|
116
|
+
|
|
117
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['01/2024']]) // The month part of the value should be '01'
|
|
118
|
+
|
|
119
|
+
wrapper.unmount()
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('do not emit update:modelValue when only a month is selected', async () => {
|
|
123
|
+
const wrapper = mount(MonthPicker, {
|
|
124
|
+
props: {
|
|
125
|
+
label: 'Début du projet',
|
|
126
|
+
modelValue: '11/2025',
|
|
127
|
+
},
|
|
128
|
+
attachTo: document.body,
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
132
|
+
await nextTick()
|
|
133
|
+
await nextTick()
|
|
134
|
+
|
|
135
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
136
|
+
await toggleBtn.trigger('click')
|
|
137
|
+
|
|
138
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
139
|
+
await monthButton.trigger('click')
|
|
140
|
+
|
|
141
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy() // The value should not be emitted when only a month is selected
|
|
142
|
+
|
|
143
|
+
wrapper.unmount()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('do not emit update:modelValue when only a month is selected', async () => {
|
|
147
|
+
const wrapper = mount(MonthPicker, {
|
|
148
|
+
props: {
|
|
149
|
+
label: 'Début du projet',
|
|
150
|
+
},
|
|
151
|
+
attachTo: document.body,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
155
|
+
await nextTick()
|
|
156
|
+
await nextTick()
|
|
157
|
+
|
|
158
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
159
|
+
await toggleBtn.trigger('click')
|
|
160
|
+
|
|
161
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
162
|
+
await monthButton.trigger('click')
|
|
163
|
+
|
|
164
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy() // The value should not be emitted when only a month is selected
|
|
165
|
+
|
|
166
|
+
wrapper.unmount()
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('do not emit update:modelValue when only a year is selected', async () => {
|
|
170
|
+
const wrapper = mount(MonthPicker, {
|
|
171
|
+
props: {
|
|
172
|
+
label: 'Début du projet',
|
|
173
|
+
},
|
|
174
|
+
attachTo: document.body,
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
178
|
+
await nextTick()
|
|
179
|
+
await nextTick()
|
|
180
|
+
|
|
181
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
182
|
+
await toggleBtn.trigger('click')
|
|
183
|
+
|
|
184
|
+
const switchViewBtn = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn')
|
|
185
|
+
await switchViewBtn.trigger('click')
|
|
186
|
+
|
|
187
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
188
|
+
await yearButton.trigger('click')
|
|
189
|
+
|
|
190
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy() // The value should not be emitted when only a year is selected
|
|
191
|
+
|
|
192
|
+
wrapper.unmount()
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('shows the year picker after the month is selected', async () => {
|
|
196
|
+
const wrapper = mount(MonthPicker, {
|
|
197
|
+
props: {
|
|
198
|
+
label: 'Début du projet',
|
|
199
|
+
modelValue: '11/2025',
|
|
200
|
+
},
|
|
201
|
+
attachTo: document.body,
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
205
|
+
await nextTick()
|
|
206
|
+
await nextTick()
|
|
207
|
+
|
|
208
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
209
|
+
await toggleBtn.trigger('click')
|
|
210
|
+
|
|
211
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
212
|
+
await monthButton.trigger('click')
|
|
213
|
+
|
|
214
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).exists()).toBeFalsy()
|
|
215
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).isVisible()).toBeTruthy()
|
|
216
|
+
expect(wrapper.findComponent({ name: 'YearSelector' })).toMatchSnapshot()
|
|
217
|
+
|
|
218
|
+
wrapper.unmount()
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('shows the month picker after the year is selected', async () => {
|
|
222
|
+
const wrapper = mount(MonthPicker, {
|
|
223
|
+
props: {
|
|
224
|
+
label: 'Début du projet',
|
|
225
|
+
modelValue: '11/2025',
|
|
226
|
+
},
|
|
227
|
+
attachTo: document.body,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
231
|
+
await nextTick()
|
|
232
|
+
await nextTick()
|
|
233
|
+
|
|
234
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
235
|
+
await toggleBtn.trigger('click')
|
|
236
|
+
|
|
237
|
+
// Switch to year selector
|
|
238
|
+
const switchViewBtn = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn')
|
|
239
|
+
await switchViewBtn.trigger('click')
|
|
240
|
+
|
|
241
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
242
|
+
await yearButton.trigger('click')
|
|
243
|
+
|
|
244
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).exists()).toBeFalsy()
|
|
245
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).isVisible()).toBeTruthy()
|
|
246
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' })).toMatchSnapshot()
|
|
247
|
+
|
|
248
|
+
wrapper.unmount()
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it ('should close the menu after selecting a year and then a month', async () => {
|
|
252
|
+
const wrapper = mount(MonthPicker, {
|
|
253
|
+
props: {
|
|
254
|
+
label: 'Début du projet',
|
|
255
|
+
modelValue: '11/2025',
|
|
256
|
+
},
|
|
257
|
+
attachTo: document.body,
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
261
|
+
await nextTick()
|
|
262
|
+
await nextTick()
|
|
263
|
+
|
|
264
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
265
|
+
await toggleBtn.trigger('click')
|
|
266
|
+
|
|
267
|
+
// Switch to year selector
|
|
268
|
+
const switchViewBtn = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn')
|
|
269
|
+
await switchViewBtn.trigger('click')
|
|
270
|
+
|
|
271
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
272
|
+
await yearButton.trigger('click')
|
|
273
|
+
|
|
274
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
275
|
+
await monthButton.trigger('click')
|
|
276
|
+
|
|
277
|
+
const monthPickerVisualWrapper = wrapper.findComponent({ name: 'MonthPickerVisual' }).find('.month-picker-menu')
|
|
278
|
+
expect(monthPickerVisualWrapper.exists()).toBeFalsy()
|
|
279
|
+
|
|
280
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['01/2024']]) // The value should be '01/2024' after selecting January and 2024
|
|
281
|
+
expect(wrapper.emitted('update:open')).toEqual([[true], [false]]) // The menu should be closed after selecting a month and a year
|
|
282
|
+
|
|
283
|
+
wrapper.unmount()
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('show the selected month in the visual month picker', async () => {
|
|
287
|
+
const wrapper = mount(MonthPicker, {
|
|
288
|
+
props: {
|
|
289
|
+
label: 'Début du projet',
|
|
290
|
+
modelValue: '11/2025',
|
|
291
|
+
},
|
|
292
|
+
attachTo: document.body,
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
296
|
+
await nextTick()
|
|
297
|
+
await nextTick()
|
|
298
|
+
|
|
299
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
300
|
+
await toggleBtn.trigger('click')
|
|
301
|
+
|
|
302
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-11') // November button
|
|
303
|
+
expect(monthButton.classes()).toContain('month-selector__month--active')
|
|
304
|
+
|
|
305
|
+
wrapper.unmount()
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
it('show the correct year in the visual year picker', async () => {
|
|
309
|
+
const wrapper = mount(MonthPicker, {
|
|
310
|
+
props: {
|
|
311
|
+
label: 'Début du projet',
|
|
312
|
+
modelValue: '11/2025',
|
|
313
|
+
},
|
|
314
|
+
attachTo: document.body,
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
318
|
+
await nextTick()
|
|
319
|
+
await nextTick()
|
|
320
|
+
|
|
321
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
322
|
+
await toggleBtn.trigger('click')
|
|
323
|
+
|
|
324
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
325
|
+
await monthButton.trigger('click')
|
|
326
|
+
|
|
327
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025')
|
|
328
|
+
expect(yearButton.classes()).toContain('year-selector__year--active')
|
|
329
|
+
|
|
330
|
+
wrapper.unmount()
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
describe('keyboard navigation', () => {
|
|
334
|
+
it('should navigate through months using arrow keys', async () => {
|
|
335
|
+
const wrapper = mount(MonthPicker, {
|
|
336
|
+
props: {
|
|
337
|
+
label: 'Début du projet',
|
|
338
|
+
modelValue: '11/2025',
|
|
339
|
+
},
|
|
340
|
+
attachTo: document.body,
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
344
|
+
await nextTick()
|
|
345
|
+
await nextTick()
|
|
346
|
+
|
|
347
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
348
|
+
await toggleBtn.trigger('click')
|
|
349
|
+
|
|
350
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-11')
|
|
351
|
+
expect(monthButton.attributes('tabindex')).toBe('0')
|
|
352
|
+
|
|
353
|
+
await monthButton.trigger('keydown', { key: 'ArrowLeft' })
|
|
354
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).find('.month-10').attributes('tabindex')).toBe('0')
|
|
355
|
+
|
|
356
|
+
await monthButton.trigger('keydown', { key: 'ArrowRight' })
|
|
357
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).find('.month-11').attributes('tabindex')).toBe('0')
|
|
358
|
+
|
|
359
|
+
await monthButton.trigger('keydown', { key: 'ArrowUp' })
|
|
360
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).find('.month-9').attributes('tabindex')).toBe('0')
|
|
361
|
+
|
|
362
|
+
await monthButton.trigger('keydown', { key: 'ArrowDown' })
|
|
363
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).find('.month-11').attributes('tabindex')).toBe('0')
|
|
364
|
+
|
|
365
|
+
wrapper.unmount()
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
it('should navigate through years using arrow keys', async () => {
|
|
369
|
+
const wrapper = mount(MonthPicker, {
|
|
370
|
+
props: {
|
|
371
|
+
label: 'Début du projet',
|
|
372
|
+
modelValue: '11/2025',
|
|
373
|
+
},
|
|
374
|
+
attachTo: document.body,
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
378
|
+
await nextTick()
|
|
379
|
+
await nextTick()
|
|
380
|
+
|
|
381
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
382
|
+
await toggleBtn.trigger('click')
|
|
383
|
+
|
|
384
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
385
|
+
await monthButton.trigger('click')
|
|
386
|
+
|
|
387
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025')
|
|
388
|
+
expect(yearButton.attributes('tabindex')).toBe('0')
|
|
389
|
+
|
|
390
|
+
await yearButton.trigger('keydown', { key: 'ArrowUp' })
|
|
391
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2022').attributes('tabindex')).toBe('0')
|
|
392
|
+
|
|
393
|
+
await yearButton.trigger('keydown', { key: 'ArrowDown' })
|
|
394
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025').attributes('tabindex')).toBe('0')
|
|
395
|
+
|
|
396
|
+
await yearButton.trigger('keydown', { key: 'ArrowLeft' })
|
|
397
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024').attributes('tabindex')).toBe('0')
|
|
398
|
+
|
|
399
|
+
await yearButton.trigger('keydown', { key: 'ArrowRight' })
|
|
400
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025').attributes('tabindex')).toBe('0')
|
|
401
|
+
|
|
402
|
+
wrapper.unmount()
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
it('should navigate through years using arrow keys according to the yearsOrder prop', async () => {
|
|
406
|
+
const wrapper = mount(MonthPicker, {
|
|
407
|
+
props: {
|
|
408
|
+
label: 'Début du projet',
|
|
409
|
+
modelValue: '11/2025',
|
|
410
|
+
yearsOrder: 'desc',
|
|
411
|
+
},
|
|
412
|
+
attachTo: document.body,
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
416
|
+
await nextTick()
|
|
417
|
+
await nextTick()
|
|
418
|
+
|
|
419
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
420
|
+
await toggleBtn.trigger('click')
|
|
421
|
+
|
|
422
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
423
|
+
await monthButton.trigger('click')
|
|
424
|
+
|
|
425
|
+
const yearSelector = wrapper.findComponent({ name: 'YearSelector' })
|
|
426
|
+
|
|
427
|
+
const yearButton = yearSelector.find('.year-2025')
|
|
428
|
+
await yearButton.trigger('keydown', { key: 'ArrowUp' })
|
|
429
|
+
expect(yearSelector.find('.year-2028').attributes('tabindex')).toBe('0')
|
|
430
|
+
await yearButton.trigger('keydown', { key: 'ArrowDown' })
|
|
431
|
+
expect(yearSelector.find('.year-2025').attributes('tabindex')).toBe('0')
|
|
432
|
+
await yearButton.trigger('keydown', { key: 'ArrowLeft' })
|
|
433
|
+
expect(yearSelector.find('.year-2026').attributes('tabindex')).toBe('0')
|
|
434
|
+
await yearButton.trigger('keydown', { key: 'ArrowRight' })
|
|
435
|
+
expect(yearSelector.find('.year-2025').attributes('tabindex')).toBe('0')
|
|
436
|
+
|
|
437
|
+
await wrapper.setProps({ yearsOrder: 'asc' })
|
|
438
|
+
expect(yearSelector.find('.year-2025').attributes('tabindex')).toBe('0')
|
|
439
|
+
await yearButton.trigger('keydown', { key: 'ArrowUp' })
|
|
440
|
+
expect(yearSelector.find('.year-2022').attributes('tabindex')).toBe('0')
|
|
441
|
+
await yearButton.trigger('keydown', { key: 'ArrowDown' })
|
|
442
|
+
expect(yearSelector.find('.year-2025').attributes('tabindex')).toBe('0')
|
|
443
|
+
await yearButton.trigger('keydown', { key: 'ArrowLeft' })
|
|
444
|
+
expect(yearSelector.find('.year-2024').attributes('tabindex')).toBe('0')
|
|
445
|
+
await yearButton.trigger('keydown', { key: 'ArrowRight' })
|
|
446
|
+
expect(yearSelector.find('.year-2025').attributes('tabindex')).toBe('0')
|
|
447
|
+
|
|
448
|
+
wrapper.unmount()
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
it ('show the years in the correct order according to the yearsOrder prop', async () => {
|
|
453
|
+
const wrapper = mount(MonthPicker, {
|
|
454
|
+
props: {
|
|
455
|
+
label: 'Début du projet',
|
|
456
|
+
modelValue: '11/2025',
|
|
457
|
+
yearsOrder: 'desc',
|
|
458
|
+
},
|
|
459
|
+
attachTo: document.body,
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
463
|
+
await nextTick()
|
|
464
|
+
await nextTick()
|
|
465
|
+
|
|
466
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
467
|
+
await toggleBtn.trigger('click')
|
|
468
|
+
|
|
469
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
470
|
+
await monthButton.trigger('click')
|
|
471
|
+
|
|
472
|
+
const yearButtons = wrapper.findComponent({ name: 'YearSelector' }).findAll('.year-selector__year')
|
|
473
|
+
expect(yearButtons[0]!.text()).toBe('2100')
|
|
474
|
+
expect(yearButtons[yearButtons.length - 1]!.text()).toBe('1900')
|
|
475
|
+
|
|
476
|
+
await wrapper.setProps({ yearsOrder: 'asc' })
|
|
477
|
+
|
|
478
|
+
const newYearButtons = wrapper.findComponent({ name: 'YearSelector' }).findAll('.year-selector__year')
|
|
479
|
+
expect(newYearButtons[0]!.text()).toBe('1900')
|
|
480
|
+
expect(newYearButtons[newYearButtons.length - 1]!.text()).toBe('2100')
|
|
481
|
+
|
|
482
|
+
wrapper.unmount()
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
describe('select current month btn', () => {
|
|
487
|
+
it('should select the current month and year when a month is already selected', async () => {
|
|
488
|
+
// mock current date to 15th March 2023
|
|
489
|
+
const mockDate = new Date(2023, 2, 15)
|
|
490
|
+
vi.setSystemTime(mockDate)
|
|
491
|
+
const wrapper = mount(MonthPicker, {
|
|
492
|
+
props: {
|
|
493
|
+
label: 'Début du projet',
|
|
494
|
+
modelValue: '11/2025',
|
|
495
|
+
},
|
|
496
|
+
attachTo: document.body,
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
500
|
+
await nextTick()
|
|
501
|
+
await nextTick()
|
|
502
|
+
|
|
503
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
504
|
+
await toggleBtn.trigger('click')
|
|
505
|
+
const modal = wrapper.findComponent({ name: 'VisualPickerFooter' })
|
|
506
|
+
|
|
507
|
+
const currentMonthBtn = modal.find('.month-picker-footer__current-month-btn')
|
|
508
|
+
await currentMonthBtn.trigger('click')
|
|
509
|
+
|
|
510
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['03/2023']]) // The value should be '03/2023' (March 2023)
|
|
511
|
+
|
|
512
|
+
wrapper.unmount()
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
it('should select the current month and year when no month is selected', async () => {
|
|
516
|
+
// mock current date to 15th March 2023
|
|
517
|
+
const mockDate = new Date(2023, 2, 15)
|
|
518
|
+
vi.setSystemTime(mockDate)
|
|
519
|
+
const wrapper = mount(MonthPicker, {
|
|
520
|
+
props: {
|
|
521
|
+
label: 'Début du projet',
|
|
522
|
+
modelValue: undefined,
|
|
523
|
+
},
|
|
524
|
+
attachTo: document.body,
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
528
|
+
await nextTick()
|
|
529
|
+
await nextTick()
|
|
530
|
+
|
|
531
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
532
|
+
await toggleBtn.trigger('click')
|
|
533
|
+
const modal = wrapper.findComponent({ name: 'VisualPickerFooter' })
|
|
534
|
+
|
|
535
|
+
const currentMonthBtn = modal.find('.month-picker-footer__current-month-btn')
|
|
536
|
+
await currentMonthBtn.trigger('click')
|
|
537
|
+
|
|
538
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['03/2023']]) // The value should be '03/2023' (March 2023)
|
|
539
|
+
|
|
540
|
+
wrapper.unmount()
|
|
541
|
+
})
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
describe('view switcher', () => {
|
|
545
|
+
it('should switch to year selector when clicking on the switch view button in month selector', async () => {
|
|
546
|
+
const wrapper = mount(MonthPicker, {
|
|
547
|
+
props: {
|
|
548
|
+
label: 'Début du projet',
|
|
549
|
+
modelValue: '11/2025',
|
|
550
|
+
},
|
|
551
|
+
attachTo: document.body,
|
|
552
|
+
})
|
|
553
|
+
|
|
554
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
555
|
+
await nextTick()
|
|
556
|
+
await nextTick()
|
|
557
|
+
|
|
558
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
559
|
+
await toggleBtn.trigger('click')
|
|
560
|
+
|
|
561
|
+
const switchViewBtn = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn')
|
|
562
|
+
await switchViewBtn.trigger('click')
|
|
563
|
+
|
|
564
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).exists()).toBeFalsy()
|
|
565
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).isVisible()).toBeTruthy()
|
|
566
|
+
|
|
567
|
+
wrapper.unmount()
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
it('should switch to month selector when clicking on the switch view button in year selector', async () => {
|
|
571
|
+
const wrapper = mount(MonthPicker, {
|
|
572
|
+
props: {
|
|
573
|
+
label: 'Début du projet',
|
|
574
|
+
modelValue: '11/2025',
|
|
575
|
+
},
|
|
576
|
+
attachTo: document.body,
|
|
577
|
+
})
|
|
578
|
+
|
|
579
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
580
|
+
await nextTick()
|
|
581
|
+
await nextTick()
|
|
582
|
+
|
|
583
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
584
|
+
await toggleBtn.trigger('click')
|
|
585
|
+
|
|
586
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
587
|
+
await monthButton.trigger('click')
|
|
588
|
+
|
|
589
|
+
const switchViewBtn = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn')
|
|
590
|
+
await switchViewBtn.trigger('click')
|
|
591
|
+
|
|
592
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).exists()).toBeFalsy()
|
|
593
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).isVisible()).toBeTruthy()
|
|
594
|
+
|
|
595
|
+
wrapper.unmount()
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
it('shows the year selector when the initialView prop is set to year', async () => {
|
|
599
|
+
const wrapper = mount(MonthPicker, {
|
|
600
|
+
props: {
|
|
601
|
+
label: 'Début du projet',
|
|
602
|
+
initialView: 'years',
|
|
603
|
+
},
|
|
604
|
+
attachTo: document.body,
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
608
|
+
await nextTick()
|
|
609
|
+
await nextTick()
|
|
610
|
+
|
|
611
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
612
|
+
await toggleBtn.trigger('click')
|
|
613
|
+
|
|
614
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).isVisible()).toBeTruthy()
|
|
615
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).exists()).toBeFalsy()
|
|
616
|
+
|
|
617
|
+
expect(document.activeElement?.classList).toContain('year-selector__year')
|
|
618
|
+
wrapper.unmount()
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
it('shows the month selector when the initialView prop is set to month', async () => {
|
|
622
|
+
const wrapper = mount(MonthPicker, {
|
|
623
|
+
props: {
|
|
624
|
+
label: 'Début du projet',
|
|
625
|
+
initialView: 'months',
|
|
626
|
+
},
|
|
627
|
+
attachTo: document.body,
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
631
|
+
await nextTick()
|
|
632
|
+
await nextTick()
|
|
633
|
+
|
|
634
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
635
|
+
await toggleBtn.trigger('click')
|
|
636
|
+
|
|
637
|
+
expect(wrapper.findComponent({ name: 'MonthSelector' }).isVisible()).toBeTruthy()
|
|
638
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).exists()).toBeFalsy()
|
|
639
|
+
|
|
640
|
+
expect(document.activeElement?.classList).toContain('month-selector__month')
|
|
641
|
+
wrapper.unmount()
|
|
642
|
+
})
|
|
643
|
+
|
|
644
|
+
it ('focuses the lowerst year when opening the year selector if no year is selected and the order is ascending', async () => {
|
|
645
|
+
const wrapper = mount(MonthPicker, {
|
|
646
|
+
props: {
|
|
647
|
+
label: 'Début du projet',
|
|
648
|
+
initialView: 'years',
|
|
649
|
+
minYear: 2000,
|
|
650
|
+
maxYear: 2020,
|
|
651
|
+
},
|
|
652
|
+
attachTo: document.body,
|
|
653
|
+
})
|
|
654
|
+
|
|
655
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
656
|
+
await nextTick()
|
|
657
|
+
await nextTick()
|
|
658
|
+
|
|
659
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
660
|
+
await toggleBtn.trigger('click')
|
|
661
|
+
|
|
662
|
+
expect(document.activeElement?.classList).toContain('year-2000')
|
|
663
|
+
|
|
664
|
+
wrapper.unmount()
|
|
665
|
+
})
|
|
666
|
+
|
|
667
|
+
it ('focuses the highest year when opening the year selector if no year is selected and the order is descending', async () => {
|
|
668
|
+
const wrapper = mount(MonthPicker, {
|
|
669
|
+
props: {
|
|
670
|
+
label: 'Début du projet',
|
|
671
|
+
initialView: 'years',
|
|
672
|
+
yearsOrder: 'desc',
|
|
673
|
+
minYear: 2000,
|
|
674
|
+
maxYear: 2020,
|
|
675
|
+
},
|
|
676
|
+
attachTo: document.body,
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
680
|
+
await nextTick()
|
|
681
|
+
await nextTick()
|
|
682
|
+
|
|
683
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
684
|
+
await toggleBtn.trigger('click')
|
|
685
|
+
|
|
686
|
+
expect(document.activeElement?.classList).toContain('year-2020')
|
|
687
|
+
|
|
688
|
+
wrapper.unmount()
|
|
689
|
+
})
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
describe('minYear and maxYear props', () => {
|
|
693
|
+
it('should not display years inferior to minYear', async () => {
|
|
694
|
+
const wrapper = mount(MonthPicker, {
|
|
695
|
+
props: {
|
|
696
|
+
label: 'Début du projet',
|
|
697
|
+
modelValue: '11/2025',
|
|
698
|
+
minYear: 2020,
|
|
699
|
+
},
|
|
700
|
+
attachTo: document.body,
|
|
701
|
+
})
|
|
702
|
+
|
|
703
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
704
|
+
await nextTick()
|
|
705
|
+
await nextTick()
|
|
706
|
+
|
|
707
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
708
|
+
await toggleBtn.trigger('click')
|
|
709
|
+
|
|
710
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
711
|
+
await monthButton.trigger('click')
|
|
712
|
+
|
|
713
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2019').exists()).toBeFalsy()
|
|
714
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2020').exists()).toBeTruthy()
|
|
715
|
+
|
|
716
|
+
wrapper.unmount()
|
|
717
|
+
})
|
|
718
|
+
|
|
719
|
+
it('should not display years superior to maxYear', async () => {
|
|
720
|
+
const wrapper = mount(MonthPicker, {
|
|
721
|
+
props: {
|
|
722
|
+
label: 'Début du projet',
|
|
723
|
+
modelValue: '11/2025',
|
|
724
|
+
maxYear: 2025,
|
|
725
|
+
},
|
|
726
|
+
attachTo: document.body,
|
|
727
|
+
})
|
|
728
|
+
|
|
729
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
730
|
+
await nextTick()
|
|
731
|
+
await nextTick()
|
|
732
|
+
|
|
733
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
734
|
+
await toggleBtn.trigger('click')
|
|
735
|
+
|
|
736
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
737
|
+
await monthButton.trigger('click')
|
|
738
|
+
|
|
739
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2026').exists()).toBeFalsy()
|
|
740
|
+
expect(wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025').exists()).toBeTruthy()
|
|
741
|
+
|
|
742
|
+
wrapper.unmount()
|
|
743
|
+
})
|
|
744
|
+
})
|
|
745
|
+
|
|
746
|
+
describe('visual/text input synchronization', () => {
|
|
747
|
+
it('should update the text input when a month and year are selected in the visual picker', async () => {
|
|
748
|
+
const wrapper = mount(MonthPicker, {
|
|
749
|
+
props: {
|
|
750
|
+
label: 'Début du projet',
|
|
751
|
+
modelValue: '11/2025',
|
|
752
|
+
},
|
|
753
|
+
attachTo: document.body,
|
|
754
|
+
})
|
|
755
|
+
|
|
756
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
757
|
+
await nextTick()
|
|
758
|
+
await nextTick()
|
|
759
|
+
|
|
760
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
761
|
+
await toggleBtn.trigger('click')
|
|
762
|
+
|
|
763
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
764
|
+
await monthButton.trigger('click')
|
|
765
|
+
|
|
766
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
767
|
+
await yearButton.trigger('click')
|
|
768
|
+
|
|
769
|
+
expect(wrapper.find('input').element.value).toBe('01/2024') // The input value should be '01/2024'
|
|
770
|
+
|
|
771
|
+
wrapper.unmount()
|
|
772
|
+
})
|
|
773
|
+
|
|
774
|
+
it('should update the visual picker when the text input value changes', async () => {
|
|
775
|
+
const wrapper = mount(MonthPicker, {
|
|
776
|
+
props: {
|
|
777
|
+
label: 'Début du projet',
|
|
778
|
+
modelValue: '11/2025',
|
|
779
|
+
},
|
|
780
|
+
attachTo: document.body,
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
const input = wrapper.find('input')
|
|
784
|
+
await input.setValue('02/2026')
|
|
785
|
+
|
|
786
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
787
|
+
await toggleBtn.trigger('click')
|
|
788
|
+
|
|
789
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-2') // February button
|
|
790
|
+
expect(monthButton.classes()).toContain('month-selector__month--active')
|
|
791
|
+
|
|
792
|
+
await wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn').trigger('click')
|
|
793
|
+
|
|
794
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2026')
|
|
795
|
+
expect(yearButton.classes()).toContain('year-selector__year--active')
|
|
796
|
+
|
|
797
|
+
wrapper.unmount()
|
|
798
|
+
})
|
|
799
|
+
|
|
800
|
+
it('handle correctly month and year that start with 0 in the text input', async () => {
|
|
801
|
+
vi.setSystemTime(new Date(2023, 5, 15))
|
|
802
|
+
const wrapper = mount(MonthPicker, {
|
|
803
|
+
props: {
|
|
804
|
+
label: 'Début du projet',
|
|
805
|
+
modelValue: '01/2025',
|
|
806
|
+
},
|
|
807
|
+
attachTo: document.body,
|
|
808
|
+
})
|
|
809
|
+
|
|
810
|
+
const input = wrapper.find('input')
|
|
811
|
+
await input.setValue('02/025')
|
|
812
|
+
|
|
813
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
814
|
+
await toggleBtn.trigger('click')
|
|
815
|
+
|
|
816
|
+
const activeMonthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-2') // February button
|
|
817
|
+
expect(activeMonthButton.classes()).toContain('month-selector__month--active')
|
|
818
|
+
|
|
819
|
+
await wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-year-btn').trigger('click')
|
|
820
|
+
|
|
821
|
+
const activeYearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-selector__year--active')
|
|
822
|
+
expect(activeYearButton.text()).toBe('2023') // the selector fallback to the current year if the year is not in the range
|
|
823
|
+
expect(activeYearButton.classes()).toContain('year-2023')
|
|
824
|
+
|
|
825
|
+
await toggleBtn.trigger('click') // close the menu
|
|
826
|
+
|
|
827
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([['02/025']])
|
|
828
|
+
expect(wrapper.find('input').element.value).toBe('02/025') // The input value should still be '02/025'
|
|
829
|
+
|
|
830
|
+
wrapper.unmount()
|
|
831
|
+
vi.useRealTimers()
|
|
832
|
+
})
|
|
833
|
+
})
|
|
834
|
+
|
|
835
|
+
describe('visual picker header', () => {
|
|
836
|
+
it('displays the current month and year when none is selected', async () => {
|
|
837
|
+
// mock current date to 15th March 2023
|
|
838
|
+
const mockDate = new Date(2023, 2, 15)
|
|
839
|
+
vi.setSystemTime(mockDate)
|
|
840
|
+
const wrapper = mount(MonthPicker, {
|
|
841
|
+
props: {
|
|
842
|
+
label: 'Début du projet',
|
|
843
|
+
modelValue: undefined,
|
|
844
|
+
},
|
|
845
|
+
attachTo: document.body,
|
|
846
|
+
})
|
|
847
|
+
|
|
848
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
849
|
+
await nextTick()
|
|
850
|
+
await nextTick()
|
|
851
|
+
|
|
852
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
853
|
+
await toggleBtn.trigger('click')
|
|
854
|
+
|
|
855
|
+
const headerText = wrapper
|
|
856
|
+
.findComponent({ name: 'VisualPickerHeader' })
|
|
857
|
+
.find('.visual-picker-header__date')
|
|
858
|
+
.text()
|
|
859
|
+
|
|
860
|
+
expect(headerText).toContain('March')
|
|
861
|
+
expect(headerText).toContain('2023')
|
|
862
|
+
|
|
863
|
+
wrapper.unmount()
|
|
864
|
+
})
|
|
865
|
+
|
|
866
|
+
it('displays the selected month and year', async () => {
|
|
867
|
+
const wrapper = mount(MonthPicker, {
|
|
868
|
+
props: {
|
|
869
|
+
label: 'Début du projet',
|
|
870
|
+
modelValue: '11/2025',
|
|
871
|
+
},
|
|
872
|
+
attachTo: document.body,
|
|
873
|
+
})
|
|
874
|
+
|
|
875
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
876
|
+
await nextTick()
|
|
877
|
+
await nextTick()
|
|
878
|
+
|
|
879
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
880
|
+
await toggleBtn.trigger('click')
|
|
881
|
+
|
|
882
|
+
const headerText = wrapper
|
|
883
|
+
.findComponent({ name: 'VisualPickerHeader' })
|
|
884
|
+
.find('.visual-picker-header__date')
|
|
885
|
+
.text()
|
|
886
|
+
expect(headerText).toBe('November 2025')
|
|
887
|
+
|
|
888
|
+
wrapper.unmount()
|
|
889
|
+
})
|
|
890
|
+
|
|
891
|
+
it('displays the current month and year when the model value is invalid', async () => {
|
|
892
|
+
// mock current date to 15th March 2023
|
|
893
|
+
const mockDate = new Date(2023, 2, 15)
|
|
894
|
+
vi.setSystemTime(mockDate)
|
|
895
|
+
const wrapper = mount(MonthPicker, {
|
|
896
|
+
props: {
|
|
897
|
+
label: 'Début du projet',
|
|
898
|
+
modelValue: '00/2025',
|
|
899
|
+
},
|
|
900
|
+
attachTo: document.body,
|
|
901
|
+
})
|
|
902
|
+
|
|
903
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
904
|
+
await nextTick()
|
|
905
|
+
await nextTick()
|
|
906
|
+
|
|
907
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
908
|
+
await toggleBtn.trigger('click')
|
|
909
|
+
|
|
910
|
+
const headerText = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-header__date').text()
|
|
911
|
+
expect(headerText).toBe('March 2023')
|
|
912
|
+
|
|
913
|
+
wrapper.unmount()
|
|
914
|
+
})
|
|
915
|
+
|
|
916
|
+
it ('displays the current month and year when the model value year is not set', async () => {
|
|
917
|
+
// mock current date to 15th March 2023
|
|
918
|
+
const mockDate = new Date(2023, 2, 15)
|
|
919
|
+
vi.setSystemTime(mockDate)
|
|
920
|
+
const wrapper = mount(MonthPicker, {
|
|
921
|
+
props: {
|
|
922
|
+
label: 'Début du projet',
|
|
923
|
+
modelValue: '05/',
|
|
924
|
+
},
|
|
925
|
+
attachTo: document.body,
|
|
926
|
+
})
|
|
927
|
+
|
|
928
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
929
|
+
await nextTick()
|
|
930
|
+
await nextTick()
|
|
931
|
+
|
|
932
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
933
|
+
await toggleBtn.trigger('click')
|
|
934
|
+
|
|
935
|
+
const headerText = wrapper.findComponent({ name: 'VisualPickerHeader' }).find('.visual-picker-header__date').text()
|
|
936
|
+
expect(headerText).toBe('March 2023')
|
|
937
|
+
|
|
938
|
+
wrapper.unmount()
|
|
939
|
+
})
|
|
940
|
+
})
|
|
941
|
+
|
|
942
|
+
describe('disabled and readonly state', () => {
|
|
943
|
+
it('does not update the model value when the field is disabled', async () => {
|
|
944
|
+
const wrapper = mount(MonthPicker, {
|
|
945
|
+
props: {
|
|
946
|
+
label: 'Début du projet',
|
|
947
|
+
modelValue: '11/2025',
|
|
948
|
+
disabled: true,
|
|
949
|
+
},
|
|
950
|
+
})
|
|
951
|
+
|
|
952
|
+
const input = wrapper.find('input')
|
|
953
|
+
expect(input.attributes('disabled')).toBeDefined()
|
|
954
|
+
|
|
955
|
+
await input.setValue('01/2027')
|
|
956
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy() // The value should not be emitted when the field is disabled
|
|
957
|
+
|
|
958
|
+
wrapper.unmount()
|
|
959
|
+
})
|
|
960
|
+
|
|
961
|
+
it('does not open the visual picker when the field is disabled', async () => {
|
|
962
|
+
const wrapper = mount(MonthPicker, {
|
|
963
|
+
props: {
|
|
964
|
+
label: 'Début du projet',
|
|
965
|
+
modelValue: '11/2025',
|
|
966
|
+
disabled: true,
|
|
967
|
+
},
|
|
968
|
+
attachTo: document.body,
|
|
969
|
+
})
|
|
970
|
+
|
|
971
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
972
|
+
await nextTick()
|
|
973
|
+
await nextTick()
|
|
974
|
+
|
|
975
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
976
|
+
expect(toggleBtn.attributes('disabled')).toBeDefined()
|
|
977
|
+
|
|
978
|
+
await toggleBtn.trigger('click')
|
|
979
|
+
|
|
980
|
+
const modal = wrapper.findComponent({ name: 'MonthPickerVisual' }).find('.month-picker-menu')
|
|
981
|
+
expect(modal.exists()).toBeFalsy() // The month buttons should not be rendered when the field is disabled
|
|
982
|
+
|
|
983
|
+
wrapper.unmount()
|
|
984
|
+
})
|
|
985
|
+
|
|
986
|
+
it('does not update the model value when the field is readonly', async () => {
|
|
987
|
+
const wrapper = mount(MonthPicker, {
|
|
988
|
+
props: {
|
|
989
|
+
label: 'Début du projet',
|
|
990
|
+
modelValue: '11/2025',
|
|
991
|
+
readonly: true,
|
|
992
|
+
},
|
|
993
|
+
})
|
|
994
|
+
|
|
995
|
+
const input = wrapper.find('input')
|
|
996
|
+
expect(input.attributes('readonly')).toBeDefined()
|
|
997
|
+
|
|
998
|
+
await input.setValue('01/2027')
|
|
999
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy() // The value should not be emitted when the field is readonly
|
|
1000
|
+
|
|
1001
|
+
wrapper.unmount()
|
|
1002
|
+
})
|
|
1003
|
+
|
|
1004
|
+
it('does not update the model value when the visual picker is used and the field is readonly', async () => {
|
|
1005
|
+
const wrapper = mount(MonthPicker, {
|
|
1006
|
+
props: {
|
|
1007
|
+
label: 'Début du projet',
|
|
1008
|
+
modelValue: '11/2025',
|
|
1009
|
+
readonly: true,
|
|
1010
|
+
},
|
|
1011
|
+
attachTo: document.body,
|
|
1012
|
+
})
|
|
1013
|
+
|
|
1014
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1015
|
+
await nextTick()
|
|
1016
|
+
await nextTick()
|
|
1017
|
+
|
|
1018
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1019
|
+
await toggleBtn.trigger('click')
|
|
1020
|
+
|
|
1021
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1')
|
|
1022
|
+
await monthButton.trigger('click')
|
|
1023
|
+
|
|
1024
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2024')
|
|
1025
|
+
await yearButton.trigger('click')
|
|
1026
|
+
|
|
1027
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy()
|
|
1028
|
+
expect(wrapper.emitted('update:open')).toEqual([[true], [false]])
|
|
1029
|
+
expect(wrapper.find('input').element.value).toBe('11/2025')
|
|
1030
|
+
|
|
1031
|
+
wrapper.unmount()
|
|
1032
|
+
})
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
describe('localization', () => {
|
|
1036
|
+
afterEach(() => {
|
|
1037
|
+
// reset navigator.language to default value after each test
|
|
1038
|
+
Object.defineProperty(navigator, 'language', {
|
|
1039
|
+
value: 'en-US',
|
|
1040
|
+
writable: true,
|
|
1041
|
+
})
|
|
1042
|
+
})
|
|
1043
|
+
|
|
1044
|
+
it('should display month names in english when the browser locale is english', async () => {
|
|
1045
|
+
const wrapper = mount(MonthPicker, {
|
|
1046
|
+
props: {
|
|
1047
|
+
label: 'Start of the project',
|
|
1048
|
+
modelValue: '11/2025',
|
|
1049
|
+
},
|
|
1050
|
+
attachTo: document.body,
|
|
1051
|
+
})
|
|
1052
|
+
|
|
1053
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1054
|
+
await nextTick()
|
|
1055
|
+
await nextTick()
|
|
1056
|
+
|
|
1057
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1058
|
+
await toggleBtn.trigger('click')
|
|
1059
|
+
|
|
1060
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
1061
|
+
expect(monthButton.attributes('aria-label')).toBe('January')
|
|
1062
|
+
expect(monthButton.text()).toBe('Jan')
|
|
1063
|
+
})
|
|
1064
|
+
|
|
1065
|
+
it('should display month names in french when the browser locale is french', async () => {
|
|
1066
|
+
// mock navigator.language to french
|
|
1067
|
+
Object.defineProperty(navigator, 'language', {
|
|
1068
|
+
value: 'fr-FR',
|
|
1069
|
+
writable: true,
|
|
1070
|
+
})
|
|
1071
|
+
const wrapper = mount(MonthPicker, {
|
|
1072
|
+
props: {
|
|
1073
|
+
label: 'Début du projet',
|
|
1074
|
+
modelValue: '11/2025',
|
|
1075
|
+
},
|
|
1076
|
+
attachTo: document.body,
|
|
1077
|
+
})
|
|
1078
|
+
|
|
1079
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1080
|
+
await nextTick()
|
|
1081
|
+
await nextTick()
|
|
1082
|
+
|
|
1083
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1084
|
+
await toggleBtn.trigger('click')
|
|
1085
|
+
|
|
1086
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
1087
|
+
expect(monthButton.attributes('aria-label')).toBe('janvier')
|
|
1088
|
+
expect(monthButton.text()).toBe('janv.')
|
|
1089
|
+
|
|
1090
|
+
wrapper.unmount()
|
|
1091
|
+
})
|
|
1092
|
+
|
|
1093
|
+
it('display the date in the header according to the locale', async () => {
|
|
1094
|
+
// mock navigator.language to french
|
|
1095
|
+
Object.defineProperty(navigator, 'language', {
|
|
1096
|
+
value: 'fr-FR',
|
|
1097
|
+
writable: true,
|
|
1098
|
+
})
|
|
1099
|
+
const wrapper = mount(MonthPicker, {
|
|
1100
|
+
props: {
|
|
1101
|
+
label: 'Début du projet',
|
|
1102
|
+
modelValue: '11/2025',
|
|
1103
|
+
},
|
|
1104
|
+
attachTo: document.body,
|
|
1105
|
+
})
|
|
1106
|
+
|
|
1107
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1108
|
+
await nextTick()
|
|
1109
|
+
await nextTick()
|
|
1110
|
+
|
|
1111
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1112
|
+
await toggleBtn.trigger('click')
|
|
1113
|
+
|
|
1114
|
+
const headerText = wrapper
|
|
1115
|
+
.findComponent({ name: 'VisualPickerHeader' })
|
|
1116
|
+
.find('.visual-picker-header__date')
|
|
1117
|
+
.text()
|
|
1118
|
+
|
|
1119
|
+
expect(headerText).toBe('novembre 2025') // The header should display the date in the format "month year" in lowercase and in french
|
|
1120
|
+
|
|
1121
|
+
wrapper.unmount()
|
|
1122
|
+
})
|
|
1123
|
+
|
|
1124
|
+
it('display the date in the header according to the locale', async () => {
|
|
1125
|
+
// mock navigator.language to German
|
|
1126
|
+
Object.defineProperty(navigator, 'language', {
|
|
1127
|
+
value: 'de-DE',
|
|
1128
|
+
writable: true,
|
|
1129
|
+
})
|
|
1130
|
+
const wrapper = mount(MonthPicker, {
|
|
1131
|
+
props: {
|
|
1132
|
+
label: 'Projektbeginn',
|
|
1133
|
+
modelValue: '02/2025',
|
|
1134
|
+
},
|
|
1135
|
+
attachTo: document.body,
|
|
1136
|
+
})
|
|
1137
|
+
|
|
1138
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1139
|
+
await nextTick()
|
|
1140
|
+
await nextTick()
|
|
1141
|
+
|
|
1142
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1143
|
+
await toggleBtn.trigger('click')
|
|
1144
|
+
|
|
1145
|
+
const headerText = wrapper
|
|
1146
|
+
.findComponent({ name: 'VisualPickerHeader' })
|
|
1147
|
+
.find('.visual-picker-header__date')
|
|
1148
|
+
.text()
|
|
1149
|
+
|
|
1150
|
+
expect(headerText).toBe('Februar 2025') // The header should display the date in the format "month year" in German
|
|
1151
|
+
|
|
1152
|
+
wrapper.unmount()
|
|
1153
|
+
})
|
|
1154
|
+
})
|
|
1155
|
+
describe('validation', () => {
|
|
1156
|
+
it('show the error message when the input value is invalid', async () => {
|
|
1157
|
+
const wrapper = mount(MonthPicker, {
|
|
1158
|
+
props: {
|
|
1159
|
+
label: 'Début du projet',
|
|
1160
|
+
customRules: [{
|
|
1161
|
+
type: 'custom',
|
|
1162
|
+
options: {
|
|
1163
|
+
validate: (value: string) => {
|
|
1164
|
+
const regex = /^(0[1-9]|1[0-2])\/\d{4}$/
|
|
1165
|
+
return regex.test(value) || 'Invalid month/year format. Use MM/YYYY.'
|
|
1166
|
+
},
|
|
1167
|
+
message: 'Invalid month/year format. Use MM/YYYY.',
|
|
1168
|
+
},
|
|
1169
|
+
}],
|
|
1170
|
+
},
|
|
1171
|
+
})
|
|
1172
|
+
|
|
1173
|
+
const input = wrapper.find('input')
|
|
1174
|
+
await input.setValue('99/2025')
|
|
1175
|
+
await input.trigger('blur')
|
|
1176
|
+
|
|
1177
|
+
expect(wrapper.find('.v-field--error').exists()).toBe(true)
|
|
1178
|
+
expect(wrapper.find('.v-input__details').text()).toBe('Invalid month/year format. Use MM/YYYY.')
|
|
1179
|
+
|
|
1180
|
+
wrapper.unmount()
|
|
1181
|
+
})
|
|
1182
|
+
|
|
1183
|
+
it('should not show an error message when the input value is valid', async () => {
|
|
1184
|
+
const wrapper = mount(MonthPicker, {
|
|
1185
|
+
props: {
|
|
1186
|
+
label: 'Début du projet',
|
|
1187
|
+
customRules: [{
|
|
1188
|
+
type: 'custom',
|
|
1189
|
+
options: {
|
|
1190
|
+
validate: (value: string) => {
|
|
1191
|
+
const regex = /^(0[1-9]|1[0-2])\/\d{4}$/
|
|
1192
|
+
return regex.test(value) || 'Invalid month/year format. Use MM/YYYY.'
|
|
1193
|
+
},
|
|
1194
|
+
message: 'Invalid month/year format. Use MM/YYYY.',
|
|
1195
|
+
},
|
|
1196
|
+
}],
|
|
1197
|
+
},
|
|
1198
|
+
})
|
|
1199
|
+
|
|
1200
|
+
const input = wrapper.find('input')
|
|
1201
|
+
await input.setValue('12/2025')
|
|
1202
|
+
await input.trigger('blur')
|
|
1203
|
+
await input.trigger('focus')
|
|
1204
|
+
|
|
1205
|
+
expect(wrapper.find('.v-field--error').exists()).toBe(false)
|
|
1206
|
+
expect(wrapper.find('.v-input__details').text()).toBe('Format MM/AAAA')
|
|
1207
|
+
|
|
1208
|
+
wrapper.unmount()
|
|
1209
|
+
})
|
|
1210
|
+
|
|
1211
|
+
it ('show the error when the value is selected in the visual picker', async () => {
|
|
1212
|
+
const wrapper = mount(MonthPicker, {
|
|
1213
|
+
props: {
|
|
1214
|
+
label: 'Début du projet',
|
|
1215
|
+
customRules: [{
|
|
1216
|
+
type: 'custom',
|
|
1217
|
+
options: {
|
|
1218
|
+
validate: (value: string) => {
|
|
1219
|
+
const year = value.split('/')[1]
|
|
1220
|
+
return !!year && parseInt(year!) >= 2026
|
|
1221
|
+
},
|
|
1222
|
+
message: 'The year must be 2026 or later.',
|
|
1223
|
+
},
|
|
1224
|
+
}],
|
|
1225
|
+
},
|
|
1226
|
+
attachTo: document.body,
|
|
1227
|
+
})
|
|
1228
|
+
|
|
1229
|
+
// Wait for the VMenu to resolve the differents ref used to find the activator element
|
|
1230
|
+
await nextTick()
|
|
1231
|
+
await nextTick()
|
|
1232
|
+
|
|
1233
|
+
const toggleBtn = wrapper.find('.month-picker-input__toggle-btn')
|
|
1234
|
+
await toggleBtn.trigger('click')
|
|
1235
|
+
|
|
1236
|
+
const monthButton = wrapper.findComponent({ name: 'MonthSelector' }).find('.month-1') // January button
|
|
1237
|
+
await monthButton.trigger('click')
|
|
1238
|
+
|
|
1239
|
+
const yearButton = wrapper.findComponent({ name: 'YearSelector' }).find('.year-2025')
|
|
1240
|
+
await yearButton.trigger('click')
|
|
1241
|
+
|
|
1242
|
+
expect(wrapper.find('.v-field--error').exists()).toBe(true)
|
|
1243
|
+
expect(wrapper.find('.v-input__details').text()).toBe('The year must be 2026 or later.')
|
|
1244
|
+
|
|
1245
|
+
wrapper.unmount()
|
|
1246
|
+
})
|
|
1247
|
+
})
|
|
1248
|
+
})
|