@cnamts/synapse 1.0.6 → 1.0.8
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-BlOpwEVq.js → DateFilter-DkqG0pmr.js} +1 -1
- package/dist/{NumberFilter-BPUXE4wY.js → NumberFilter-Ck7AwD39.js} +1 -1
- package/dist/{PeriodFilter-B2yx329_.js → PeriodFilter-LRI6YpgU.js} +1 -1
- package/dist/{SelectFilter-CedKn1oV.js → SelectFilter-DPc70Jk7.js} +1 -1
- package/dist/{TextFilter-DkhJjRtR.js → TextFilter-DRQL7uD8.js} +1 -1
- package/dist/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.d.ts +116 -0
- package/dist/components/Amelipro/AmeliproAccordionGroup/types.d.ts +4 -0
- package/dist/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.d.ts +220 -0
- package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.d.ts +68 -0
- package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.d.ts +70 -0
- package/dist/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.d.ts +204 -0
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +26 -26
- package/dist/components/Amelipro/AmeliproBadge/AmeliproBadge.d.ts +59 -0
- package/dist/components/Amelipro/AmeliproBtn/AmeliproBtn.d.ts +3 -3
- package/dist/components/Amelipro/AmeliproCaptcha/AmeliproCaptcha.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproCarousel/AmeliproCarousel.d.ts +214 -0
- package/dist/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/AmeliproCarouselItem.d.ts +70 -0
- package/dist/components/Amelipro/AmeliproCarousel/types.d.ts +7 -0
- package/dist/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.d.ts +125 -0
- package/dist/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproIllustratedDataTile/AmeliproIllustratedDataTile.d.ts +2 -2
- package/dist/components/Amelipro/AmeliproResultList/AmeliproResultList.d.ts +164 -0
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +27 -27
- package/dist/components/Amelipro/AmeliproStateTile/AmeliproStateTile.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTable/AmeliproTable.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +32 -32
- package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +6 -6
- package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTooltips/AmeliproTooltips.d.ts +2 -2
- package/dist/components/ChipList/ChipList.d.ts +4 -0
- package/dist/components/ChipList/locales.d.ts +4 -2
- package/dist/components/CookiesSelection/CookiesInformation/CookiesInformation.d.ts +8 -8
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +329 -1296
- package/dist/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.d.ts +0 -1
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +2 -0
- package/dist/components/Customs/SyTabs/SyTabs.d.ts +71 -0
- package/dist/components/Customs/SyTabs/config.d.ts +17 -0
- package/dist/components/Customs/SyTabs/types.d.ts +11 -0
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +9 -9
- package/dist/components/DataList/DataList.d.ts +1 -1
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +4811 -240
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +52 -33
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +23 -10
- package/dist/components/DatePicker/composables/useDateInputEditing.d.ts +1 -0
- package/dist/components/DatePicker/composables/useTodayButton.d.ts +1 -0
- package/dist/components/DialogBox/DialogBox.d.ts +219 -0
- package/dist/components/HeaderLoading/HeaderLoading.d.ts +27 -0
- package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +110 -3
- package/dist/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.d.ts +19 -1
- package/dist/components/LangBtn/LangBtn.d.ts +2 -2
- package/dist/components/NirField/NirField.d.ts +18 -18
- package/dist/components/PeriodField/PeriodField.d.ts +10766 -1620
- package/dist/components/PhoneField/PhoneField.d.ts +1866 -2
- package/dist/components/PhoneField/indicatifs.d.ts +1 -0
- package/dist/components/PhoneField/locales.d.ts +1 -0
- package/dist/components/RangeField/RangeField.d.ts +1 -1
- package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +1 -1
- package/dist/components/SubHeader/SubHeader.d.ts +8 -0
- package/dist/components/SubHeader/locales.d.ts +1 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +6 -6
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -4
- package/dist/components/Tables/SyTable/SyTable.d.ts +5 -4
- package/dist/components/Tables/common/SyTablePagination.d.ts +333 -1296
- package/dist/components/Tables/common/organizeColumns/OrganizeColumns.d.ts +2 -2
- package/dist/components/Tables/common/types.d.ts +2 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/design-system-v3.js +173 -164
- package/dist/design-system-v3.umd.cjs +286 -263
- package/dist/{main-BXPFSAB4.js → main-DXMoMtj5.js} +13176 -11457
- package/dist/services/NotificationService.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/assets/amelipro/icons.ts +38 -11
- package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.mdx +20 -0
- package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.stories.ts +135 -0
- package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.vue +107 -0
- package/src/components/Amelipro/AmeliproAccordionGroup/__tests__/AmeliproAccordionGroup.spec.ts +37 -0
- package/src/components/Amelipro/AmeliproAccordionGroup/__tests__/__snapshots__/AmeliproAccordionGroup.spec.ts.snap +513 -0
- package/src/components/Amelipro/AmeliproAccordionGroup/types.d.ts +4 -0
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.mdx +16 -0
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.stories.ts +300 -0
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +288 -0
- package/src/components/Amelipro/AmeliproAccordionList/__tests__/AmeliproAccordionList.spec.ts +38 -0
- package/src/components/Amelipro/AmeliproAccordionList/__tests__/__snapshots__/AmeliproAccordionList.spec.ts.snap +1712 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.mdx +19 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.stories.ts +68 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.vue +66 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.vue +145 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/__tests__/AmeliproAccordionResultTemplate.spec.ts +24 -0
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/__tests__/__snapshots__/AmeliproAccordionResultTemplate.spec.ts.snap +127 -0
- package/src/components/Amelipro/AmeliproAccordionResult/__tests__/AmeliproAccordionResult.spec.ts +24 -0
- package/src/components/Amelipro/AmeliproAccordionResult/__tests__/__snapshots__/AmeliproAccordionResult.spec.ts.snap +123 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.mdx +20 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.stories.ts +273 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +275 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/__tests__/AmeliproAccordionResultList.spec.ts +38 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/__tests__/__snapshots__/AmeliproAccordionResultList.spec.ts.snap +1593 -0
- package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.mdx +15 -0
- package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.stories.ts +54 -0
- package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.vue +76 -0
- package/src/components/Amelipro/AmeliproBadge/__tests__/AmeliproBadge.spec.ts +20 -0
- package/src/components/Amelipro/AmeliproBadge/__tests__/__snapshots__/AmeliproBadge.spec.ts.snap +19 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.mdx +15 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.stories.ts +191 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.vue +263 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/AmeliproCarouselItem.vue +93 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/__tests__/AmeliproCarouselItem.spec.ts +24 -0
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/__tests__/__snapshots__/AmeliproCarouselItem.spec.ts.snap +43 -0
- package/src/components/Amelipro/AmeliproCarousel/__tests__/AmeliproCarousel.spec.ts +40 -0
- package/src/components/Amelipro/AmeliproCarousel/__tests__/__snapshots__/AmeliproCarousel.spec.ts.snap +342 -0
- package/src/components/Amelipro/AmeliproCarousel/types.d.ts +8 -0
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.mdx +18 -0
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.stories.ts +67 -0
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.vue +233 -0
- package/src/components/Amelipro/AmeliproClickableTile/tests/AmeliproClickableTile.spec.ts +21 -0
- package/src/components/Amelipro/AmeliproClickableTile/tests/__snapshots__/AmeliproClickableTile.spec.ts.snap +140 -0
- package/src/components/Amelipro/AmeliproHeader/AmeliproHeader.vue +7 -1
- package/src/components/Amelipro/AmeliproHeader/tests/__snapshots__/AmeliproHeader.spec.ts.snap +5 -4
- package/src/components/Amelipro/AmeliproIcon/iconList.ts +6 -0
- package/src/components/Amelipro/AmeliproPageLayout/tests/__snapshots__/AmeliproPageLayout.spec.ts.snap +5 -4
- package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.mdx +15 -0
- package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.stories.ts +264 -0
- package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.vue +231 -0
- package/src/components/Amelipro/AmeliproResultList/__tests__/AmeliproResultList.spec.ts +37 -0
- package/src/components/Amelipro/AmeliproResultList/__tests__/__snapshots__/AmeliproResultList.spec.ts.snap +434 -0
- package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +6 -5
- package/src/components/Amelipro/AmeliproTable/__tests__/__snapshots__/AmeliproTable.spec.ts.snap +23 -26
- package/src/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.stories.ts +2 -2
- package/src/components/ChipList/Accessibilite.stories.ts +4 -0
- package/src/components/ChipList/ChipList.vue +185 -42
- package/src/components/ChipList/locales.ts +4 -2
- package/src/components/ChipList/tests/chipList.spec.ts +7 -4
- package/src/components/Customs/Selects/SelectOverview.mdx +34 -66
- package/src/components/Customs/Selects/SyBtnSelect/SyBtnSelect.stories.ts +10 -10
- package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.mdx +3 -0
- package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.stories.ts +14 -0
- package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +14 -6
- package/src/components/Customs/Selects/SySelect/SySelect.vue +268 -205
- package/src/components/Customs/Selects/SySelect/composables/tests/useSySelectKeyboard.spec.ts +0 -10
- package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +0 -5
- package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +184 -25
- package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +3 -1
- package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +165 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +28 -9
- package/src/components/Customs/SyTabs/Accessibilite.mdx +309 -0
- package/src/components/Customs/SyTabs/SyTabs.mdx +117 -0
- package/src/components/Customs/SyTabs/SyTabs.stories.ts +354 -0
- package/src/components/Customs/SyTabs/SyTabs.vue +413 -0
- package/src/components/Customs/SyTabs/config.ts +17 -0
- package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +425 -0
- package/src/components/Customs/SyTabs/types.ts +12 -0
- package/src/components/Customs/SyTextField/SyTextField.mdx +3 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +142 -1
- package/src/components/Customs/SyTextField/SyTextField.vue +19 -16
- package/src/components/DataList/DataList.vue +47 -49
- package/src/components/DataListGroup/DataListGroup.vue +1 -1
- package/src/components/DataListItem/DataListItem.vue +67 -63
- package/src/components/DataListItem/tests/DataListItem.spec.ts +2 -2
- package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +3 -3
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +49 -13
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +412 -649
- package/src/components/DatePicker/DatePickerValidationExample/CalendarMode.stories.ts +215 -0
- package/src/components/DatePicker/DatePickerValidationExample/ComplexDatePicker.stories.ts +218 -0
- package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.mdx +2 -0
- package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +1 -1
- package/src/components/DatePicker/DatePickerValidationExample/DateTextInput.stories.ts +218 -0
- package/src/components/DatePicker/DatePickerValidationExample/MultiMode.stories.ts +281 -0
- package/src/components/DatePicker/DateTextInput/DateTextInput.events.spec.ts +17 -4
- package/src/components/DatePicker/DateTextInput/DateTextInput.range.spec.ts +111 -18
- package/src/components/DatePicker/DateTextInput/DateTextInput.spec.ts +238 -6
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +716 -757
- package/src/components/DatePicker/composables/tests/useDateInputEditing.spec.ts +4 -4
- package/src/components/DatePicker/composables/tests/useDisplayedDateString.spec.ts +17 -10
- package/src/components/DatePicker/composables/useDateInputEditing.ts +52 -22
- package/src/components/DatePicker/composables/useDisplayedDateString.ts +18 -4
- package/src/components/DatePicker/composables/useTodayButton.ts +13 -1
- package/src/components/DatePicker/utils/dateFormattingUtils.ts +79 -14
- package/src/components/DialogBox/DialogBox.stories.ts +12 -0
- package/src/components/DialogBox/DialogBox.vue +16 -11
- package/src/components/DialogBox/tests/DialogBox.spec.ts +22 -0
- package/src/components/HeaderLoading/Accessibilite.mdx +429 -8
- package/src/components/HeaderLoading/Accessibilite.stories.ts +4 -0
- package/src/components/HeaderLoading/HeaderLoading.vue +59 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +17 -2
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +91 -2
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +37 -1
- package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +284 -21
- package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +2 -2
- package/src/components/NirField/NirField.mdx +3 -0
- package/src/components/NirField/NirField.vue +10 -1
- package/src/components/NirField/tests/NirField.spec.ts +81 -0
- package/src/components/NotificationBar/NotificationBar.stories.ts +128 -2
- package/src/components/NotificationBar/NotificationBar.vue +16 -1
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +65 -0
- package/src/components/PasswordField/PasswordField.mdx +3 -0
- package/src/components/PeriodField/PeriodField.mdx +2 -0
- package/src/components/PeriodField/PeriodField.stories.ts +195 -0
- package/src/components/PhoneField/Accessibilite.stories.ts +4 -0
- package/src/components/PhoneField/PhoneField.mdx +3 -1
- package/src/components/PhoneField/PhoneField.stories.ts +285 -1
- package/src/components/PhoneField/PhoneField.vue +228 -95
- package/src/components/PhoneField/indicatifs.ts +102 -102
- package/src/components/PhoneField/locales.ts +1 -0
- package/src/components/PhoneField/tests/PhoneField.spec.ts +419 -2
- package/src/components/SkipLink/SkipLink.vue +3 -31
- package/src/components/SkipLink/tests/skipLink.spec.ts +0 -21
- package/src/components/SubHeader/Accessibilite.stories.ts +8 -0
- package/src/components/SubHeader/SubHeader.mdx +1 -0
- package/src/components/SubHeader/SubHeader.stories.ts +179 -60
- package/src/components/SubHeader/SubHeader.vue +45 -15
- package/src/components/SubHeader/locales.ts +1 -0
- package/src/components/SyAlert/SyAlert.vue +6 -0
- package/src/components/Tables/SyServerTable/SyServerTable.mdx +3 -10
- package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +242 -0
- package/src/components/Tables/SyServerTable/SyServerTable.vue +29 -10
- package/src/components/Tables/SyTable/SyTable.mdx +3 -10
- package/src/components/Tables/SyTable/SyTable.stories.ts +242 -0
- package/src/components/Tables/SyTable/SyTable.vue +2 -0
- package/src/components/Tables/common/SyTablePagination.vue +13 -6
- package/src/components/Tables/common/filters/tests/SelectFilter.spec.ts +6 -1
- package/src/components/Tables/common/tests/SyTablePagination.spec.ts +157 -0
- package/src/components/Tables/common/types.ts +2 -0
- package/src/components/index.ts +9 -0
- package/src/composables/useFilterable/useFilterable.ts +10 -0
- package/src/designTokens/tokens/amelipro/apColors.ts +1 -1
- package/src/designTokens/tokens/cnam/cnamSemantic.ts +3 -3
- package/src/services/NotificationService.ts +9 -0
- package/src/stories/Components/Components.stories.ts +1 -1
- package/src/stories/GuideDuDev/FormValidationGuide.mdx +342 -0
- package/src/stories/Templates/Templates.stories.ts +1 -1
- package/src/utils/functions/ameliproColors/ameliproColors.ts +1 -1
- package/dist/components/DataList/locales.d.ts +0 -3
- package/src/components/DataList/locales.ts +0 -3
- package/src/components/PhoneField/tests/PhoneField.additional.spec.ts +0 -266
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { Meta, Source } from '@storybook/addon-docs/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Guide Du Dev/Guide de Validation des Formulaires"/>
|
|
4
|
+
|
|
5
|
+
# Guide de Validation des Formulaires
|
|
6
|
+
|
|
7
|
+
Ce guide pratique explique comment utiliser le système de validation des formulaires du Design System dans vos applications.
|
|
8
|
+
|
|
9
|
+
## Les bases de la validation
|
|
10
|
+
|
|
11
|
+
Le système de validation offre un mécanisme complet et intuitif pour valider les entrées utilisateur avec trois niveaux de retour :
|
|
12
|
+
|
|
13
|
+
- **Erreurs** 🔴 : Empêchent la soumission du formulaire
|
|
14
|
+
- **Avertissements** 🟠 : Informent l'utilisateur sans bloquer la soumission
|
|
15
|
+
- **Succès** 🟢 : Confirment la validité de l'entrée
|
|
16
|
+
|
|
17
|
+
## Mise en place simple
|
|
18
|
+
|
|
19
|
+
Voici comment mettre en place une validation basique sur un champ :
|
|
20
|
+
|
|
21
|
+
<Source dark code={`
|
|
22
|
+
<template>
|
|
23
|
+
<SyTextField
|
|
24
|
+
v-model="email"
|
|
25
|
+
label="Email"
|
|
26
|
+
:custom-rules="emailRules"
|
|
27
|
+
/>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { ref } from 'vue';
|
|
32
|
+
import { SyTextField } from '@cnamts/synapse';
|
|
33
|
+
|
|
34
|
+
const email = ref('');
|
|
35
|
+
|
|
36
|
+
const emailRules = [
|
|
37
|
+
{
|
|
38
|
+
type: 'required',
|
|
39
|
+
options: { message: "L'email est obligatoire" }
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
type: 'email',
|
|
43
|
+
options: { message: "L'email n'est pas valide" }
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
</script>
|
|
47
|
+
`}/>
|
|
48
|
+
|
|
49
|
+
## Validation complète avec les 3 niveaux
|
|
50
|
+
|
|
51
|
+
Utilisez les différents types de règles pour une expérience utilisateur riche :
|
|
52
|
+
|
|
53
|
+
<Source dark code={`
|
|
54
|
+
<script setup>
|
|
55
|
+
import { ref } from 'vue'
|
|
56
|
+
import PasswordField from '@/components/PasswordField/PasswordField.vue'
|
|
57
|
+
|
|
58
|
+
const password = ref('')
|
|
59
|
+
|
|
60
|
+
// Règles d'erreur (bloquantes)
|
|
61
|
+
const passwordRules = [
|
|
62
|
+
{
|
|
63
|
+
type: 'required',
|
|
64
|
+
options: {
|
|
65
|
+
message: 'Le mot de passe est obligatoire',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: 'minLength',
|
|
70
|
+
options: {
|
|
71
|
+
length: 8,
|
|
72
|
+
message: 'Le mot de passe doit contenir au moins 8 caractères',
|
|
73
|
+
// si pas de successMessage, le message par defaut est affiché
|
|
74
|
+
successMessage: 'Le mot de passe est sécurisé',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
// Règles d'avertissement (non-bloquantes)
|
|
80
|
+
const passwordWarningRules = [
|
|
81
|
+
{
|
|
82
|
+
type: 'custom',
|
|
83
|
+
options: {
|
|
84
|
+
validate: (value) => {
|
|
85
|
+
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value)
|
|
86
|
+
if (!hasSpecialChar) {
|
|
87
|
+
return 'Le mot de passe pourrait être plus fort avec des caractères spéciaux'
|
|
88
|
+
}
|
|
89
|
+
return true
|
|
90
|
+
},
|
|
91
|
+
fieldIdentifier: 'password',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<template>
|
|
99
|
+
<PasswordField
|
|
100
|
+
v-model="password"
|
|
101
|
+
label="Mot de passe"
|
|
102
|
+
:custom-warning-rules="passwordWarningRules"
|
|
103
|
+
:custom-rules="passwordRules"
|
|
104
|
+
/>
|
|
105
|
+
</template>
|
|
106
|
+
|
|
107
|
+
`}/>
|
|
108
|
+
|
|
109
|
+
## Validation à la soumission avec validateOnSubmit
|
|
110
|
+
|
|
111
|
+
La méthode `validateOnSubmit` est essentielle pour valider l'ensemble du formulaire lors de sa soumission :
|
|
112
|
+
|
|
113
|
+
<Source dark code={`
|
|
114
|
+
<template>
|
|
115
|
+
<form @submit.prevent="handleSubmit">
|
|
116
|
+
<SyTextField
|
|
117
|
+
ref="emailField"
|
|
118
|
+
v-model="email"
|
|
119
|
+
label="Email"
|
|
120
|
+
:custom-rules="emailRules"
|
|
121
|
+
/>
|
|
122
|
+
|
|
123
|
+
<PasswordField
|
|
124
|
+
ref="passwordField"
|
|
125
|
+
v-model="password"
|
|
126
|
+
label="Mot de passe"
|
|
127
|
+
type="password"
|
|
128
|
+
:custom-rules="passwordRules"
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
<VBtn type="submit">Se connecter</VBtn>
|
|
132
|
+
|
|
133
|
+
<p v-if="formError" class="error-message">{{ formError }}</p>
|
|
134
|
+
</form>
|
|
135
|
+
</template>
|
|
136
|
+
|
|
137
|
+
<script setup>
|
|
138
|
+
import { ref } from 'vue';
|
|
139
|
+
import { SyTextField, PasswordField } from '@cnamts/synapse';
|
|
140
|
+
|
|
141
|
+
const email = ref('');
|
|
142
|
+
const password = ref('');
|
|
143
|
+
const formError = ref('');
|
|
144
|
+
|
|
145
|
+
const emailField = ref();
|
|
146
|
+
const passwordField = ref();
|
|
147
|
+
|
|
148
|
+
const emailRules = [
|
|
149
|
+
{ type: 'required', options: { message: "L'email est obligatoire" } },
|
|
150
|
+
{ type: 'email', options: { message: "L'email n'est pas valide" } }
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const passwordRules = [
|
|
154
|
+
{ type: 'required', options: { message: 'Le mot de passe est obligatoire' } }
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
const handleSubmit = async () => {
|
|
158
|
+
formError.value = '';
|
|
159
|
+
|
|
160
|
+
// Validation de tous les champs
|
|
161
|
+
const isEmailValid = await emailField.value.validateOnSubmit();
|
|
162
|
+
const isPasswordValid = await passwordField.value.validateOnSubmit();
|
|
163
|
+
|
|
164
|
+
if (isEmailValid && isPasswordValid) {
|
|
165
|
+
// Soumettre le formulaire
|
|
166
|
+
console.log('Formulaire soumis avec succès !');
|
|
167
|
+
// loginUser(email.value, password.value);
|
|
168
|
+
} else {
|
|
169
|
+
formError.value = 'Veuillez corriger les erreurs dans le formulaire';
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
</script>
|
|
173
|
+
`}/>
|
|
174
|
+
|
|
175
|
+
## Validation croisée entre champs
|
|
176
|
+
|
|
177
|
+
Parfois, la validation d'un champ dépend de la valeur d'un autre champ. Voici comment gérer ce cas :
|
|
178
|
+
|
|
179
|
+
<Source dark code={`
|
|
180
|
+
<template>
|
|
181
|
+
<form @submit.prevent="handleSubmit">
|
|
182
|
+
<PasswordField
|
|
183
|
+
ref="passwordField"
|
|
184
|
+
v-model="password"
|
|
185
|
+
label="Mot de passe"
|
|
186
|
+
type="password"
|
|
187
|
+
:custom-rules="passwordRules"
|
|
188
|
+
/>
|
|
189
|
+
|
|
190
|
+
<PasswordField
|
|
191
|
+
ref="confirmPasswordField"
|
|
192
|
+
v-model="confirmPassword"
|
|
193
|
+
label="Confirmer le mot de passe"
|
|
194
|
+
type="password"
|
|
195
|
+
:custom-rules="confirmPasswordRules"
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
<VBtn type="submit">S'inscrire</VBtn>
|
|
199
|
+
</form>
|
|
200
|
+
</template>
|
|
201
|
+
|
|
202
|
+
<script setup>
|
|
203
|
+
import { ref, watch } from 'vue';
|
|
204
|
+
import { PasswordField } from '@cnamts/synapse';
|
|
205
|
+
|
|
206
|
+
const password = ref('');
|
|
207
|
+
const confirmPassword = ref('');
|
|
208
|
+
|
|
209
|
+
const passwordField = ref();
|
|
210
|
+
const confirmPasswordField = ref();
|
|
211
|
+
|
|
212
|
+
const passwordRules = [
|
|
213
|
+
{ type: 'required', options: { message: 'Le mot de passe est obligatoire' } },
|
|
214
|
+
{ type: 'minLength', options: { length: 8, message: 'Le mot de passe doit contenir au moins 8 caractères' } }
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
const confirmPasswordRules = [
|
|
218
|
+
{ type: 'required', options: { message: 'La confirmation du mot de passe est obligatoire' } },
|
|
219
|
+
{
|
|
220
|
+
type: 'custom',
|
|
221
|
+
options: {
|
|
222
|
+
validate: (value) => {
|
|
223
|
+
if (value !== password.value) {
|
|
224
|
+
return 'Les mots de passe ne correspondent pas';
|
|
225
|
+
}
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
// Revalider la confirmation lorsque le mot de passe change
|
|
233
|
+
watch(password, () => {
|
|
234
|
+
if (confirmPassword.value && confirmPasswordField.value) {
|
|
235
|
+
// Forcer la validation du champ de confirmation
|
|
236
|
+
confirmPasswordField.value.validateOnSubmit();
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const handleSubmit = async () => {
|
|
241
|
+
// Validation de tous les champs
|
|
242
|
+
const isPasswordValid = await passwordField.value.validateOnSubmit();
|
|
243
|
+
const isConfirmValid = await confirmPasswordField.value.validateOnSubmit();
|
|
244
|
+
|
|
245
|
+
if (isPasswordValid && isConfirmValid) {
|
|
246
|
+
// Soumettre le formulaire
|
|
247
|
+
console.log('Inscription réussie !');
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
</script>
|
|
251
|
+
`}/>
|
|
252
|
+
|
|
253
|
+
## Composants avec validation intégrée
|
|
254
|
+
|
|
255
|
+
Plusieurs composants du Design System intègrent déjà la validation :
|
|
256
|
+
|
|
257
|
+
- **SyTextField** : Pour les champs texte
|
|
258
|
+
- **NirField** : Pour les numéros de sécurité sociale
|
|
259
|
+
- **DatePicker** : Pour les dates
|
|
260
|
+
- **PeriodField** : Pour les périodes (deux dates liées)
|
|
261
|
+
- **PasswordField** : Pour les mots de passe sécurisés
|
|
262
|
+
|
|
263
|
+
### Exemple avec NirField
|
|
264
|
+
|
|
265
|
+
<Source dark code={`
|
|
266
|
+
<template>
|
|
267
|
+
<form @submit.prevent="handleSubmit">
|
|
268
|
+
<NirField
|
|
269
|
+
ref="nirFieldRef"
|
|
270
|
+
v-model="nirValue"
|
|
271
|
+
label="Numéro de sécurité sociale"
|
|
272
|
+
/>
|
|
273
|
+
|
|
274
|
+
<SyButton type="submit">Valider</SyButton>
|
|
275
|
+
</form>
|
|
276
|
+
</template>
|
|
277
|
+
|
|
278
|
+
<script setup>
|
|
279
|
+
import { ref } from 'vue';
|
|
280
|
+
import { NirField, SyButton } from '@cnamts/synapse';
|
|
281
|
+
|
|
282
|
+
const nirValue = ref('');
|
|
283
|
+
const nirFieldRef = ref();
|
|
284
|
+
|
|
285
|
+
const handleSubmit = async () => {
|
|
286
|
+
const isValid = await nirFieldRef.value.validateOnSubmit();
|
|
287
|
+
|
|
288
|
+
if (isValid) {
|
|
289
|
+
console.log('NIR valide :', nirValue.value);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
</script>
|
|
293
|
+
`}/>
|
|
294
|
+
|
|
295
|
+
## Règles de validation disponibles
|
|
296
|
+
|
|
297
|
+
### Règles génériques
|
|
298
|
+
- `required` : Champ obligatoire
|
|
299
|
+
- `minLength` / `maxLength` : Longueur minimale/maximale
|
|
300
|
+
- `min` / `max` : Valeur minimale/maximale pour les nombres
|
|
301
|
+
- `email` : Format d'email valide
|
|
302
|
+
- `matchPattern` : Correspondance à une expression régulière
|
|
303
|
+
|
|
304
|
+
### Règles de dates
|
|
305
|
+
- `notBeforeToday` / `notAfterToday` : Date après/avant aujourd'hui
|
|
306
|
+
- `notBeforeDate` / `notAfterDate` : Date après/avant une date spécifique
|
|
307
|
+
- `notWeekend` : Jour ouvrable
|
|
308
|
+
- `isHolidayDay` : Jour non férié
|
|
309
|
+
|
|
310
|
+
### Règles personnalisées
|
|
311
|
+
Utilisez le type `custom` avec une fonction `validate` pour créer vos propres règles :
|
|
312
|
+
|
|
313
|
+
<Source dark code={`
|
|
314
|
+
const customRule = {
|
|
315
|
+
type: 'custom',
|
|
316
|
+
options: {
|
|
317
|
+
validate: (value) => {
|
|
318
|
+
// Votre logique personnalisée
|
|
319
|
+
if (!condition) {
|
|
320
|
+
return 'Message d\'erreur personnalisé';
|
|
321
|
+
}
|
|
322
|
+
return true; // Valide
|
|
323
|
+
},
|
|
324
|
+
// Optionnel : traiter comme avertissement au lieu d'erreur
|
|
325
|
+
isWarning: false
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
`}/>
|
|
329
|
+
|
|
330
|
+
## Bonnes pratiques
|
|
331
|
+
|
|
332
|
+
1. **Validation progressive** : Validez pendant la saisie pour une rétroaction immédiate
|
|
333
|
+
2. **Messages clairs** : Utilisez des messages d'erreur explicites et constructifs
|
|
334
|
+
3. **Validation côté client ET serveur** : Ne vous fiez jamais uniquement à la validation côté client
|
|
335
|
+
4. **Utilisez validateOnSubmit** : Assurez-vous que tous les champs sont validés à la soumission
|
|
336
|
+
5. **Hiérarchisez les erreurs** : Affichez d'abord les erreurs les plus importantes
|
|
337
|
+
6. **Utilisez les avertissements** pour les recommandations non-bloquantes
|
|
338
|
+
7. **Célébrez la réussite** avec des messages de succès pour renforcer les bonnes pratiques
|
|
339
|
+
|
|
340
|
+
## Conclusion
|
|
341
|
+
|
|
342
|
+
Le système de validation du Design System vous permet de créer des formulaires intuitifs avec des retours utilisateur riches. En combinant validation à la saisie et validation à la soumission, vous offrez une expérience utilisateur optimale tout en garantissant l'intégrité des données.
|
|
@@ -10,7 +10,7 @@ export const Header: StoryObj = {
|
|
|
10
10
|
return {
|
|
11
11
|
template: `
|
|
12
12
|
<div class="mb-8">
|
|
13
|
-
<h1 class="
|
|
13
|
+
<h1 class="mb-4">Templates</h1>
|
|
14
14
|
<p class="text-body-1">Découvrez notre collection de templates conçus pour accélérer le développement de vos IHM.</p>
|
|
15
15
|
</div>
|
|
16
16
|
`,
|
|
@@ -14,7 +14,7 @@ export const AmeliproColors: AmeliproColorsTypes = {
|
|
|
14
14
|
apGreendarken1: { hexColor: '#459B5A' },
|
|
15
15
|
apGreendarken2: { hexColor: '#337343' },
|
|
16
16
|
apGreenlighten1: { hexColor: '#78CE8D' },
|
|
17
|
-
apGreenlighten2: { hexColor: '#
|
|
17
|
+
apGreenlighten2: { hexColor: '#DDF3E3' },
|
|
18
18
|
apGrey: { hexColor: '#545859' },
|
|
19
19
|
apGreydarken1: { hexColor: '#1A1B1B' },
|
|
20
20
|
apGreylighten1: { hexColor: '#CCCDCE' },
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils'
|
|
2
|
-
import PhoneField from '../PhoneField.vue'
|
|
3
|
-
import { describe, it, expect, beforeEach } from 'vitest'
|
|
4
|
-
import { createVuetify } from 'vuetify'
|
|
5
|
-
import * as components from 'vuetify/components'
|
|
6
|
-
import * as directives from 'vuetify/directives'
|
|
7
|
-
import { indicatifs } from '../indicatifs'
|
|
8
|
-
|
|
9
|
-
const vuetify = createVuetify({
|
|
10
|
-
components,
|
|
11
|
-
directives,
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
// Tests supplémentaires pour le composant PhoneField
|
|
15
|
-
describe('PhoneField - Additional Tests', () => {
|
|
16
|
-
// Tests pour les différents formats d'affichage
|
|
17
|
-
describe('Display formats', () => {
|
|
18
|
-
let wrapper
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
wrapper = mount(PhoneField, {
|
|
22
|
-
global: {
|
|
23
|
-
plugins: [vuetify],
|
|
24
|
-
},
|
|
25
|
-
props: {
|
|
26
|
-
withCountryCode: true,
|
|
27
|
-
dialCodeModel: { code: '+33', abbreviation: 'FR', country: 'France', phoneLength: 10, mask: '## ## ## ## ##' },
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('formats display text as code by default', async () => {
|
|
33
|
-
const select = wrapper.findComponent({ name: 'SySelect' })
|
|
34
|
-
// Vérifier que le format d'affichage est bien le code
|
|
35
|
-
const firstItem = select.props('items')[0]
|
|
36
|
-
expect(firstItem.displayText).toBe(firstItem.code)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('formats display text as code-abbreviation', async () => {
|
|
40
|
-
await wrapper.setProps({ displayFormat: 'code-abbreviation' })
|
|
41
|
-
const select = wrapper.findComponent({ name: 'SySelect' })
|
|
42
|
-
const firstItem = select.props('items')[0]
|
|
43
|
-
expect(firstItem.displayText).toBe(`${firstItem.code} (${firstItem.abbreviation})`)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('formats display text as code-country', async () => {
|
|
47
|
-
await wrapper.setProps({ displayFormat: 'code-country' })
|
|
48
|
-
const select = wrapper.findComponent({ name: 'SySelect' })
|
|
49
|
-
const firstItem = select.props('items')[0]
|
|
50
|
-
expect(firstItem.displayText).toBe(`${firstItem.code} ${firstItem.country}`)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('formats display text as country', async () => {
|
|
54
|
-
await wrapper.setProps({ displayFormat: 'country' })
|
|
55
|
-
const select = wrapper.findComponent({ name: 'SySelect' })
|
|
56
|
-
const firstItem = select.props('items')[0]
|
|
57
|
-
expect(firstItem.displayText).toBe(firstItem.country)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('formats display text as abbreviation', async () => {
|
|
61
|
-
await wrapper.setProps({ displayFormat: 'abbreviation' })
|
|
62
|
-
const select = wrapper.findComponent({ name: 'SySelect' })
|
|
63
|
-
const firstItem = select.props('items')[0]
|
|
64
|
-
expect(firstItem.displayText).toBe(firstItem.abbreviation)
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// Tests pour l'initialisation avec un dialCode par défaut
|
|
69
|
-
describe('Default dialCode initialization', () => {
|
|
70
|
-
it('initializes with a default dialCode object', async () => {
|
|
71
|
-
const defaultDialCode = { code: '+44', abbreviation: 'UK', country: 'United Kingdom', phoneLength: 11, mask: '#### ### ####' }
|
|
72
|
-
const wrapper = mount(PhoneField, {
|
|
73
|
-
global: {
|
|
74
|
-
plugins: [vuetify],
|
|
75
|
-
},
|
|
76
|
-
props: {
|
|
77
|
-
withCountryCode: true,
|
|
78
|
-
dialCodeModel: defaultDialCode,
|
|
79
|
-
},
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
await wrapper.vm.$nextTick()
|
|
83
|
-
|
|
84
|
-
// Vérifier que le dialCode est correctement initialisé
|
|
85
|
-
expect(wrapper.vm.dialCode).toBeDefined()
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
87
|
-
expect((wrapper.vm.dialCode as any).code).toBe('+44')
|
|
88
|
-
// Vérifier que le masque est appliqué (le format exact peut varier)
|
|
89
|
-
expect(wrapper.vm.phoneMask).toBeDefined()
|
|
90
|
-
// Vérifier que le counter est défini selon la phoneLength
|
|
91
|
-
expect(wrapper.vm.counter).toBeDefined()
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('initializes with a default dialCode string', async () => {
|
|
95
|
-
const wrapper = mount(PhoneField, {
|
|
96
|
-
global: {
|
|
97
|
-
plugins: [vuetify],
|
|
98
|
-
},
|
|
99
|
-
props: {
|
|
100
|
-
withCountryCode: true,
|
|
101
|
-
dialCodeModel: '+33',
|
|
102
|
-
},
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
await wrapper.vm.$nextTick()
|
|
106
|
-
|
|
107
|
-
// Vérifier que le dialCode est correctement initialisé
|
|
108
|
-
expect(wrapper.vm.dialCode).toBe('+33')
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
// Tests pour la désactivation de la gestion des erreurs
|
|
113
|
-
describe('Error handling', () => {
|
|
114
|
-
it('displays error messages by default when validation fails', async () => {
|
|
115
|
-
const wrapper = mount(PhoneField, {
|
|
116
|
-
global: {
|
|
117
|
-
plugins: [vuetify],
|
|
118
|
-
},
|
|
119
|
-
props: {
|
|
120
|
-
required: true,
|
|
121
|
-
modelValue: '',
|
|
122
|
-
isValidatedOnBlur: true,
|
|
123
|
-
},
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
// Déclencher la validation
|
|
127
|
-
await wrapper.vm.validateOnSubmit()
|
|
128
|
-
|
|
129
|
-
// Vérifier que les erreurs sont affichées
|
|
130
|
-
expect(wrapper.vm.hasError).toBe(true)
|
|
131
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
132
|
-
expect((wrapper.vm as any).errors.length).toBeGreaterThan(0)
|
|
133
|
-
|
|
134
|
-
// Vérifier que les erreurs sont passées au composant SyTextField
|
|
135
|
-
const textField = wrapper.findComponent({ name: 'SyTextField' })
|
|
136
|
-
expect(textField.props('errorMessages')).toBeTruthy()
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('initializes with disableErrorHandling prop', async () => {
|
|
140
|
-
const wrapper = mount(PhoneField, {
|
|
141
|
-
global: {
|
|
142
|
-
plugins: [vuetify],
|
|
143
|
-
},
|
|
144
|
-
props: {
|
|
145
|
-
required: true,
|
|
146
|
-
modelValue: '',
|
|
147
|
-
isValidatedOnBlur: true,
|
|
148
|
-
disableErrorHandling: true,
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
// Vérifier que la propriété disableErrorHandling est bien prise en compte
|
|
153
|
-
// en vérifiant qu'elle est passée lors de l'initialisation du composable useValidation
|
|
154
|
-
expect(wrapper.vm.validation).toBeDefined()
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
// Tests pour la validation dans un contexte de formulaire
|
|
159
|
-
describe('Form validation', () => {
|
|
160
|
-
it('validates as part of a form submission', async () => {
|
|
161
|
-
const wrapper = mount(PhoneField, {
|
|
162
|
-
global: {
|
|
163
|
-
plugins: [vuetify],
|
|
164
|
-
},
|
|
165
|
-
props: {
|
|
166
|
-
required: true,
|
|
167
|
-
modelValue: '',
|
|
168
|
-
},
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
// Simuler une soumission de formulaire avec un champ vide
|
|
172
|
-
const isValid = await wrapper.vm.validateOnSubmit()
|
|
173
|
-
expect(isValid).toBe(false)
|
|
174
|
-
|
|
175
|
-
// Mettre à jour la valeur et valider à nouveau
|
|
176
|
-
await wrapper.setProps({ modelValue: '0123456789' })
|
|
177
|
-
const isValidAfterUpdate = await wrapper.vm.validateOnSubmit()
|
|
178
|
-
expect(isValidAfterUpdate).toBe(true)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('validates country code as part of form submission', async () => {
|
|
182
|
-
const wrapper = mount(PhoneField, {
|
|
183
|
-
global: {
|
|
184
|
-
plugins: [vuetify],
|
|
185
|
-
},
|
|
186
|
-
props: {
|
|
187
|
-
required: true,
|
|
188
|
-
modelValue: '0123456789',
|
|
189
|
-
withCountryCode: true,
|
|
190
|
-
countryCodeRequired: true,
|
|
191
|
-
},
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
// Sans code pays, la validation échoue
|
|
195
|
-
const isValidWithoutCountry = await wrapper.vm.validateOnSubmit()
|
|
196
|
-
expect(isValidWithoutCountry).toBe(false)
|
|
197
|
-
|
|
198
|
-
// Ajouter un code pays et valider à nouveau
|
|
199
|
-
wrapper.vm.dialCode = { code: '+33', abbreviation: 'FR', country: 'France', phoneLength: 10, mask: '## ## ## ## ##' }
|
|
200
|
-
await wrapper.vm.$nextTick()
|
|
201
|
-
|
|
202
|
-
const isValidWithCountry = await wrapper.vm.validateOnSubmit()
|
|
203
|
-
expect(isValidWithCountry).toBe(true)
|
|
204
|
-
})
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
// Tests pour la gestion des indicatifs personnalisés
|
|
208
|
-
describe('Custom indicatifs', () => {
|
|
209
|
-
it('merges custom indicatifs with standard ones by default', () => {
|
|
210
|
-
const customIndicatifs = [{ code: '+999', abbreviation: 'XX', country: 'Test Country', phoneLength: 8, mask: '## ## ## ##' }]
|
|
211
|
-
const wrapper = mount(PhoneField, {
|
|
212
|
-
global: {
|
|
213
|
-
plugins: [vuetify],
|
|
214
|
-
},
|
|
215
|
-
props: {
|
|
216
|
-
customIndicatifs,
|
|
217
|
-
withCountryCode: true,
|
|
218
|
-
},
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
// Vérifier que les indicatifs personnalisés sont ajoutés aux indicatifs standards
|
|
222
|
-
expect(wrapper.vm.mergedDialCodes.length).toBe(indicatifs.length + customIndicatifs.length)
|
|
223
|
-
expect(wrapper.vm.mergedDialCodes).toContainEqual(customIndicatifs[0])
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('uses only custom indicatifs when useCustomIndicatifsOnly is true', () => {
|
|
227
|
-
const customIndicatifs = [{ code: '+999', abbreviation: 'XX', country: 'Test Country', phoneLength: 8, mask: '## ## ## ##' }]
|
|
228
|
-
const wrapper = mount(PhoneField, {
|
|
229
|
-
global: {
|
|
230
|
-
plugins: [vuetify],
|
|
231
|
-
},
|
|
232
|
-
props: {
|
|
233
|
-
customIndicatifs,
|
|
234
|
-
useCustomIndicatifsOnly: true,
|
|
235
|
-
withCountryCode: true,
|
|
236
|
-
},
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
// Vérifier que seuls les indicatifs personnalisés sont utilisés
|
|
240
|
-
expect(wrapper.vm.mergedDialCodes.length).toBe(customIndicatifs.length)
|
|
241
|
-
expect(wrapper.vm.mergedDialCodes).toEqual(customIndicatifs)
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
it('updates phone mask and counter based on selected custom indicatif', async () => {
|
|
245
|
-
const customIndicatifs = [{ code: '+999', abbreviation: 'XX', country: 'Test Country', phoneLength: 8, mask: '## ## ## ##' }]
|
|
246
|
-
const wrapper = mount(PhoneField, {
|
|
247
|
-
global: {
|
|
248
|
-
plugins: [vuetify],
|
|
249
|
-
},
|
|
250
|
-
props: {
|
|
251
|
-
customIndicatifs,
|
|
252
|
-
useCustomIndicatifsOnly: true,
|
|
253
|
-
withCountryCode: true,
|
|
254
|
-
},
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
// Sélectionner l'indicatif personnalisé
|
|
258
|
-
wrapper.vm.dialCode = customIndicatifs[0]
|
|
259
|
-
await wrapper.vm.$nextTick()
|
|
260
|
-
|
|
261
|
-
// Vérifier que le masque et le compteur sont mis à jour
|
|
262
|
-
expect(wrapper.vm.phoneMask).toBe('## ## ## ##')
|
|
263
|
-
expect(wrapper.vm.counter).toBe(8)
|
|
264
|
-
})
|
|
265
|
-
})
|
|
266
|
-
})
|