@cnamts/synapse 1.0.26 → 1.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/{AutocompleteFilter-BPR-a55G.js → AutocompleteFilter-C9eLKyW8.js} +3 -3
  2. package/dist/{DateFilter-CknrJWs2.js → DateFilter-y-GLkAkn.js} +8 -8
  3. package/dist/{NumberFilter-DJ-yNlzv.js → NumberFilter-DN6hIBS7.js} +1 -1
  4. package/dist/{PeriodFilter-CiB5Oa9Z.js → PeriodFilter-MoUUp9qS.js} +1 -1
  5. package/dist/{SelectFilter-EiafX97M.js → SelectFilter-bCbrdLmu.js} +1 -1
  6. package/dist/{TextFilter-BzOmpdxj.js → TextFilter-CvjgEaoM.js} +4 -4
  7. package/dist/apLightTheme2026-ug4Y23ns.js +611 -0
  8. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +2369 -353
  9. package/dist/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.d.ts +18 -0
  10. package/dist/components/Customs/Selects/SyAutocomplete/utils/ariaManager.d.ts +1 -1
  11. package/dist/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.d.ts +3 -1
  12. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +9 -10
  13. package/dist/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.d.ts +1 -0
  14. package/dist/components/Customs/Selects/SySelect/composables/useSySelectValidation.d.ts +15 -0
  15. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +3 -3
  16. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +3 -3
  17. package/dist/components/Customs/SyIconButton/SyIconButton.d.ts +18 -0
  18. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +20 -38
  19. package/dist/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.d.ts +50 -0
  20. package/dist/components/Customs/SyTextField/SyTextField.d.ts +6 -6
  21. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +147 -136
  22. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +62 -54
  23. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +27 -24
  24. package/dist/components/DatePicker/composables/index.d.ts +1 -0
  25. package/dist/components/DatePicker/composables/useDatePickerValidationBridge.d.ts +51 -0
  26. package/dist/components/MonthPicker/MonthPicker.d.ts +23 -23
  27. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +23 -23
  28. package/dist/components/NirField/NirField.d.ts +56 -56
  29. package/dist/components/PasswordField/PasswordField.d.ts +3 -3
  30. package/dist/components/PeriodField/PeriodField.d.ts +236 -212
  31. package/dist/components/PhoneField/PhoneField.d.ts +23 -23
  32. package/dist/components/SyTextArea/SyTextArea.d.ts +25 -15
  33. package/dist/components/SyTextArea/composables/useSyTextAreaValidation.d.ts +20 -0
  34. package/dist/components/SyTextArea/locales.d.ts +1 -0
  35. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +1 -0
  36. package/dist/components/Tables/SyTable/SyTable.d.ts +1 -0
  37. package/dist/components/Tables/common/SyTablePagination.d.ts +25 -25
  38. package/dist/components/Tables/common/types.d.ts +2 -0
  39. package/dist/components/index.d.ts +1 -0
  40. package/dist/composables/unifyValidation/documentationValidationProps.d.ts +160 -160
  41. package/dist/composables/unifyValidation/useValidation.d.ts +16 -14
  42. package/dist/design-system-v3.js +81 -80
  43. package/dist/designTokens/tokens/amelipro/apContextual.d.ts +6 -6
  44. package/dist/designTokens/tokens/amelipro/apDarkTheme.d.ts +3 -1
  45. package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +53 -100
  46. package/dist/designTokens/tokens/baseContextualTokens.d.ts +0 -6
  47. package/dist/designTokens/tokens/baseTokens.d.ts +232 -0
  48. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +6 -6
  49. package/dist/designTokens/tokens/cnam/cnamDarkTheme.d.ts +1 -1
  50. package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +57 -101
  51. package/dist/designTokens/tokens/pa/paContextual.d.ts +0 -6
  52. package/dist/designTokens/tokens/pa/paDarkTheme.d.ts +1 -1
  53. package/dist/designTokens/tokens/pa/paLightTheme.d.ts +53 -97
  54. package/dist/designTokens/tokens/pa/paSemantic.d.ts +1 -0
  55. package/dist/designTokens/tokens/semanticTokens.d.ts +112 -0
  56. package/dist/main-CI6Q9nmO.js +39234 -0
  57. package/dist/synapse.css +1 -1
  58. package/dist/vuetifyConfig.js +208 -72
  59. package/package.json +4 -2
  60. package/src/assets/overrides/_icons.scss +5 -4
  61. package/src/assets/overrides/_otp.scss +4 -4
  62. package/src/assets/overrides/_typography.scss +2 -1
  63. package/src/assets/overrides/_utilities.scss +1 -42
  64. package/src/components/ChipList/ChipList.vue +30 -18
  65. package/src/components/ChipList/tests/chipList.spec.ts +4 -4
  66. package/src/components/CopyBtn/CopyBtn.vue +2 -2
  67. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.stories.ts +4 -0
  68. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +7 -6
  69. package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +223 -0
  70. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +283 -351
  71. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +182 -218
  72. package/src/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.ts +101 -0
  73. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +761 -1
  74. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +3 -1
  75. package/src/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.ts +79 -5
  76. package/src/components/Customs/Selects/SyAutocomplete/validation/Validation.stories.ts +1029 -0
  77. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +9 -491
  78. package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -79
  79. package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +3 -0
  80. package/src/components/Customs/Selects/SySelect/composables/useSySelectValidation.ts +64 -0
  81. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +196 -0
  82. package/src/components/Customs/Selects/SySelect/validation/Validation.stories.ts +1026 -0
  83. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +18 -7
  84. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +2 -2
  85. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +8 -8
  86. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +8 -8
  87. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +1 -1
  88. package/src/components/Customs/SyIcon/accessibilite/Accessibility.mdx +0 -6
  89. package/src/components/Customs/SyIcon/utils/tests/iconUtils.spec.ts +107 -0
  90. package/src/components/Customs/SyRadioGroup/SyRadioGroup.mdx +2 -2
  91. package/src/components/Customs/SyRadioGroup/SyRadioGroup.stories.ts +395 -200
  92. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +82 -127
  93. package/src/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.ts +127 -0
  94. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.a11y.spec.ts +93 -1
  95. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.spec.ts +146 -9
  96. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.visual.cy.ts +165 -0
  97. package/src/components/Customs/SyRadioGroup/validation/Validation.stories.ts +773 -0
  98. package/src/components/Customs/SyTabs/config.ts +3 -3
  99. package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +265 -0
  100. package/src/components/Customs/SyTabs/tests/useTabTransition.spec.ts +188 -0
  101. package/src/components/Customs/SyTextField/SyTextField.stories.ts +10 -29
  102. package/src/components/Customs/SyTextField/SyTextField.vue +23 -15
  103. package/src/components/DataList/DataList.stories.ts +1 -1
  104. package/src/components/DataListItem/tests/DataListItem.spec.ts +3 -1
  105. package/src/components/DatePicker/CalendarMode/DatePicker.vue +37 -142
  106. package/src/components/DatePicker/CalendarMode/tests/DatePicker.coverage.spec.ts +156 -0
  107. package/src/components/DatePicker/CalendarMode/tests/DatePicker.spec.ts +495 -4
  108. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +47 -66
  109. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +206 -0
  110. package/src/components/DatePicker/ComplexDatePicker/tests/bridge-integration.regression.spec.ts +210 -0
  111. package/src/components/DatePicker/ComplexDatePicker/tests/calendar-navigation.regression.spec.ts +214 -0
  112. package/src/components/DatePicker/ComplexDatePicker/tests/validation-cross.regression.spec.ts +194 -0
  113. package/src/components/DatePicker/ComplexDatePicker/tests/validation-success-messages.regression.spec.ts +83 -0
  114. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +129 -54
  115. package/src/components/DatePicker/DateTextInput/tests/DateTextInput.spec.ts +320 -0
  116. package/src/components/DatePicker/composables/index.ts +1 -0
  117. package/src/components/DatePicker/composables/tests/useCalendarKeyboardNavigation.spec.ts +360 -0
  118. package/src/components/DatePicker/composables/tests/useDatePickerValidationBridge.spec.ts +129 -0
  119. package/src/components/DatePicker/composables/useDatePickerValidationBridge.ts +205 -0
  120. package/src/components/DatePicker/docExamples/BidirectionalComplexValidation.vue +1 -1
  121. package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +1 -1
  122. package/src/components/DatePicker/tests/exposed-methods.coverage.spec.ts +75 -0
  123. package/src/components/DialogBox/DialogBox.vue +1 -1
  124. package/src/components/FileList/UploadItem/UploadItem.vue +4 -4
  125. package/src/components/FileUpload/FileUpload.vue +2 -2
  126. package/src/components/FileUpload/FileUploadContent.vue +1 -1
  127. package/src/components/FilterInline/FilterInline.mdx +2 -2
  128. package/src/components/FilterSideBar/FilterSideBar.stories.ts +1 -1
  129. package/src/components/FilterSideBar/FilterSideBar.vue +2 -2
  130. package/src/components/FooterBar/FooterBar.vue +7 -7
  131. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +1 -1
  132. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +2 -2
  133. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +7 -7
  134. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +2 -2
  135. package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +87 -8
  136. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +3 -3
  137. package/src/components/HeaderNavigationBar/HorizontalNavbar/tests/HorizontalNavbar.spec.ts +589 -0
  138. package/src/components/HeaderToolbar/tests/HeaderToolBar.spec.ts +153 -1
  139. package/src/components/HeaderToolbar/tests/useMobileRightMenu.spec.ts +258 -0
  140. package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +2 -2
  141. package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +1 -1
  142. package/src/components/LunarCalendar/tests/useLunarCalendarRules.spec.ts +184 -0
  143. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +3 -3
  144. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +1 -1
  145. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +2 -2
  146. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +1 -1
  147. package/src/components/NirField/NirField.vue +3 -3
  148. package/src/components/NotificationBar/Notification/Notification.vue +12 -12
  149. package/src/components/NotificationBar/NotificationBar.stories.ts +8 -8
  150. package/src/components/PaginatedTable/Pagination.vue +2 -2
  151. package/src/components/PasswordField/PasswordField.vue +8 -8
  152. package/src/components/PasswordField/tests/PasswordField.spec.ts +3 -3
  153. package/src/components/RangeField/RangeSlider/RangeSlider.vue +2 -2
  154. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +1 -1
  155. package/src/components/StatusPage/tests/StatusPage.spec.ts +149 -0
  156. package/src/components/SubHeader/SubHeader.vue +1 -1
  157. package/src/components/SyAlert/SyAlert.vue +23 -23
  158. package/src/components/SyTextArea/SyTextArea.stories.ts +177 -131
  159. package/src/components/SyTextArea/SyTextArea.vue +235 -83
  160. package/src/components/SyTextArea/composables/useSyTextAreaValidation.ts +81 -0
  161. package/src/components/SyTextArea/locales.ts +1 -0
  162. package/src/components/SyTextArea/tests/SyTextArea.spec.ts +449 -1
  163. package/src/components/SyTextArea/useDefaultValidationRules.ts +2 -7
  164. package/src/components/SyTextArea/validation/Validation.stories.ts +856 -0
  165. package/src/components/TableToolbar/TableToolbar.vue +6 -6
  166. package/src/components/TableToolbar/accessibilite/Accessibility.mdx +81 -7
  167. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +163 -0
  168. package/src/components/Tables/SyServerTable/SyServerTable.vue +2 -1
  169. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +67 -0
  170. package/src/components/Tables/SyTable/SyTable.stories.ts +94 -0
  171. package/src/components/Tables/SyTable/SyTable.vue +2 -1
  172. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +64 -0
  173. package/src/components/Tables/common/TableHeader.vue +2 -2
  174. package/src/components/Tables/common/filters/logics/tests/NumberFilterLogic.spec.ts +176 -0
  175. package/src/components/Tables/common/filters/logics/tests/SelectFilterLogic.spec.ts +111 -0
  176. package/src/components/Tables/common/tableStyles.scss +6 -6
  177. package/src/components/Tables/common/types.ts +2 -0
  178. package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +2 -0
  179. package/src/components/index.ts +1 -0
  180. package/src/composables/date/tests/useDateFormatDayjs.spec.ts +31 -0
  181. package/src/composables/date/tests/useHolidayDay.spec.ts +109 -0
  182. package/src/composables/rules/tests/useFieldValidation.spec.ts +374 -0
  183. package/src/composables/tests/useError.spec.ts +30 -0
  184. package/src/composables/tests/useFormFieldErrorHandling.spec.ts +234 -0
  185. package/src/composables/unifyValidation/documentationValidationProps.ts +5 -5
  186. package/src/composables/unifyValidation/tests/documentationValidationProps.spec.ts +177 -0
  187. package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +30 -0
  188. package/src/composables/unifyValidation/tests/useValidation.spec.ts +6 -2
  189. package/src/composables/unifyValidation/useCustomValidation.ts +19 -9
  190. package/src/composables/unifyValidation/useValidation.ts +18 -21
  191. package/src/composables/useFilterable/useFilterable.spec.ts +42 -0
  192. package/src/composables/useFilterable/useFilterable.ts +11 -7
  193. package/src/composables/useFormFieldErrorHandling.ts +2 -2
  194. package/src/composantsVuetify/VBtn/VBtn.mdx +9 -39
  195. package/src/composantsVuetify/VBtn/v-btn.stories.ts +26 -86
  196. package/src/designTokens/tokens/amelipro/apContextual.ts +6 -0
  197. package/src/designTokens/tokens/amelipro/apDarkTheme.ts +2 -2
  198. package/src/designTokens/tokens/amelipro/apLightTheme.ts +72 -103
  199. package/src/designTokens/tokens/amelipro/apSemantic.ts +1 -1
  200. package/src/designTokens/tokens/baseContextualTokens.ts +1 -6
  201. package/src/designTokens/tokens/baseTokens.ts +232 -0
  202. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -0
  203. package/src/designTokens/tokens/cnam/cnamDarkTheme.ts +2 -2
  204. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +76 -104
  205. package/src/designTokens/tokens/pa/paDarkTheme.ts +2 -2
  206. package/src/designTokens/tokens/pa/paLightTheme.ts +73 -99
  207. package/src/designTokens/tokens/pa/paSemantic.ts +2 -0
  208. package/src/designTokens/tokens/semanticTokens.ts +114 -0
  209. package/src/stories/Components/Components.stories.ts +7 -3
  210. package/src/stories/DesignTokens/ColorIntegrationExample.vue +2 -3
  211. package/src/stories/DesignTokens/Colors.mdx +6 -8
  212. package/src/stories/DesignTokens/colors.stories.ts +244 -1081
  213. package/src/utils/amelipro/toKebabCase/tests/toKebabCase.spec.ts +52 -0
  214. package/src/utils/formatNir/tests/formatNir.spec.ts +34 -0
  215. package/src/utils/tests/insertAt.spec.ts +44 -0
  216. package/dist/apLightTheme-DS0Uy44H.js +0 -954
  217. package/dist/components/RatingPicker/tests/RatingPicker.a11y.spect.d.ts +0 -1
  218. package/dist/main-BsJ9ec3i.js +0 -38954
  219. package/src/components/BackBtn/tests/__snapshots__/back-btn-custom-bg.snap.png +0 -0
  220. package/src/components/BackBtn/tests/__snapshots__/back-btn-dark-mode.snap.png +0 -0
  221. package/src/components/BackBtn/tests/__snapshots__/back-btn-default.snap.png +0 -0
  222. package/src/components/BackBtn/tests/__snapshots__/back-btn-no-icon.snap.png +0 -0
  223. package/src/components/DatePicker/CalendarMode/tests/DatePicker.events.spec.ts +0 -178
  224. package/src/components/DialogBox/tests/__snapshots__/dialog-box-custom-texts.snap.png +0 -0
  225. package/src/components/DialogBox/tests/__snapshots__/dialog-box-default.snap.png +0 -0
  226. package/src/components/DialogBox/tests/__snapshots__/dialog-box-no-actions.snap.png +0 -0
  227. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated-submenu-open.snap.png +0 -0
  228. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated.snap.png +0 -0
  229. package/src/components/HeaderBar/tests/__snapshots__/header-bar-custom-width.snap.png +0 -0
  230. package/src/components/HeaderBar/tests/__snapshots__/header-bar-default.snap.png +0 -0
  231. package/src/components/HeaderBar/tests/__snapshots__/header-bar-no-sticky.snap.png +0 -0
  232. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-prepend.snap.png +0 -0
  233. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-side.snap.png +0 -0
  234. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-subtitle.snap.png +0 -0
  235. package/src/components/Logo/tests/__snapshots__/logo-avatar.snap.png +0 -0
  236. package/src/components/Logo/tests/__snapshots__/logo-dark.snap.png +0 -0
  237. package/src/components/Logo/tests/__snapshots__/logo-default.snap.png +0 -0
  238. package/src/components/Logo/tests/__snapshots__/logo-no-organism.snap.png +0 -0
  239. package/src/components/Logo/tests/__snapshots__/logo-no-signature.snap.png +0 -0
  240. package/src/components/Logo/tests/__snapshots__/logo-risque-pro.snap.png +0 -0
  241. package/src/components/RangeField/tests/__snapshots__/range-field-custom-bg.snap.png +0 -0
  242. package/src/components/RangeField/tests/__snapshots__/range-field-custom-range.snap.png +0 -0
  243. package/src/components/RangeField/tests/__snapshots__/range-field-default.snap.png +0 -0
  244. package/src/components/RangeField/tests/__snapshots__/range-field-step.snap.png +0 -0
  245. package/src/components/RangeField/tests/__snapshots__/range-field-with-label.snap.png +0 -0
  246. package/src/components/SyAlert/tests/__snapshots__/sy-alert-closable.snap.png +0 -0
  247. package/src/components/SyAlert/tests/__snapshots__/sy-alert-error.snap.png +0 -0
  248. package/src/components/SyAlert/tests/__snapshots__/sy-alert-info.snap.png +0 -0
  249. package/src/components/SyAlert/tests/__snapshots__/sy-alert-success.snap.png +0 -0
  250. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-outlined.snap.png +0 -0
  251. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-tonal.snap.png +0 -0
  252. package/src/components/SyAlert/tests/__snapshots__/sy-alert-warning.snap.png +0 -0
  253. /package/src/components/RatingPicker/tests/{RatingPicker.a11y.spect.ts → RatingPicker.a11y.spec.ts} +0 -0
