@cnamts/synapse 0.0.5-alpha → 0.0.7-alpha

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 (229) hide show
  1. package/dist/design-system-v3.d.ts +487 -415
  2. package/dist/design-system-v3.js +2954 -2203
  3. package/dist/design-system-v3.umd.cjs +6 -6
  4. package/dist/style.css +1 -1
  5. package/package.json +17 -17
  6. package/src/assets/settings.scss +3 -0
  7. package/src/assets/tokens.scss +16 -16
  8. package/src/components/BackBtn/AccessibiliteItems.ts +0 -30
  9. package/src/components/BackBtn/BackBtn.mdx +1 -1
  10. package/src/components/BackBtn/BackBtn.stories.ts +12 -9
  11. package/src/components/BackBtn/BackBtn.vue +0 -1
  12. package/src/components/BackToTopBtn/AccessibiliteItems.ts +0 -30
  13. package/src/components/BackToTopBtn/BackToTopBtn.mdx +1 -1
  14. package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +3 -3
  15. package/src/components/CollapsibleList/Accessibilite.stories.ts +4 -0
  16. package/src/components/CollapsibleList/AccessibiliteItems.ts +55 -62
  17. package/src/components/CollapsibleList/CollapsibleList.stories.ts +1 -1
  18. package/src/components/CookieBanner/Accessibilite.stories.ts +219 -0
  19. package/src/components/CookieBanner/AccessibiliteItems.ts +356 -0
  20. package/src/components/CookieBanner/CookieBanner.mdx +219 -0
  21. package/src/components/CookieBanner/CookieBanner.stories.ts +680 -0
  22. package/src/components/CookieBanner/CookieBanner.vue +225 -0
  23. package/src/components/CookieBanner/config.ts +38 -0
  24. package/src/components/CookieBanner/locales.ts +12 -0
  25. package/src/components/CookieBanner/tests/CookieBanner.spec.ts +129 -0
  26. package/src/components/CookieBanner/tests/__snapshots__/CookieBanner.spec.ts.snap +197 -0
  27. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +123 -0
  28. package/src/components/CookiesSelection/CookiesInformation/locales.ts +21 -0
  29. package/src/components/CookiesSelection/CookiesInformation/tests/CookiesInformation.spec.ts +121 -0
  30. package/src/components/CookiesSelection/CookiesSelection.vue +127 -0
  31. package/src/components/CookiesSelection/CookiesTable/CookiesTable.vue +47 -0
  32. package/src/components/CookiesSelection/CookiesTable/headers.ts +14 -0
  33. package/src/components/CookiesSelection/CookiesTable/tests/CookiesTable.spec.ts +30 -0
  34. package/src/components/CookiesSelection/CookiesTable/tests/__snapshots__/CookiesTable.spec.ts.snap +3 -0
  35. package/src/components/CookiesSelection/locales.ts +10 -0
  36. package/src/components/CookiesSelection/tests/CookiesSelection.spec.ts +184 -0
  37. package/src/components/CookiesSelection/tests/__snapshots__/CookiesSelection.spec.ts.snap +192 -0
  38. package/src/components/CookiesSelection/types.ts +15 -0
  39. package/src/components/CopyBtn/AccessibiliteItems.ts +0 -30
  40. package/src/components/CopyBtn/CopyBtn.mdx +1 -1
  41. package/src/components/CopyBtn/CopyBtn.stories.ts +9 -6
  42. package/src/components/CopyBtn/CopyBtn.vue +0 -1
  43. package/src/components/Customs/SyBtnSelect/Accessibilite.mdx +14 -0
  44. package/src/components/Customs/SyBtnSelect/Accessibilite.stories.ts +193 -0
  45. package/src/components/Customs/SyBtnSelect/AccessibiliteItems.ts +139 -0
  46. package/src/components/Customs/SyBtnSelect/SyBtnSelect.mdx +3 -2
  47. package/src/components/Customs/SyBtnSelect/SyBtnSelect.stories.ts +30 -14
  48. package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +21 -13
  49. package/src/components/Customs/SyBtnSelect/constants/ExpertiseLevelEnum.ts +4 -0
  50. package/src/components/Customs/SyInputSelect/Accessibilite.mdx +14 -0
  51. package/src/components/Customs/SyInputSelect/Accessibilite.stories.ts +166 -0
  52. package/src/components/Customs/SyInputSelect/AccessibiliteItems.ts +96 -0
  53. package/src/components/Customs/SyInputSelect/SyInputSelect.mdx +7 -3
  54. package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +24 -65
  55. package/src/components/Customs/SyInputSelect/SyInputSelect.vue +36 -4
  56. package/src/components/Customs/SyInputSelect/constants/ExpertiseLevelEnum.ts +4 -0
  57. package/src/components/Customs/SySelect/Accessibilite.mdx +14 -0
  58. package/src/components/Customs/SySelect/Accessibilite.stories.ts +217 -0
  59. package/src/components/Customs/SySelect/AccessibiliteItems.ts +173 -0
  60. package/src/components/Customs/SySelect/SySelect.mdx +4 -4
  61. package/src/components/Customs/SySelect/SySelect.stories.ts +4 -60
  62. package/src/components/Customs/SySelect/SySelect.vue +35 -8
  63. package/src/components/Customs/SySelect/constants/ExpertiseLevelEnum.ts +4 -0
  64. package/src/components/Customs/SyTextField/Accessibilite.mdx +14 -0
  65. package/src/components/Customs/SyTextField/Accessibilite.stories.ts +224 -0
  66. package/src/components/Customs/SyTextField/AccessibiliteItems.ts +198 -0
  67. package/src/components/Customs/SyTextField/SyTextField.mdx +1 -1
  68. package/src/components/Customs/SyTextField/SyTextField.stories.ts +118 -7
  69. package/src/components/Customs/SyTextField/SyTextField.vue +27 -7
  70. package/src/components/Customs/SyTextField/constants/ExpertiseLevelEnum.ts +4 -0
  71. package/src/components/Customs/SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap +2 -1
  72. package/src/components/DataList/Accessibilite.mdx +14 -0
  73. package/src/components/DataList/Accessibilite.stories.ts +166 -0
  74. package/src/components/DataList/AccessibiliteItems.ts +47 -0
  75. package/src/components/DataList/DataList.mdx +1 -1
  76. package/src/components/DataList/DataList.stories.ts +10 -10
  77. package/src/components/DataList/constants/ExpertiseLevelEnum.ts +4 -0
  78. package/src/components/DataListGroup/Accessibilite.mdx +14 -0
  79. package/src/components/DataListGroup/Accessibilite.stories.ts +225 -0
  80. package/src/components/DataListGroup/AccessibiliteItems.ts +79 -0
  81. package/src/components/DataListGroup/DataListGroup.mdx +1 -1
  82. package/src/components/DataListGroup/DataListGroup.stories.ts +7 -7
  83. package/src/components/DataListGroup/constants/ExpertiseLevelEnum.ts +4 -0
  84. package/src/components/DialogBox/Accessibilite.mdx +14 -0
  85. package/src/components/DialogBox/Accessibilite.stories.ts +189 -0
  86. package/src/components/DialogBox/AccessibiliteItems.ts +167 -0
  87. package/src/components/DialogBox/constants/ExpertiseLevelEnum.ts +4 -0
  88. package/src/components/DownloadBtn/AccessibiliteItems.ts +1 -31
  89. package/src/components/DownloadBtn/DownloadBtn.mdx +5 -6
  90. package/src/components/DownloadBtn/DownloadBtn.stories.ts +25 -26
  91. package/src/components/ErrorPage/Accessibilite.mdx +14 -0
  92. package/src/components/ErrorPage/Accessibilite.stories.ts +189 -0
  93. package/src/components/ErrorPage/AccessibiliteItems.ts +205 -0
  94. package/src/components/ErrorPage/ErrorPage.vue +1 -1
  95. package/src/components/ErrorPage/constants/ExpertiseLevelEnum.ts +4 -0
  96. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +4 -4
  97. package/src/components/FooterBar/Accessibilite.mdx +14 -0
  98. package/src/components/FooterBar/Accessibilite.stories.ts +223 -0
  99. package/src/components/FooterBar/AccessibiliteItems.ts +257 -0
  100. package/src/components/FooterBar/FooterBar.mdx +2 -2
  101. package/src/components/FooterBar/FooterBar.stories.ts +14 -14
  102. package/src/components/FooterBar/FooterBar.vue +86 -75
  103. package/src/components/FooterBar/constants/ExpertiseLevelEnum.ts +4 -0
  104. package/src/components/FooterBar/tests/__snapshots__/FooterBar.spec.ts.snap +22 -20
  105. package/src/components/FranceConnectBtn/AccessibiliteItems.ts +0 -30
  106. package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +1 -1
  107. package/src/components/FranceConnectBtn/FranceConnectBtn.stories.ts +5 -4
  108. package/src/components/HeaderBar/Accessibilite.mdx +14 -0
  109. package/src/components/HeaderBar/Accessibilite.stories.ts +223 -0
  110. package/src/components/HeaderBar/AccessibiliteItems.ts +194 -0
  111. package/src/components/HeaderBar/HeaderBar.stories.ts +19 -12
  112. package/src/components/HeaderBar/HeaderBar.vue +9 -12
  113. package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.mdx +14 -0
  114. package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.stories.ts +223 -0
  115. package/src/components/HeaderBar/HeaderBurgerMenu/AccessibiliteItems.ts +174 -0
  116. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +1 -0
  117. package/src/components/HeaderBar/HeaderBurgerMenu/constants/ExpertiseLevelEnum.ts +4 -0
  118. package/src/components/HeaderBar/constants/ExpertiseLevelEnum.ts +4 -0
  119. package/src/components/HeaderBar/tests/__snapshots__/HeaderBar.spec.ts.snap +1 -1
  120. package/src/components/HeaderLoading/Accessibilite.mdx +14 -0
  121. package/src/components/HeaderLoading/Accessibilite.stories.ts +167 -0
  122. package/src/components/HeaderLoading/AccessibiliteItems.ts +29 -0
  123. package/src/components/HeaderLoading/HeaderLoading.mdx +1 -1
  124. package/src/components/HeaderLoading/HeaderLoading.stories.ts +1 -1
  125. package/src/components/HeaderLoading/constants/ExpertiseLevelEnum.ts +4 -0
  126. package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +104 -32
  127. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +35 -33
  128. package/src/components/HeaderToolbar/Accessibilite.mdx +14 -0
  129. package/src/components/HeaderToolbar/Accessibilite.stories.ts +203 -0
  130. package/src/components/HeaderToolbar/AccessibiliteItems.ts +200 -0
  131. package/src/components/HeaderToolbar/HeaderToolbar.mdx +1 -1
  132. package/src/components/HeaderToolbar/HeaderToolbar.stories.ts +2 -2
  133. package/src/components/HeaderToolbar/HeaderToolbar.vue +24 -1
  134. package/src/components/HeaderToolbar/constants/ExpertiseLevelEnum.ts +4 -0
  135. package/src/components/LangBtn/Accessibilite.stories.ts +3 -1
  136. package/src/components/LangBtn/AccessibiliteItems.ts +0 -31
  137. package/src/components/LangBtn/LangBtn.mdx +1 -1
  138. package/src/components/LangBtn/LangBtn.stories.ts +4 -4
  139. package/src/components/LangBtn/LangBtn.vue +3 -2
  140. package/src/components/Logo/Accessibilite.mdx +14 -0
  141. package/src/components/Logo/Accessibilite.stories.ts +223 -0
  142. package/src/components/Logo/AccessibiliteItems.ts +155 -0
  143. package/src/components/Logo/Logo.mdx +1 -1
  144. package/src/components/Logo/Logo.stories.ts +8 -8
  145. package/src/components/Logo/constants/ExpertiseLevelEnum.ts +4 -0
  146. package/src/components/LogoBrandSection/Accessibilite.mdx +14 -0
  147. package/src/components/LogoBrandSection/Accessibilite.stories.ts +223 -0
  148. package/src/components/LogoBrandSection/AccessibiliteItems.ts +194 -0
  149. package/src/components/LogoBrandSection/constants/ExpertiseLevelEnum.ts +4 -0
  150. package/src/components/MaintenancePage/Accessibilite.mdx +14 -0
  151. package/src/components/MaintenancePage/Accessibilite.stories.ts +189 -0
  152. package/src/components/MaintenancePage/AccessibiliteItems.ts +173 -0
  153. package/src/components/MaintenancePage/constants/ExpertiseLevelEnum.ts +4 -0
  154. package/src/components/NirField/Accessibilite.mdx +14 -0
  155. package/src/components/NirField/Accessibilite.stories.ts +214 -0
  156. package/src/components/NirField/AccessibiliteItems.ts +243 -0
  157. package/src/components/NirField/NirField.mdx +213 -0
  158. package/src/components/NirField/NirField.stories.ts +412 -0
  159. package/src/components/NirField/NirField.vue +453 -0
  160. package/src/components/NirField/config.ts +16 -0
  161. package/src/components/NirField/constants/ExpertiseLevelEnum.ts +4 -0
  162. package/src/components/NirField/locales.ts +12 -0
  163. package/src/components/NirField/nirValidation.ts +42 -0
  164. package/src/components/NirField/tests/NirField.spec.ts +120 -0
  165. package/src/components/NotFoundPage/Accessibilite.mdx +14 -0
  166. package/src/components/NotFoundPage/Accessibilite.stories.ts +190 -0
  167. package/src/components/NotFoundPage/AccessibiliteItems.ts +205 -0
  168. package/src/components/NotFoundPage/constants/ExpertiseLevelEnum.ts +4 -0
  169. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +4 -4
  170. package/src/components/NotificationBar/AccessibiliteItems.ts +0 -30
  171. package/src/components/NotificationBar/NotificationBar.mdx +1 -1
  172. package/src/components/PageContainer/PageContainer.mdx +1 -1
  173. package/src/components/PageContainer/PageContainer.stories.ts +9 -9
  174. package/src/components/PageContainer/PageContainer.vue +24 -18
  175. package/src/components/PageContainer/tests/PageContainer.spec.ts +2 -2
  176. package/src/components/PageContainer/tests/__snapshots__/PageContainer.spec.ts.snap +2 -2
  177. package/src/components/PhoneField/Accessibilite.mdx +14 -0
  178. package/src/components/PhoneField/Accessibilite.stories.ts +216 -0
  179. package/src/components/PhoneField/AccessibiliteItems.ts +238 -0
  180. package/src/components/PhoneField/PhoneField.mdx +1 -1
  181. package/src/components/PhoneField/PhoneField.stories.ts +2 -2
  182. package/src/components/PhoneField/PhoneField.vue +0 -1
  183. package/src/components/PhoneField/constants/ExpertiseLevelEnum.ts +4 -0
  184. package/src/components/SkipLink/Accessibilite.stories.ts +1 -1
  185. package/src/components/SkipLink/SkipLink.stories.ts +2 -2
  186. package/src/components/SocialMediaLinks/Accessibilite.mdx +14 -0
  187. package/src/components/SocialMediaLinks/Accessibilite.stories.ts +170 -0
  188. package/src/components/SocialMediaLinks/AccessibiliteItems.ts +160 -0
  189. package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +1 -1
  190. package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +1 -1
  191. package/src/components/SocialMediaLinks/SocialMediaLinks.vue +7 -1
  192. package/src/components/SocialMediaLinks/constants/ExpertiseLevelEnum.ts +4 -0
  193. package/src/components/SocialMediaLinks/tests/__snapshots__/SocialMediaLinks.spec.ts.snap +2 -2
  194. package/src/components/SubHeader/Accessibilite.mdx +14 -0
  195. package/src/components/SubHeader/Accessibilite.stories.ts +166 -0
  196. package/src/components/SubHeader/AccessibiliteItems.ts +146 -0
  197. package/src/components/SubHeader/SubHeader.mdx +1 -1
  198. package/src/components/SubHeader/SubHeader.stories.ts +17 -14
  199. package/src/components/SubHeader/constants/ExpertiseLevelEnum.ts +4 -0
  200. package/src/components/SyAlert/Accessibilite.mdx +14 -0
  201. package/src/components/{Alert → SyAlert}/Accessibilite.stories.ts +1 -1
  202. package/src/components/{Alert → SyAlert}/AccessibiliteItems.ts +2 -32
  203. package/src/components/{Alert/Alert.mdx → SyAlert/SyAlert.mdx} +9 -9
  204. package/src/components/{Alert/Alert.stories.ts → SyAlert/SyAlert.stories.ts} +22 -22
  205. package/src/components/{Alert/Alert.vue → SyAlert/SyAlert.vue} +7 -0
  206. package/src/components/SyAlert/constants/ExpertiseLevelEnum.ts +4 -0
  207. package/src/components/{Alert/tests/Alert.spec.ts → SyAlert/tests/SyAlert.spec.ts} +5 -5
  208. package/src/components/{Alert/tests/__snapshots__/Alert.spec.ts.snap → SyAlert/tests/__snapshots__/SyAlert.spec.ts.snap} +2 -2
  209. package/src/components/UserMenuBtn/Accessibilite.mdx +14 -0
  210. package/src/components/UserMenuBtn/Accessibilite.stories.ts +189 -0
  211. package/src/components/UserMenuBtn/AccessibiliteItems.ts +155 -0
  212. package/src/components/UserMenuBtn/UserMenuBtn.mdx +17 -17
  213. package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +121 -19
  214. package/src/components/UserMenuBtn/UserMenuBtn.vue +25 -29
  215. package/src/components/UserMenuBtn/config.ts +1 -1
  216. package/src/components/UserMenuBtn/constants/ExpertiseLevelEnum.ts +4 -0
  217. package/src/components/index.ts +11 -4
  218. package/src/composables/rules/tests/useFieldValidation.spec.ts +60 -58
  219. package/src/composables/rules/useFieldValidation.ts +65 -28
  220. package/src/main.ts +1 -0
  221. package/src/stories/GuideDuDev/CommentUtiliserLesRules.mdx +67 -79
  222. package/src/stories/GuideDuDev/components.stories.ts +5 -5
  223. package/src/stories/GuideDuDev/moduleDeNotification.mdx +1 -1
  224. package/src/stories/Guidelines/Vuetify/Vuetify.mdx +11 -0
  225. package/src/stories/Guidelines/Vuetify/Vuetify.stories.ts +138 -0
  226. package/src/stories/Guidelines/Vuetify/VuetifyItems.ts +350 -0
  227. /package/src/components/{Alert → CookieBanner}/Accessibilite.mdx +0 -0
  228. /package/src/components/{Alert → CookieBanner}/constants/ExpertiseLevelEnum.ts +0 -0
  229. /package/src/components/{Alert → SyAlert}/locales.ts +0 -0