@@ -0,0 +1,214 @@
1
+ import { mount, flushPromises } from '@vue/test-utils'
2
+ import { describe, it, expect } from 'vitest'
3
+ import { nextTick } from 'vue'
4
+ import ComplexDatePicker from '../ComplexDatePicker.vue'
5
+
6
+ /**
7
+ * Tests de régression pour la navigation du calendrier
8
+ * Bug précédent : currentMonthName ne se mettait pas à jour via les flèches
9
+ */
10
+ describe('Calendar Navigation Regression Tests', () => {
11
+ /**
12
+ * Test 1 : Navigation mois via flèches met à jour l'affichage
13
+ */
14
+ it('met à jour currentMonthName quand on navigue via les flèches', async () => {
15
+ const wrapper = mount(ComplexDatePicker, {
16
+ props: {
17
+ modelValue: '15/05/2025',
18
+ label: 'Date',
19
+ format: 'DD/MM/YYYY',
20
+ },
21
+ })
22
+
23
+ // Attendre l'initialisation
24
+ await flushPromises()
25
+
26
+ // Ouvrir le calendrier (via propriété directe pour éviter les listeners)
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ ;(wrapper.vm as any).isDatePickerVisible = true
29
+ await nextTick()
30
+
31
+ // Le mois affiché doit correspondre à la date sélectionnée (mai)
32
+ // Note: On ne peut pas tester directement le DOM interne de VDatePicker
33
+ // mais on peut vérifier que selectedDates est bien synchronisé
34
+ const emitted = wrapper.emitted('date-selected')
35
+ expect(emitted).toBeTruthy()
36
+
37
+ wrapper.unmount()
38
+ })
39
+
40
+ /**
41
+ * Test 2 : Clear réinitialise le calendrier
42
+ * Bug production : VDatePicker gardait l'ancienne date après clear
43
+ */
44
+ it('reset le calendrier après clear', async () => {
45
+ const wrapper = mount(ComplexDatePicker, {
46
+ props: {
47
+ modelValue: '15/05/2025',
48
+ label: 'Date',
49
+ format: 'DD/MM/YYYY',
50
+ },
51
+ })
52
+
53
+ await flushPromises()
54
+
55
+ // Simuler un clear
56
+ await wrapper.find('input').setValue('')
57
+ await wrapper.find('input').trigger('blur')
58
+ await flushPromises()
59
+
60
+ // Vérifier que le model est mis à jour
61
+ const emitted = wrapper.emitted('update:modelValue')
62
+ const lastValue = emitted?.[emitted.length - 1]?.[0]
63
+ expect(lastValue).toBeNull()
64
+
65
+ wrapper.unmount()
66
+ })
67
+
68
+ /**
69
+ * Test 3 : Réouverture avec date déjà sélectionnée
70
+ * Bug : Navigation bloquée après réouverture
71
+ */
72
+ it('permet la navigation après réouverture du calendrier', async () => {
73
+ const wrapper = mount(ComplexDatePicker, {
74
+ props: {
75
+ modelValue: '',
76
+ label: 'Date',
77
+ format: 'DD/MM/YYYY',
78
+ },
79
+ })
80
+
81
+ // Ouvrir le calendrier (via propriété directe)
82
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ ;(wrapper.vm as any).isDatePickerVisible = true
84
+ await nextTick()
85
+
86
+ // Vérifier que l'input est interactif
87
+ const input = wrapper.find('input')
88
+ expect(input.exists()).toBe(true)
89
+
90
+ // Fermer avec Escape
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ ;(wrapper.vm as any).isDatePickerVisible = false
93
+ await nextTick()
94
+
95
+ // Réouvrir (via propriété directe)
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ ;(wrapper.vm as any).isDatePickerVisible = true
98
+ await nextTick()
99
+
100
+ // L'input doit toujours être interactif (pas de blocage)
101
+ expect(wrapper.find('input').exists()).toBe(true)
102
+
103
+ wrapper.unmount()
104
+ })
105
+
106
+ /**
107
+ * Test 4 : Synchronisation selectedDates avec input
108
+ * Bug : selectedDates et textInputValue désynchronisés
109
+ */
110
+ it('synchronise selectedDates avec la valeur de l\'input', async () => {
111
+ const wrapper = mount(ComplexDatePicker, {
112
+ props: {
113
+ modelValue: '',
114
+ label: 'Date',
115
+ format: 'DD/MM/YYYY',
116
+ },
117
+ })
118
+
119
+ // Saisir une date
120
+ const input = wrapper.find('input')
121
+ await input.setValue('20/06/2025')
122
+ await input.trigger('blur')
123
+ await flushPromises()
124
+
125
+ // La date doit être émise
126
+ const emitted = wrapper.emitted('update:modelValue')
127
+ expect(emitted).toBeTruthy()
128
+ expect(emitted && emitted[0] && emitted[0][0]).toBe('20/06/2025')
129
+
130
+ // Le date-selected doit aussi être émis
131
+ const dateSelected = wrapper.emitted('date-selected')
132
+ expect(dateSelected).toBeTruthy()
133
+
134
+ wrapper.unmount()
135
+ })
136
+
137
+ /**
138
+ * Test 5 : Mode range - sélection de plage complète
139
+ */
140
+ it('gère correctement la sélection de plage de dates', async () => {
141
+ const wrapper = mount(ComplexDatePicker, {
142
+ props: {
143
+ modelValue: '',
144
+ label: 'Période',
145
+ format: 'DD/MM/YYYY',
146
+ displayRange: true,
147
+ },
148
+ })
149
+
150
+ // Saisir une plage
151
+ const input = wrapper.find('input')
152
+ await input.setValue('01/06/2025 - 15/06/2025')
153
+ await input.trigger('blur')
154
+ await flushPromises()
155
+
156
+ // Le model doit être un array
157
+ const emitted = wrapper.emitted('update:modelValue')
158
+ expect(emitted).toBeTruthy()
159
+ const value = emitted && emitted[0] && emitted[0][0]
160
+ expect(Array.isArray(value)).toBe(true)
161
+ if (Array.isArray(value)) {
162
+ expect(value).toHaveLength(2)
163
+ }
164
+
165
+ wrapper.unmount()
166
+ })
167
+
168
+ /**
169
+ * Test 6 : fieldKey pour re-render (bug production)
170
+ * Bug : VDatePicker ne se réinitialisait pas après clear en production
171
+ * Solution : fieldKey force la recréation du composant
172
+ */
173
+ it('utilise fieldKey pour forcer le re-render après clear', async () => {
174
+ const wrapper = mount(ComplexDatePicker, {
175
+ props: {
176
+ modelValue: '15/05/2025',
177
+ label: 'Date',
178
+ format: 'DD/MM/YYYY',
179
+ },
180
+ })
181
+
182
+ // Vérifier que fieldKey existe (utilisé pour forcer le re-render)
183
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Testing internal implementation
184
+ expect((wrapper.vm as any).fieldKey).toBeDefined()
185
+
186
+ wrapper.unmount()
187
+ })
188
+
189
+ /**
190
+ * Test 7 : Reset view mode à l'ouverture
191
+ * Bug : Navigation bloquée après réouverture
192
+ */
193
+ it('reset view mode quand le calendrier s\'ouvre', async () => {
194
+ const wrapper = mount(ComplexDatePicker, {
195
+ props: {
196
+ modelValue: '',
197
+ label: 'Date',
198
+ format: 'DD/MM/YYYY',
199
+ },
200
+ })
201
+
202
+ // Ouvrir le calendrier
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
+ await (wrapper.vm as any).openDatePicker()
205
+ await nextTick()
206
+
207
+ // Vérifier que le view mode est bien initialisé
208
+ // (la propriété exacte dépend de l'implémentation)
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
+ expect((wrapper.vm as any).currentViewMode || (wrapper.vm as any).viewMode).toBeDefined()
211
+
212
+ wrapper.unmount()
213
+ })
214
+ })
@@ -0,0 +1,194 @@
1
+ import { mount, flushPromises } from '@vue/test-utils'
2
+ import { describe, it, expect } from 'vitest'
3
+ import { nextTick, ref, computed } from 'vue'
4
+ import ComplexDatePicker from '../ComplexDatePicker.vue'
5
+
6
+ /**
7
+ * Tests de régression pour la validation croisée (dateA -> dateB)
8
+ * Bug précédent : Les règles dateBRules ne se mettaient pas à jour quand dateA changeait
9
+ */
10
+ describe('Validation Croisée Regression Tests', () => {
11
+ /**
12
+ * Test 1 : notBeforeDate avec date dynamique
13
+ * Scénario : Date B ne peut pas être avant Date A
14
+ */
15
+ it('met à jour la validation de Date B quand Date A change', async () => {
16
+ const dateA = ref('15/05/2025')
17
+
18
+ // Date B avec règle notBeforeDate qui dépend de dateA
19
+ const dateBRules = computed(() => [
20
+ {
21
+ type: 'notBeforeDate',
22
+ options: {
23
+ date: dateA.value,
24
+ message: 'Date B doit être après Date A',
25
+ },
26
+ },
27
+ ])
28
+
29
+ const wrapper = mount(ComplexDatePicker, {
30
+ props: {
31
+ modelValue: '',
32
+ label: 'Date B',
33
+ format: 'DD/MM/YYYY',
34
+ customRules: dateBRules.value,
35
+ showSuccessMessages: true,
36
+ },
37
+ })
38
+
39
+ // Date B avant Date A (doit être invalide)
40
+ const input = wrapper.find('input')
41
+ await input.setValue('10/05/2025')
42
+ await input.trigger('blur')
43
+ await flushPromises()
44
+
45
+ // Doit avoir une erreur
46
+ let errors = wrapper.findAll('.v-messages__message--error')
47
+ expect(errors.length).toBeGreaterThan(0)
48
+
49
+ // Changer Date A pour être avant Date B
50
+ dateA.value = '05/05/2025'
51
+ await wrapper.setProps({
52
+ customRules: [
53
+ {
54
+ type: 'notBeforeDate',
55
+ options: {
56
+ date: dateA.value,
57
+ message: 'Date B doit être après Date A',
58
+ },
59
+ },
60
+ ],
61
+ })
62
+ await nextTick()
63
+
64
+ // Re-valider
65
+ await input.trigger('blur')
66
+ await flushPromises()
67
+
68
+ // Maintenant c'est valide (10/05 >= 05/05)
69
+ errors = wrapper.findAll('.v-messages__message--error')
70
+ expect(errors.length).toBe(0)
71
+
72
+ wrapper.unmount()
73
+ })
74
+
75
+ /**
76
+ * Test 2 : Validation réactive sans re-saisie
77
+ * Quand la règle change, la validation doit se mettre à jour automatiquement
78
+ */
79
+ it('re-valide automatiquement quand les règles changent', async () => {
80
+ const strictMode = ref(false)
81
+
82
+ const dynamicRules = computed(() => {
83
+ if (strictMode.value) {
84
+ return [{ type: 'notBeforeToday', options: { message: 'Date future obligatoire' } }]
85
+ }
86
+ return [] // Pas de validation en mode non-strict
87
+ })
88
+
89
+ const wrapper = mount(ComplexDatePicker, {
90
+ props: {
91
+ modelValue: '01/01/2020', // Date passée
92
+ label: 'Date',
93
+ format: 'DD/MM/YYYY',
94
+ customRules: dynamicRules.value,
95
+ },
96
+ })
97
+
98
+ // En mode non-strict, pas d'erreur
99
+ await flushPromises()
100
+ let errors = wrapper.findAll('.v-messages__message--error')
101
+ expect(errors.length).toBe(0)
102
+
103
+ // Passer en mode strict
104
+ strictMode.value = true
105
+ await wrapper.setProps({
106
+ customRules: [{ type: 'notBeforeToday', options: { message: 'Date future obligatoire' } }],
107
+ })
108
+ await nextTick()
109
+ await flushPromises()
110
+
111
+ // Maintenant doit y avoir une erreur (date passée en mode strict)
112
+ errors = wrapper.findAll('.v-messages__message--error')
113
+ expect(errors.length).toBeGreaterThan(0)
114
+
115
+ wrapper.unmount()
116
+ })
117
+
118
+ /**
119
+ * Test 3 : Pas de validation avec règles vides
120
+ */
121
+ it('ne valide pas quand customRules est vide', async () => {
122
+ const wrapper = mount(ComplexDatePicker, {
123
+ props: {
124
+ modelValue: '',
125
+ label: 'Date',
126
+ format: 'DD/MM/YYYY',
127
+ customRules: [], // Pas de règles
128
+ showSuccessMessages: true,
129
+ },
130
+ })
131
+
132
+ const input = wrapper.find('input')
133
+ await input.setValue('15/05/2025')
134
+ await input.trigger('blur')
135
+ await flushPromises()
136
+
137
+ // Pas de validation custom, donc validateSpy ne doit pas être appelé
138
+ // (mais le champ peut avoir un succès de validation de format)
139
+ const successMessages = wrapper.findAll('.v-messages__message--success')
140
+ // Un seul message maximum (pas de double validation)
141
+ expect(successMessages.length).toBeLessThanOrEqual(1)
142
+
143
+ wrapper.unmount()
144
+ })
145
+
146
+ /**
147
+ * Test 4 : Gestion des valeurs null (bug "Date invalide")
148
+ * Bug précédent : "Date invalide" s'affichait quand on supprimait la date
149
+ */
150
+ it('gère les valeurs null sans erreur "Date invalide"', async () => {
151
+ const wrapper = mount(ComplexDatePicker, {
152
+ props: {
153
+ modelValue: null,
154
+ label: 'Date',
155
+ format: 'DD/MM/YYYY',
156
+ customRules: [{ type: 'notBeforeDate', options: { date: '01/01/2025', message: 'Date trop ancienne' } }],
157
+ },
158
+ })
159
+
160
+ await flushPromises()
161
+
162
+ // Ne doit pas afficher "Date invalide" pour valeur null
163
+ const errors = wrapper.findAll('.v-messages__message--error')
164
+ const hasDateInvalide = errors.some(e => e.text().includes('Date invalide'))
165
+ expect(hasDateInvalide).toBe(false)
166
+
167
+ wrapper.unmount()
168
+ })
169
+
170
+ /**
171
+ * Test 5 : Pas d'erreur "Configuration invalide"
172
+ * Bug précédent : Message quand options.date = undefined
173
+ */
174
+ it('ne montre pas "Configuration de la règle invalide" quand la règle est valide', async () => {
175
+ const wrapper = mount(ComplexDatePicker, {
176
+ props: {
177
+ modelValue: '15/05/2025',
178
+ label: 'Date',
179
+ format: 'DD/MM/YYYY',
180
+ // Règle avec une date valide (pas undefined)
181
+ customRules: [{ type: 'notBeforeDate', options: { date: '01/01/2025', message: 'Date trop ancienne' } }],
182
+ },
183
+ })
184
+
185
+ await flushPromises()
186
+
187
+ // Ne doit pas avoir de message d'erreur de configuration
188
+ const errors = wrapper.findAll('.v-messages__message--error')
189
+ const hasConfigError = errors.some(e => e.text().includes('Configuration de la règle invalide'))
190
+ expect(hasConfigError).toBe(false)
191
+
192
+ wrapper.unmount()
193
+ })
194
+ })
@@ -0,0 +1,83 @@
1
+ import { mount, flushPromises } from '@vue/test-utils'
2
+ import { describe, it, expect } from 'vitest'
3
+ import ComplexDatePicker from '../ComplexDatePicker.vue'
4
+ import DateTextInput from '../../DateTextInput/DateTextInput.vue'
5
+
6
+ /**
7
+ * Tests de régression pour les messages de succès
8
+ * Bug précédent : Double affichage des messages de succès quand
9
+ * ComplexDatePicker et DateTextInput validaient tous les deux
10
+ */
11
+ describe('Validation Success Messages Regression', () => {
12
+ it('affiche un seul message de succès quand une date valide est saisie', async () => {
13
+ const wrapper = mount(ComplexDatePicker, {
14
+ props: {
15
+ modelValue: '',
16
+ label: 'Date de test',
17
+ format: 'DD/MM/YYYY',
18
+ showSuccessMessages: true,
19
+ required: true,
20
+ },
21
+ })
22
+
23
+ // Saisir une date valide
24
+ const input = wrapper.find('input')
25
+ await input.setValue('15/05/2025')
26
+ await input.trigger('blur')
27
+ await flushPromises()
28
+
29
+ // Vérifier qu'il n'y a qu'un seul message de succès
30
+ const successMessages = wrapper.findAll('.v-messages__message--success')
31
+ expect(successMessages.length).toBeLessThanOrEqual(1)
32
+
33
+ wrapper.unmount()
34
+ })
35
+
36
+ it('DateTextInput isolé affiche correctement les messages de succès', async () => {
37
+ const wrapper = mount(DateTextInput, {
38
+ props: {
39
+ modelValue: '',
40
+ label: 'Date isolée',
41
+ format: 'DD/MM/YYYY',
42
+ showSuccessMessages: true,
43
+ required: true,
44
+ },
45
+ })
46
+
47
+ const input = wrapper.find('input')
48
+ await input.setValue('20/06/2025')
49
+ await input.trigger('blur')
50
+ await flushPromises()
51
+
52
+ // Un seul message attendu
53
+ const successMessages = wrapper.findAll('.v-messages__message--success')
54
+ expect(successMessages.length).toBeLessThanOrEqual(1)
55
+
56
+ wrapper.unmount()
57
+ })
58
+
59
+ it('pas de double message avec skipInternalValidation', async () => {
60
+ const wrapper = mount(DateTextInput, {
61
+ props: {
62
+ modelValue: '',
63
+ label: 'Date avec skip',
64
+ format: 'DD/MM/YYYY',
65
+ showSuccessMessages: true,
66
+ required: true,
67
+ skipInternalValidation: true, // Simule utilisation dans ComplexDatePicker
68
+ },
69
+ })
70
+
71
+ const input = wrapper.find('input')
72
+ await input.setValue('10/07/2025')
73
+ await input.trigger('blur')
74
+ await flushPromises()
75
+
76
+ // Avec skipInternalValidation, pas de validation interne
77
+ // donc pas de message de succès généré par DateTextInput
78
+ const successMessages = wrapper.findAll('.v-messages__message--success')
79
+ expect(successMessages.length).toBe(0)
80
+
81
+ wrapper.unmount()
82
+ })
83
+ })