@@ -0,0 +1,123 @@
1
+ <script setup lang="ts">
2
+ import { required } from '@/utils/rules/required'
3
+ import { mdiChevronDown, mdiChevronUp } from '@mdi/js'
4
+ import { computed, ref } from 'vue'
5
+ import CookiesTable from '../CookiesTable/CookiesTable.vue'
6
+ import type { CookieTypes, Cookie } from '../types'
7
+ import { locales } from './locales'
8
+
9
+ defineProps<{
10
+ type: CookieTypes
11
+ tableItems: Cookie[]
12
+ }>()
13
+
14
+ const status = defineModel<boolean | undefined>()
15
+
16
+ const parsedValue = computed(() => {
17
+ if (status.value === true) {
18
+ return 'accept'
19
+ }
20
+ if (status.value === false) {
21
+ return 'reject'
22
+ }
23
+ return undefined
24
+ })
25
+
26
+ const open = ref(false)
27
+ function toggleDetails(event: ToggleEvent): void {
28
+ open.value = event.newState === 'open'
29
+ }
30
+ </script>
31
+
32
+ <template>
33
+ <div class="vd-cookies-information">
34
+ <h2 class="text-subtitle-1 font-weight-bold mb-2">
35
+ {{ locales[type].title }}
36
+ </h2>
37
+
38
+ <p class="mb-4">
39
+ {{ locales[type].description }}
40
+ </p>
41
+
42
+ <details @toggle="toggleDetails">
43
+ <summary class="mb-1">
44
+ {{ open ? locales.hideInformation : locales.showInformation }}
45
+
46
+ <VIcon
47
+ class="mr-2"
48
+ data-test="chevron"
49
+ >
50
+ {{ open ? mdiChevronUp : mdiChevronDown }}
51
+ </VIcon>
52
+ </summary>
53
+
54
+ <CookiesTable
55
+ :items="tableItems"
56
+ class="mb-2"
57
+ >
58
+ <template
59
+ v-for="(_, slotName) in $slots"
60
+ #[slotName]="slotProps"
61
+ >
62
+ <slot
63
+ :name="slotName"
64
+ v-bind="slotProps ?? {}"
65
+ />
66
+ </template>
67
+ </CookiesTable>
68
+ </details>
69
+
70
+ <VRadioGroup
71
+ v-if="type !== 'essentials'"
72
+ :model-value="parsedValue"
73
+ :rules="[required]"
74
+ data-test-id="radio-group"
75
+ inline
76
+ hide-details="auto"
77
+ class="vd-cookies-information__radio-group"
78
+ @update:model-value="status = $event === 'accept'"
79
+ >
80
+ <VSpacer />
81
+
82
+ <VRadio
83
+ :label="locales.reject"
84
+ :value="'reject'"
85
+ color="primary"
86
+ />
87
+
88
+ <VRadio
89
+ :label="locales.accept"
90
+ :value="'accept'"
91
+ class="mr-0"
92
+ color="primary"
93
+ />
94
+ </VRadioGroup>
95
+ </div>
96
+ </template>
97
+
98
+ <style lang="scss" scoped>
99
+ @use '@/assets/tokens.scss';
100
+
101
+ details > summary {
102
+ cursor: pointer;
103
+ list-style: none;
104
+ user-select: none;
105
+
106
+ &::marker,
107
+ &::-webkit-details-marker {
108
+ display: none;
109
+ }
110
+ }
111
+
112
+ .vd-cookies-information__radio-group {
113
+ margin-top: 0;
114
+
115
+ :deep(.v-input__details) {
116
+ padding: 0;
117
+ }
118
+
119
+ :deep(.v-messages) {
120
+ text-align: end;
121
+ }
122
+ }
123
+ </style>
@@ -0,0 +1,21 @@
1
+ export const locales = {
2
+ essentials: {
3
+ title: 'Cookies requis',
4
+ description:
5
+ 'Ces cookies sont indispensables au fonctionnement du site et ne peuvent être désactivés.',
6
+ },
7
+ functional: {
8
+ title: 'Cookies fonctionnels',
9
+ description:
10
+ 'Ces cookies sont utilisés pour capturer vos préférences sur notre site. Ils permettent de vous assurer un confort dans votre navigation.',
11
+ },
12
+ analytics: {
13
+ title: 'Cookies d’analyse',
14
+ description:
15
+ 'Ces cookies sont dédiés à l’amélioration de notre site en analysant votre expérience d’utilisation. Ils nous sont très utiles pour vous proposer un site de bonne qualité.',
16
+ },
17
+ showInformation: 'Afficher les cookies',
18
+ hideInformation: 'Masquer les cookies',
19
+ reject: 'Refuser',
20
+ accept: 'Accepter',
21
+ } as const
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+ import CookiesInformation from '../CookiesInformation.vue'
5
+ import { locales } from '../locales'
6
+
7
+ const cookies = [
8
+ {
9
+ name: 'session',
10
+ description: 'Sauvegarde la session pour rester connecté.',
11
+ conservation: '20 heures',
12
+ },
13
+ {
14
+ name: 'cookie_policy',
15
+ description: 'Sauvegarde les préférences de cookies.',
16
+ conservation: '1 an',
17
+ },
18
+ ]
19
+
20
+ describe('CookiesInformation', () => {
21
+ it('renders correctly', () => {
22
+ const wrapper = mount(CookiesInformation, {
23
+ global: {
24
+ plugins: [vuetify],
25
+ },
26
+ props: {
27
+ tableItems: cookies,
28
+ type: 'functional',
29
+ },
30
+ })
31
+
32
+ expect(wrapper.text()).toContain(locales.functional.title)
33
+ expect(wrapper.text()).toContain(cookies[0].name)
34
+ expect(wrapper.text()).toContain(cookies[1].name)
35
+ expect(wrapper.text()).toContain(cookies[0].description)
36
+ expect(wrapper.text()).toContain(cookies[1].description)
37
+ expect(wrapper.text()).toContain(cookies[0].conservation)
38
+ expect(wrapper.text()).toContain(cookies[1].conservation)
39
+ expect(wrapper.findAll('tr')).toHaveLength(3)
40
+ })
41
+
42
+ it('renders correctly without items', () => {
43
+ const wrapper = mount(CookiesInformation, {
44
+ global: {
45
+ plugins: [vuetify],
46
+ },
47
+ props: {
48
+ type: 'functional',
49
+ tableItems: [],
50
+ },
51
+ })
52
+
53
+ expect(wrapper.findAll('tr')).toHaveLength(1)
54
+ })
55
+
56
+ it('renders correctly when details is toggled', async () => {
57
+ const wrapper = mount(CookiesInformation, {
58
+ global: {
59
+ plugins: [vuetify],
60
+ },
61
+ propsData: {
62
+ tableItems: cookies,
63
+ type: 'functional',
64
+ },
65
+ })
66
+
67
+ expect(wrapper.find('thead').isVisible()).toBe(false)
68
+ const details = wrapper.find('details')
69
+ const chevronClosed = wrapper.find('[data-test="chevron"]').html()
70
+ expect(chevronClosed).toMatchInlineSnapshot(`"<i data-v-2ca04413="" class="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z mdi v-icon notranslate v-theme--light v-icon--size-default mr-2" aria-hidden="true" data-test="chevron"></i>"`)
71
+
72
+ details.element.open = true
73
+ await details.trigger('toggle', { newState: 'open' })
74
+
75
+ expect(wrapper.find('thead').isVisible()).toBe(true)
76
+ const chevronOpen = wrapper.find('[data-test="chevron"]').html()
77
+ expect(chevronOpen).not.toEqual(chevronClosed)
78
+ expect(chevronOpen).toMatchInlineSnapshot(`"<i data-v-2ca04413="" class="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z mdi v-icon notranslate v-theme--light v-icon--size-default mr-2" aria-hidden="true" data-test="chevron"></i>"`)
79
+ })
80
+
81
+ it('update the radio when the modelValue change', async () => {
82
+ const wrapper = mount(CookiesInformation, {
83
+ global: {
84
+ plugins: [vuetify],
85
+ },
86
+ props: {
87
+ tableItems: cookies,
88
+ type: 'functional',
89
+ modelValue: true,
90
+ },
91
+ })
92
+
93
+ const radios = wrapper.findAll<HTMLInputElement>('input[type="radio"]')
94
+
95
+ expect(radios[0].element.checked).toBe(false)
96
+ expect(radios[1].element.checked).toBe(true)
97
+
98
+ await wrapper.setProps({ modelValue: false })
99
+
100
+ expect(radios[0].element.checked).toBe(true)
101
+ expect(radios[1].element.checked).toBe(false)
102
+ })
103
+
104
+ it('do not set the radio when the modelValue is undefined', async () => {
105
+ const wrapper = mount(CookiesInformation, {
106
+ global: {
107
+ plugins: [vuetify],
108
+ },
109
+ props: {
110
+ tableItems: cookies,
111
+ type: 'functional',
112
+ modelValue: undefined,
113
+ },
114
+ })
115
+
116
+ const radios = wrapper.findAll<HTMLInputElement>('input[type="radio"]')
117
+
118
+ expect(radios[0].element.checked).toBe(false)
119
+ expect(radios[1].element.checked).toBe(false)
120
+ })
121
+ })
@@ -0,0 +1,127 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue'
3
+ import type { VForm } from 'vuetify/components'
4
+ import CookiesInformation from './CookiesInformation/CookiesInformation.vue'
5
+ import { locales } from './locales'
6
+ import type { CookieTypes, CookiesItems, Preferences } from './types'
7
+
8
+ const props = defineProps<{
9
+ items: CookiesItems
10
+ }>()
11
+
12
+ const emits = defineEmits<{
13
+ submit: [preferences: Partial<Preferences>]
14
+ }>()
15
+
16
+ const form = ref<VForm | null>(null)
17
+
18
+ const preferences = ref<Preferences>({
19
+ essentials: undefined,
20
+ functional: undefined,
21
+ analytics: undefined,
22
+ })
23
+
24
+ const filteredPreferences = computed(() => {
25
+ const filtered: Partial<Preferences> = {}
26
+
27
+ Object.entries(preferences.value).forEach(([key, value]) => {
28
+ if (key != 'essentials' && props.items[key as CookieTypes]) {
29
+ filtered[key as CookieTypes] = value
30
+ }
31
+ })
32
+
33
+ return filtered
34
+ })
35
+
36
+ function setGlobalPreferences(value: boolean): void {
37
+ preferences.value['functional'] = value
38
+ preferences.value['analytics'] = value
39
+ }
40
+
41
+ async function submitForm(): Promise<void> {
42
+ const { valid } = await form.value!.validate()
43
+
44
+ if (!valid) {
45
+ return
46
+ }
47
+
48
+ emits('submit', filteredPreferences.value)
49
+ }
50
+ </script>
51
+
52
+ <template>
53
+ <VCard
54
+ v-if="items"
55
+ elevation="0"
56
+ color="transparent"
57
+ class="vd-cookies-card"
58
+ >
59
+ <VForm ref="form">
60
+ <p class="mb-4">
61
+ {{ locales.description }}
62
+ </p>
63
+
64
+ <p class="mb-4">
65
+ {{ locales.cookieDefinition }}
66
+ </p>
67
+
68
+ <div class="d-flex flex-wrap justify-end mx-n2 mt-n2 mb-6">
69
+ <VBtn
70
+ data-test-id="reject-all"
71
+ color="primary"
72
+ variant="outlined"
73
+ class="ma-2"
74
+ @click="setGlobalPreferences(false)"
75
+ >
76
+ {{ locales.rejectAll }}
77
+ </VBtn>
78
+
79
+ <VBtn
80
+ data-test-id="accept-all"
81
+ color="primary"
82
+ variant="outlined"
83
+ class="ma-2"
84
+ @click="setGlobalPreferences(true)"
85
+ >
86
+ {{ locales.acceptAll }}
87
+ </VBtn>
88
+ </div>
89
+
90
+ <template
91
+ v-for="(cookies, cookieType) in items"
92
+ :key="cookieType"
93
+ >
94
+ <CookiesInformation
95
+ v-if="cookies"
96
+ v-model="preferences[cookieType]"
97
+ :type="cookieType"
98
+ :table-items="cookies"
99
+ class="mb-6"
100
+ >
101
+ <template
102
+ v-for="(_, slotName) in $slots"
103
+ #[slotName]="slotProps"
104
+ >
105
+ <slot
106
+ v-if="String(slotName).startsWith('cookie-description')"
107
+ :name="slotName"
108
+ v-bind="slotProps ?? {}"
109
+ />
110
+ </template>
111
+ </CookiesInformation>
112
+ </template>
113
+
114
+ <div class="d-flex mt-16">
115
+ <VSpacer />
116
+
117
+ <VBtn
118
+ data-test-id="submit"
119
+ color="primary"
120
+ @click="submitForm"
121
+ >
122
+ {{ locales.saveBtn }}
123
+ </VBtn>
124
+ </div>
125
+ </VForm>
126
+ </VCard>
127
+ </template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ import type { Cookie } from '../types'
3
+ import { headers } from './headers'
4
+
5
+ defineProps<{ items: Cookie[] }>()
6
+ </script>
7
+
8
+ <template>
9
+ <VTable class="vd-cookie-table bg-transparent">
10
+ <thead>
11
+ <tr>
12
+ <th
13
+ v-for="(item, index) in headers"
14
+ :key="index"
15
+ :style="{ width: item.width }"
16
+ class="text-left"
17
+ >
18
+ {{ item.label }}
19
+ </th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <tr
25
+ v-for="cookie in items"
26
+ :key="cookie.name"
27
+ >
28
+ <td>{{ cookie.name }}</td>
29
+ <td>
30
+ <slot
31
+ :name="'cookie-description-' + cookie.name"
32
+ :cookie
33
+ >
34
+ {{ cookie.description }}
35
+ </slot>
36
+ </td>
37
+ <td>{{ cookie.conservation }}</td>
38
+ </tr>
39
+ </tbody>
40
+ </VTable>
41
+ </template>
42
+
43
+ <style lang="scss" scoped>
44
+ .vd-cookie-table :deep(table) {
45
+ table-layout: fixed;
46
+ }
47
+ </style>
@@ -0,0 +1,14 @@
1
+ export const headers = [
2
+ {
3
+ label: 'Dénomination du cookie',
4
+ width: '180px',
5
+ },
6
+ {
7
+ label: 'Finalité',
8
+ width: '328px',
9
+ },
10
+ {
11
+ label: 'Durée de conservation',
12
+ width: '180px',
13
+ },
14
+ ] as const
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { shallowMount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+ import CookiesTable from '../CookiesTable.vue'
5
+
6
+ describe('CookiesTable', () => {
7
+ it('renders correctly', () => {
8
+ const wrapper = shallowMount(CookiesTable, {
9
+ global: {
10
+ plugins: [vuetify],
11
+ },
12
+ propsData: {
13
+ items: [
14
+ {
15
+ name: 'session',
16
+ description: 'Sauvegarde la session pour rester connecté.',
17
+ conservation: '20 heures',
18
+ },
19
+ {
20
+ name: 'cookie_policy',
21
+ description: 'Sauvegarde les préférences de cookies.',
22
+ conservation: '1 an',
23
+ },
24
+ ],
25
+ },
26
+ })
27
+
28
+ expect(wrapper.html()).toMatchSnapshot()
29
+ })
30
+ })
@@ -0,0 +1,3 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`CookiesTable > renders correctly 1`] = `"<v-table-stub data-v-d0e8c396="" class="vd-cookie-table bg-transparent" fixedheader="false" fixedfooter="false" hover="false" density="default" tag="div"></v-table-stub>"`;
@@ -0,0 +1,10 @@
1
+ export const locales = {
2
+ title: 'Gestion des cookies',
3
+ description:
4
+ 'Définissez vos préférences de collecte et de traitement de vos données sur ce site.',
5
+ cookieDefinition:
6
+ 'Un cookie est un petit fichier texte déposé sur votre terminal (ordinateur, tablette ou mobile) lors de la visite d’un site ou lors de la consultation d’une publicité. Il contient plusieurs données\xa0: le nom du service qui l’a déposé, un identifiant sous forme de numéro unique, une valeur et éventuellement une date d’expiration.',
7
+ rejectAll: 'Tout refuser',
8
+ acceptAll: 'Tout accepter',
9
+ saveBtn: 'Enregistrer mes choix',
10
+ }
@@ -0,0 +1,184 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+ import CookiesSelection from '../CookiesSelection.vue'
5
+
6
+ const cookiesList = {
7
+ essentials: [
8
+ {
9
+ name: 'session',
10
+ description: 'Sauvegarde la session pour rester connecté.',
11
+ conservation: '20 heures',
12
+ },
13
+ {
14
+ name: 'cookie_policy',
15
+ description: 'Sauvegarde les préférences de cookies.',
16
+ conservation: '1 an',
17
+ },
18
+ ],
19
+ functional: [
20
+ {
21
+ name: 'contrast',
22
+ description: 'Sauvegarde la personnalisation de l’affichage.',
23
+ conservation: '1 an',
24
+ },
25
+ ],
26
+ analytics: [
27
+ {
28
+ name: 'user_id',
29
+ description: 'Sauvegarde l’identifiant unique de visiteur.',
30
+ conservation: '6 mois',
31
+ },
32
+ ],
33
+ }
34
+
35
+ describe('CookiesSelection', () => {
36
+ it('renders correctly', () => {
37
+ const wrapper = mount(CookiesSelection, {
38
+ global: {
39
+ plugins: [vuetify],
40
+ },
41
+ propsData: {
42
+ items: cookiesList,
43
+ },
44
+ })
45
+
46
+ expect(wrapper.html()).toMatchSnapshot()
47
+ const cookiesSections = wrapper.findAll('.vd-cookies-information')
48
+ expect(cookiesSections[0].text()).toContain(cookiesList.essentials[0].name)
49
+ expect(cookiesSections[1].text()).toContain(cookiesList.functional[0].name)
50
+ expect(cookiesSections[2].text()).toContain(cookiesList.analytics[0].name)
51
+ })
52
+
53
+ it('sets global preferences', async () => {
54
+ const wrapper = mount(CookiesSelection, {
55
+ global: {
56
+ plugins: [vuetify],
57
+ },
58
+ props: {
59
+ items: cookiesList,
60
+ },
61
+ })
62
+
63
+ await wrapper.find('[data-test-id="reject-all"]').trigger('click')
64
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
65
+ await wrapper.vm.$nextTick()
66
+ await wrapper.vm.$nextTick()
67
+
68
+ expect(wrapper.emitted()).toHaveProperty('submit')
69
+ expect(wrapper.emitted('submit')?.[0]?.[0]).toStrictEqual({
70
+ functional: false,
71
+ analytics: false,
72
+ })
73
+
74
+ await wrapper.find('[data-test-id="accept-all"]').trigger('click')
75
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
76
+ await wrapper.vm.$nextTick()
77
+ await wrapper.vm.$nextTick()
78
+
79
+ expect(wrapper.emitted('submit')?.[1]?.[0]).toStrictEqual({
80
+ functional: true,
81
+ analytics: true,
82
+ })
83
+ })
84
+
85
+ it('sets preferences for each category', async () => {
86
+ const wrapper = mount(CookiesSelection, {
87
+ global: {
88
+ plugins: [vuetify],
89
+ },
90
+ props: {
91
+ items: cookiesList,
92
+ },
93
+ })
94
+
95
+ const radioGroup = wrapper.findAll('[data-test-id="radio-group"]')
96
+
97
+ const functionalReject = radioGroup[0].find('input[value="reject"]')
98
+ const functionalAccept = radioGroup[0].find('input[value="accept"]')
99
+ const analyticsReject = radioGroup[1].find('input[value="reject"]')
100
+ const analyticsAccept = radioGroup[1].find('input[value="accept"]')
101
+
102
+ await functionalReject.setValue(true)
103
+ await analyticsAccept.setValue(true)
104
+
105
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
106
+ await wrapper.vm.$nextTick()
107
+ await wrapper.vm.$nextTick()
108
+
109
+ expect(wrapper.emitted()).toHaveProperty('submit')
110
+ expect(wrapper.emitted('submit')?.[0]?.[0]).toStrictEqual({
111
+ functional: false,
112
+ analytics: true,
113
+ })
114
+
115
+ await functionalAccept.setValue(true)
116
+ await analyticsReject.setValue(true)
117
+
118
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
119
+ await wrapper.vm.$nextTick()
120
+ await wrapper.vm.$nextTick()
121
+
122
+ expect(wrapper.emitted('submit')?.[1]?.[0]).toStrictEqual({
123
+ functional: true,
124
+ analytics: false,
125
+ })
126
+ })
127
+
128
+ it('requires all categories to be set', async () => {
129
+ const wrapper = mount(CookiesSelection, {
130
+ global: {
131
+ plugins: [vuetify],
132
+ },
133
+ props: {
134
+ items: cookiesList,
135
+ modelValue: undefined,
136
+ },
137
+ })
138
+
139
+ const radioGroup = wrapper.findAll('[data-test-id="radio-group"]')
140
+
141
+ const functionalReject = radioGroup[0].find('input[value="reject"]')
142
+ const functionalAccept = radioGroup[0].find('input[value="accept"]')
143
+ const analyticsReject = radioGroup[1].find('input[value="reject"]')
144
+
145
+ await functionalReject.setValue(true)
146
+
147
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
148
+ await wrapper.vm.$nextTick()
149
+ await wrapper.vm.$nextTick()
150
+
151
+ expect(wrapper.emitted()).not.toHaveProperty('submit')
152
+ expect(wrapper.text()).toContain('Le champ est requis.')
153
+
154
+ await functionalAccept.setValue(true)
155
+ await analyticsReject.setValue(true)
156
+
157
+ await wrapper.find('[data-test-id="submit"]').trigger('click')
158
+ await wrapper.vm.$nextTick()
159
+ await wrapper.vm.$nextTick()
160
+
161
+ expect(wrapper.emitted()).toHaveProperty('submit')
162
+ expect(wrapper.text()).not.toContain('Le champ est requis.')
163
+ })
164
+
165
+ it('displays the cookie description as a scoped slot', () => {
166
+ const wrapper = mount(CookiesSelection, {
167
+ global: {
168
+ plugins: [vuetify],
169
+ },
170
+ props: {
171
+ items: cookiesList,
172
+ },
173
+ slots: {
174
+ 'cookie-description-contrast': `
175
+ <template #cookie-description-contrast="{ cookie }">
176
+ <a href="#" class="contrast-description">{{ cookie.description }}</a>
177
+ </template>
178
+ `,
179
+ },
180
+ })
181
+
182
+ expect(wrapper.find('a.contrast-description').text()).toContain(cookiesList.functional[0].description)
183
+ })
184
+ })