@cnamts/synapse 0.0.15-alpha → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Accordion/Accordion.d.ts +39 -0
- package/dist/components/Accordion/config.d.ts +9 -0
- package/dist/components/ChipList/ChipList.d.ts +1 -1
- package/dist/components/CookiesSelection/CookiesSelection.d.ts +26 -26
- package/dist/components/CopyBtn/CopyBtn.d.ts +2 -0
- package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +12 -0
- package/dist/components/Customs/SySelect/SySelect.d.ts +43 -16
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +1391 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2810 -16
- package/dist/components/DatePicker/DateTextInput.d.ts +1401 -4
- package/dist/components/DiacriticPicker/DiacriticPicker.d.ts +27 -0
- package/dist/components/DiacriticPicker/config.d.ts +14 -0
- package/dist/components/DiacriticPicker/locales.d.ts +6 -0
- package/dist/components/DownloadBtn/DownloadBtn.d.ts +1 -1
- package/dist/components/FooterBar/FooterBar.d.ts +1 -1
- package/dist/components/LangBtn/LangBtn.d.ts +4 -4
- package/dist/components/NirField/NirField.d.ts +2796 -4
- package/dist/components/NotificationBar/NotificationBar.d.ts +1 -1
- package/dist/components/PasswordField/PasswordField.d.ts +1 -1
- package/dist/components/PeriodField/PeriodField.d.ts +5636 -48
- package/dist/components/PhoneField/PhoneField.d.ts +1 -0
- package/dist/components/PhoneField/tests/types.d.ts +18 -0
- package/dist/components/SyAlert/SyAlert.d.ts +72 -1
- package/dist/components/SyTextArea/SyTextArea.d.ts +900 -0
- package/dist/components/SyTextArea/locales.d.ts +3 -0
- package/dist/components/SyTextArea/trimStartOnUpdate.d.ts +1 -0
- package/dist/components/SyTextArea/useTextActions.d.ts +13 -0
- package/dist/components/SyTextArea/wrapText.d.ts +1 -0
- package/dist/components/TableToolbar/TableToolbar.d.ts +10 -4
- package/dist/components/TableToolbar/config.d.ts +3 -2
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +26 -26
- package/dist/components/index.d.ts +4 -0
- package/dist/composables/date/useDateFormat.d.ts +2 -2
- package/dist/composables/date/useDateFormatDayjs.d.ts +23 -0
- package/dist/composables/date/useDateInitializationDayjs.d.ts +18 -0
- package/dist/composables/date/useHolidayDay.d.ts +36 -0
- package/dist/design-system-v3.js +5106 -4208
- package/dist/design-system-v3.umd.cjs +4 -1
- package/dist/designTokens/tokens/pa/paLightTheme.d.ts +1 -32
- package/dist/style.css +1 -1
- package/dist/utils/rules/index.d.ts +1 -0
- package/dist/utils/rules/isHolidayDay/index.d.ts +11 -0
- package/dist/utils/rules/isHolidayDay/locales.d.ts +2 -0
- package/package.json +3 -2
- package/src/assets/settings.scss +12 -0
- package/src/components/Accordion/Accordion.mdx +69 -0
- package/src/components/Accordion/Accordion.stories.ts +262 -0
- package/src/components/Accordion/Accordion.vue +319 -0
- package/src/components/Accordion/config.ts +9 -0
- package/src/components/Accordion/tests/__snapshots__/accordion.spec.ts.snap +155 -0
- package/src/components/Accordion/tests/accordion.spec.ts +492 -0
- package/src/components/CopyBtn/CopyBtn.stories.ts +189 -0
- package/src/components/CopyBtn/CopyBtn.vue +29 -1
- package/src/components/CopyBtn/tests/CopyBtn.spec.ts +102 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +155 -1
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +97 -14
- package/src/components/Customs/SyInputSelect/tests/SyInputSelect.spec.ts +386 -106
- package/src/components/Customs/SySelect/SySelect.stories.ts +121 -2
- package/src/components/Customs/SySelect/SySelect.vue +33 -8
- package/src/components/Customs/SySelect/tests/SySelect.spec.ts +290 -1
- package/src/components/Customs/SyTextField/Accessibilite.stories.ts +7 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +13 -0
- package/src/components/Customs/SyTextField/SyTextField.vue +87 -20
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +795 -0
- package/src/components/DatePicker/DatePicker.stories.ts +432 -1
- package/src/components/DatePicker/DatePicker.vue +82 -27
- package/src/components/DatePicker/DatePickerValidation.stories.ts +9 -1
- package/src/components/DatePicker/DateTextInput.vue +101 -138
- package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +282 -0
- package/src/components/DatePicker/examples/DatePickerHolidayRule.vue +130 -0
- package/src/components/DatePicker/tests/DatePicker.spec.ts +33 -32
- package/src/components/DatePicker/tests/DateTextInput.spec.ts +81 -33
- package/src/components/DiacriticPicker/DiacriticPicker.mdx +104 -0
- package/src/components/DiacriticPicker/DiacriticPicker.stories.ts +447 -0
- package/src/components/DiacriticPicker/DiacriticPicker.vue +262 -0
- package/src/components/DiacriticPicker/config.ts +15 -0
- package/src/components/DiacriticPicker/locales.ts +6 -0
- package/src/components/DiacriticPicker/tests/DiatriticPicker.spec.ts +132 -0
- package/src/components/DialogBox/DialogBox.vue +1 -3
- package/src/components/NirField/NirField.stories.ts +172 -0
- package/src/components/NirField/NirField.vue +15 -7
- package/src/components/NotificationBar/Accessibilite.stories.ts +1 -1
- package/src/components/NotificationBar/NotificationBar.stories.ts +14 -0
- package/src/components/NotificationBar/NotificationBar.vue +26 -3
- package/src/components/NotificationBar/{options.ts → config.ts} +0 -1
- package/src/components/PaginatedTable/PaginatedTable.vue +0 -11
- package/src/components/PasswordField/PasswordField.stories.ts +4 -3
- package/src/components/PasswordField/PasswordField.vue +26 -18
- package/src/components/PasswordField/tests/PasswordField.spec.ts +1 -10
- package/src/components/PhoneField/PhoneField.stories.ts +143 -0
- package/src/components/PhoneField/PhoneField.vue +88 -30
- package/src/components/PhoneField/tests/PhoneField.additional.spec.ts +266 -0
- package/src/components/PhoneField/tests/PhoneField.spec.ts +248 -28
- package/src/components/PhoneField/tests/types.d.ts +19 -0
- package/src/components/SyAlert/Accessibilite.stories.ts +4 -0
- package/src/components/SyAlert/SyAlert.mdx +3 -7
- package/src/components/SyAlert/SyAlert.stories.ts +19 -12
- package/src/components/SyAlert/SyAlert.vue +88 -51
- package/src/components/SyAlert/tests/SyAlert.spec.ts +20 -2
- package/src/components/SyAlert/tests/__snapshots__/SyAlert.spec.ts.snap +83 -75
- package/src/components/SyTextArea/SyTextArea.mdx +17 -0
- package/src/components/SyTextArea/SyTextArea.stories.ts +322 -0
- package/src/components/SyTextArea/SyTextArea.vue +113 -0
- package/src/components/SyTextArea/locales.ts +3 -0
- package/src/components/SyTextArea/tests/SyTextArea.spec.ts +194 -0
- package/src/components/SyTextArea/trimStartOnUpdate.ts +12 -0
- package/src/components/SyTextArea/useTextActions.ts +52 -0
- package/src/components/SyTextArea/wrapText.ts +42 -0
- package/src/components/TableToolbar/TableToolbar.mdx +86 -1
- package/src/components/TableToolbar/TableToolbar.stories.ts +422 -74
- package/src/components/TableToolbar/TableToolbar.vue +25 -8
- package/src/components/TableToolbar/config.ts +3 -2
- package/src/components/TableToolbar/tests/__snapshots__/TableToolbar.spec.ts.snap +35 -12
- package/src/components/index.ts +4 -0
- package/src/composables/date/useDateFormat.ts +17 -1
- package/src/composables/date/useDateFormatDayjs.ts +84 -0
- package/src/composables/date/useDateInitializationDayjs.ts +133 -0
- package/src/composables/date/useHolidayDay.ts +98 -0
- package/src/composables/rules/useFieldValidation.ts +16 -3
- package/src/composables/validation/useValidation.ts +2 -1
- package/src/designTokens/tokens/pa/paLightTheme.ts +10 -41
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +12 -0
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +134 -0
- package/src/stories/Accessibilite/Introduction.mdx +5 -2
- package/src/stories/DesignTokens/colors.stories.ts +100 -41
- package/src/utils/rules/index.ts +1 -0
- package/src/utils/rules/isHolidayDay/IsHolidayDay.mdx +52 -0
- package/src/utils/rules/isHolidayDay/IsHolidayDay.stories.ts +129 -0
- package/src/utils/rules/isHolidayDay/index.ts +36 -0
- package/src/utils/rules/isHolidayDay/locales.ts +5 -0
- package/src/utils/rules/isHolidayDay/tests/isHolidayDay.spec.ts +35 -0
- /package/dist/components/NotificationBar/{options.d.ts → config.d.ts} +0 -0
- /package/src/components/DatePicker/{DatePickerValidationExamples.vue → docExamples/DatePickerValidationExamples.vue} +0 -0
|
@@ -4,137 +4,417 @@ import SyInputSelect from '../SyInputSelect.vue'
|
|
|
4
4
|
import { vuetify } from '@tests/unit/setup'
|
|
5
5
|
|
|
6
6
|
describe('SyInputSelect', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
describe('Rendu et affichage', () => {
|
|
8
|
+
it('renders the component with default props', () => {
|
|
9
|
+
const wrapper = mount(SyInputSelect, {
|
|
10
|
+
global: {
|
|
11
|
+
plugins: [vuetify],
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
expect(wrapper.exists()).toBe(true)
|
|
15
|
+
expect(wrapper.find('.sy-input-select').text()).toBe('Sélectionnez une option')
|
|
16
|
+
})
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
it('displays the selected item text', async () => {
|
|
19
|
+
const items = [{ text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }]
|
|
20
|
+
const wrapper = mount(SyInputSelect, {
|
|
21
|
+
props: { items, modelValue: { text: 'Option 1', value: '1' } },
|
|
22
|
+
global: {
|
|
23
|
+
plugins: [vuetify],
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
expect(wrapper.find('.sy-input-select').text()).toContain('Option 1')
|
|
24
27
|
})
|
|
25
|
-
expect(wrapper.find('.sy-input-select').text()).toContain('Option 1')
|
|
26
|
-
})
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
it('does not render error messages when not provided', () => {
|
|
30
|
+
const wrapper = mount(SyInputSelect, {
|
|
31
|
+
global: {
|
|
32
|
+
plugins: [vuetify],
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
33
36
|
})
|
|
34
|
-
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
35
|
-
})
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
it('does not render the label when not provided', () => {
|
|
39
|
+
const wrapper = mount(SyInputSelect, {
|
|
40
|
+
global: {
|
|
41
|
+
plugins: [vuetify],
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
expect(wrapper.find('label').exists()).toBe(false)
|
|
42
45
|
})
|
|
43
|
-
expect(wrapper.find('label').exists()).toBe(false)
|
|
44
|
-
})
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
it('formats items correctly', () => {
|
|
48
|
+
const items = ['Option 1', 'Option 2']
|
|
49
|
+
const wrapper = mount(SyInputSelect, {
|
|
50
|
+
props: { items, textKey: 'text', valueKey: 'value' },
|
|
51
|
+
global: {
|
|
52
|
+
plugins: [vuetify],
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
56
|
+
const formattedItems = (wrapper.vm as any).formattedItems
|
|
57
|
+
expect(formattedItems).toEqual([
|
|
58
|
+
{ text: 'Option 1', value: 'Option 1' },
|
|
59
|
+
{ text: 'Option 2', value: 'Option 2' },
|
|
60
|
+
])
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('applies the correct button class when outlined is true', () => {
|
|
64
|
+
const wrapper = mount(SyInputSelect, {
|
|
65
|
+
props: { outlined: true },
|
|
66
|
+
global: {
|
|
67
|
+
plugins: [vuetify],
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
expect(wrapper.find('.sy-input-select').classes()).toContain('v-btn--variant-outlined')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('toggles the menu when the button is clicked', async () => {
|
|
74
|
+
const wrapper = mount(SyInputSelect, {
|
|
75
|
+
global: {
|
|
76
|
+
plugins: [vuetify],
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
const button = wrapper.find('.sy-input-select')
|
|
80
|
+
await button.trigger('click')
|
|
81
|
+
expect(wrapper.vm.isOpen).toBe(true)
|
|
82
|
+
await button.trigger('click')
|
|
83
|
+
expect(wrapper.vm.isOpen).toBe(false)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('use closeList method', async () => {
|
|
87
|
+
const wrapper = mount(SyInputSelect, {
|
|
88
|
+
global: {
|
|
89
|
+
plugins: [vuetify],
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
await wrapper.vm.closeList()
|
|
93
|
+
expect(wrapper.vm.isOpen).toBe(false)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('selectItem method', async () => {
|
|
97
|
+
const wrapper = mount(SyInputSelect, {
|
|
98
|
+
global: {
|
|
99
|
+
plugins: [vuetify],
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
await wrapper.vm.selectItem({ text: 'Option 1', value: '1' })
|
|
103
|
+
expect(wrapper.vm.isOpen).toBe(false)
|
|
104
|
+
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 1', value: '1' })
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('getItemText method', async () => {
|
|
108
|
+
const wrapper = mount(SyInputSelect, {
|
|
109
|
+
global: {
|
|
110
|
+
plugins: [vuetify],
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
const item = { text: 'Option 1', value: '1' }
|
|
114
|
+
const text = wrapper.vm.getItemText(item)
|
|
115
|
+
expect(text).toBe('Option 1')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('watch modelValue', async () => {
|
|
119
|
+
const wrapper = mount(SyInputSelect, {
|
|
120
|
+
props: { modelValue: { text: 'Option 1', value: '1' } },
|
|
121
|
+
global: {
|
|
122
|
+
plugins: [vuetify],
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 1', value: '1' })
|
|
126
|
+
await wrapper.setProps({ modelValue: { text: 'Option 2', value: '2' } })
|
|
127
|
+
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 2', value: '2' })
|
|
128
|
+
})
|
|
61
129
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
130
|
+
it('watch errorMessages', async () => {
|
|
131
|
+
const wrapper = mount(SyInputSelect, {
|
|
132
|
+
props: { errorMessages: ['Error message'] },
|
|
133
|
+
global: {
|
|
134
|
+
plugins: [vuetify],
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(true)
|
|
138
|
+
await wrapper.setProps({ errorMessages: [] })
|
|
139
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
68
140
|
})
|
|
69
|
-
expect(wrapper.find('.sy-input-select').classes()).toContain('v-btn--variant-outlined')
|
|
70
141
|
})
|
|
71
142
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
143
|
+
describe('Validation', () => {
|
|
144
|
+
it('validateField valide correctement un champ requis avec une valeur', async () => {
|
|
145
|
+
const wrapper = mount(SyInputSelect, {
|
|
146
|
+
props: {
|
|
147
|
+
required: true,
|
|
148
|
+
modelValue: { text: 'Option 1', value: '1' },
|
|
149
|
+
},
|
|
150
|
+
global: {
|
|
151
|
+
plugins: [vuetify],
|
|
152
|
+
},
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const result = wrapper.vm.validateField({ text: 'Option 1', value: '1' })
|
|
156
|
+
expect(result).toBe(true)
|
|
157
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('validateField échoue pour un champ requis sans valeur', async () => {
|
|
161
|
+
const wrapper = mount(SyInputSelect, {
|
|
162
|
+
props: {
|
|
163
|
+
required: true,
|
|
164
|
+
label: 'Test Label',
|
|
165
|
+
errorMessages: [],
|
|
166
|
+
},
|
|
167
|
+
global: {
|
|
168
|
+
plugins: [vuetify],
|
|
169
|
+
},
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const result = wrapper.vm.validateField(null)
|
|
173
|
+
expect(result).toBe(false)
|
|
174
|
+
|
|
175
|
+
await wrapper.setProps({ errorMessages: ['Test Label est requis'] })
|
|
176
|
+
await wrapper.vm.$nextTick()
|
|
177
|
+
|
|
178
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(true)
|
|
179
|
+
expect(wrapper.find('.v-messages__message').text()).toContain('Test Label est requis')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('validateOnSubmit retourne le résultat de validation', async () => {
|
|
183
|
+
const wrapper = mount(SyInputSelect, {
|
|
184
|
+
props: { required: true },
|
|
185
|
+
global: {
|
|
186
|
+
plugins: [vuetify],
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const result = wrapper.vm.validateOnSubmit()
|
|
191
|
+
expect(result).toBe(false)
|
|
192
|
+
|
|
193
|
+
await wrapper.setProps({ modelValue: { text: 'Option 1', value: '1' } })
|
|
194
|
+
const resultWithValue = wrapper.vm.validateOnSubmit()
|
|
195
|
+
expect(resultWithValue).toBe(true)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('vérifie que checkForErrors retourne le résultat de la validation', () => {
|
|
199
|
+
const wrapper1 = mount(SyInputSelect, {
|
|
200
|
+
props: {
|
|
201
|
+
required: true,
|
|
202
|
+
modelValue: null,
|
|
203
|
+
},
|
|
204
|
+
global: {
|
|
205
|
+
plugins: [vuetify],
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
const result1 = wrapper1.vm.checkForErrors()
|
|
210
|
+
expect(result1).toBe(false)
|
|
211
|
+
|
|
212
|
+
const wrapper2 = mount(SyInputSelect, {
|
|
213
|
+
props: {
|
|
214
|
+
required: true,
|
|
215
|
+
modelValue: { text: 'Option 1', value: '1' },
|
|
216
|
+
},
|
|
217
|
+
global: {
|
|
218
|
+
plugins: [vuetify],
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const result2 = wrapper2.vm.checkForErrors()
|
|
223
|
+
expect(result2).toBe(true)
|
|
224
|
+
})
|
|
83
225
|
})
|
|
84
226
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
227
|
+
describe('Mode readonly', () => {
|
|
228
|
+
it('désactive la validation en mode readonly', () => {
|
|
229
|
+
const wrapper = mount(SyInputSelect, {
|
|
230
|
+
props: {
|
|
231
|
+
readonly: true,
|
|
232
|
+
required: true,
|
|
233
|
+
},
|
|
234
|
+
global: {
|
|
235
|
+
plugins: [vuetify],
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const result = wrapper.vm.validateField(null)
|
|
240
|
+
expect(result).toBe(true)
|
|
241
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it('empêche l\'ouverture du menu en mode readonly', async () => {
|
|
245
|
+
const wrapper = mount(SyInputSelect, {
|
|
246
|
+
props: { readonly: true },
|
|
247
|
+
global: {
|
|
248
|
+
plugins: [vuetify],
|
|
249
|
+
},
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
const button = wrapper.find('.sy-input-select')
|
|
253
|
+
await button.trigger('click')
|
|
254
|
+
expect(wrapper.vm.isOpen).toBe(false)
|
|
90
255
|
})
|
|
91
|
-
await wrapper.vm.closeList()
|
|
92
|
-
expect(wrapper.vm.isOpen).toBe(false)
|
|
93
256
|
})
|
|
94
257
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
258
|
+
describe('Option clearable', () => {
|
|
259
|
+
it('affiche l\'icône de suppression quand clearable est true et une valeur est sélectionnée', async () => {
|
|
260
|
+
const wrapper = mount(SyInputSelect, {
|
|
261
|
+
props: {
|
|
262
|
+
clearable: true,
|
|
263
|
+
modelValue: { text: 'Option 1', value: '1' },
|
|
264
|
+
},
|
|
265
|
+
global: {
|
|
266
|
+
plugins: [vuetify],
|
|
267
|
+
},
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const clearIcon = wrapper.find('.sy-input-select .v-icon[aria-label="Supprimer"]')
|
|
271
|
+
expect(clearIcon.exists()).toBe(true)
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('n\'affiche pas l\'icône de suppression quand clearable est false', async () => {
|
|
275
|
+
const wrapper = mount(SyInputSelect, {
|
|
276
|
+
props: {
|
|
277
|
+
clearable: false,
|
|
278
|
+
modelValue: { text: 'Option 1', value: '1' },
|
|
279
|
+
},
|
|
280
|
+
global: {
|
|
281
|
+
plugins: [vuetify],
|
|
282
|
+
},
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
const clearIcon = wrapper.find('.sy-input-select .v-icon[aria-label="Supprimer"]')
|
|
286
|
+
expect(clearIcon.exists()).toBe(false)
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
it('efface la valeur sélectionnée quand l\'icône de suppression est cliquée', async () => {
|
|
290
|
+
const wrapper = mount(SyInputSelect, {
|
|
291
|
+
props: {
|
|
292
|
+
clearable: true,
|
|
293
|
+
modelValue: { text: 'Option 1', value: '1' },
|
|
294
|
+
},
|
|
295
|
+
global: {
|
|
296
|
+
plugins: [vuetify],
|
|
297
|
+
},
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
const clearIcon = wrapper.find('.sy-input-select .v-icon[aria-label="Supprimer"]')
|
|
301
|
+
await clearIcon.trigger('click')
|
|
302
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([null])
|
|
100
303
|
})
|
|
101
|
-
await wrapper.vm.selectItem({ text: 'Option 1', value: '1' })
|
|
102
|
-
expect(wrapper.vm.isOpen).toBe(false)
|
|
103
|
-
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 1', value: '1' })
|
|
104
304
|
})
|
|
105
305
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
306
|
+
describe('Affichage de l\'astérisque', () => {
|
|
307
|
+
it('affiche l\'astérisque quand displayAsterisk et required sont true', () => {
|
|
308
|
+
const wrapper = mount(SyInputSelect, {
|
|
309
|
+
props: {
|
|
310
|
+
displayAsterisk: true,
|
|
311
|
+
required: true,
|
|
312
|
+
label: 'Test Label',
|
|
313
|
+
},
|
|
314
|
+
global: {
|
|
315
|
+
plugins: [vuetify],
|
|
316
|
+
},
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
const html = wrapper.html()
|
|
320
|
+
expect(html).toContain('Test Label *')
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('n\'affiche pas l\'astérisque quand displayAsterisk est false', () => {
|
|
324
|
+
const wrapper = mount(SyInputSelect, {
|
|
325
|
+
props: {
|
|
326
|
+
displayAsterisk: false,
|
|
327
|
+
required: true,
|
|
328
|
+
label: 'Test Label',
|
|
329
|
+
},
|
|
330
|
+
global: {
|
|
331
|
+
plugins: [vuetify],
|
|
332
|
+
},
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
const html = wrapper.html()
|
|
336
|
+
expect(html).not.toContain('Test Label *')
|
|
337
|
+
expect(html).toContain('Test Label')
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
it('n\'affiche pas l\'astérisque quand required est false', () => {
|
|
341
|
+
const wrapper = mount(SyInputSelect, {
|
|
342
|
+
props: {
|
|
343
|
+
displayAsterisk: true,
|
|
344
|
+
required: false,
|
|
345
|
+
label: 'Test Label',
|
|
346
|
+
},
|
|
347
|
+
global: {
|
|
348
|
+
plugins: [vuetify],
|
|
349
|
+
},
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
const html = wrapper.html()
|
|
353
|
+
expect(html).not.toContain('Test Label *')
|
|
354
|
+
expect(html).toContain('Test Label')
|
|
111
355
|
})
|
|
112
|
-
const item = { text: 'Option 1', value: '1' }
|
|
113
|
-
const text = wrapper.vm.getItemText(item)
|
|
114
|
-
expect(text).toBe('Option 1')
|
|
115
356
|
})
|
|
116
357
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
358
|
+
describe('Événements émis', () => {
|
|
359
|
+
it('émet update:modelValue lors de la sélection d\'un élément', async () => {
|
|
360
|
+
const wrapper = mount(SyInputSelect, {
|
|
361
|
+
props: {
|
|
362
|
+
items: [{ text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }],
|
|
363
|
+
},
|
|
364
|
+
global: {
|
|
365
|
+
plugins: [vuetify],
|
|
366
|
+
},
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
await wrapper.vm.selectItem({ text: 'Option 1', value: '1' })
|
|
370
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([{ text: 'Option 1', value: '1' }])
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
it('émet update:errorMessages après validation', async () => {
|
|
374
|
+
const wrapper = mount(SyInputSelect, {
|
|
375
|
+
props: {
|
|
376
|
+
required: true,
|
|
377
|
+
label: 'Test Label',
|
|
378
|
+
},
|
|
379
|
+
global: {
|
|
380
|
+
plugins: [vuetify],
|
|
381
|
+
},
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
await wrapper.vm.validateField(null)
|
|
385
|
+
await wrapper.vm.selectItem(null)
|
|
386
|
+
|
|
387
|
+
expect(wrapper.emitted('update:errorMessages')).toBeTruthy()
|
|
388
|
+
expect(wrapper.emitted('update:errorMessages')?.[0][0]).toContainEqual(expect.stringContaining('Test Label est requis'))
|
|
123
389
|
})
|
|
124
|
-
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 1', value: '1' })
|
|
125
|
-
await wrapper.setProps({ modelValue: { text: 'Option 2', value: '2' } })
|
|
126
|
-
expect(wrapper.vm.selectedItem).toEqual({ text: 'Option 2', value: '2' })
|
|
127
390
|
})
|
|
128
391
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
392
|
+
describe('Comportement du menu', () => {
|
|
393
|
+
it('ouvre le menu quand on clique sur le bouton', async () => {
|
|
394
|
+
const wrapper = mount(SyInputSelect, {
|
|
395
|
+
global: {
|
|
396
|
+
plugins: [vuetify],
|
|
397
|
+
},
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
const button = wrapper.find('.sy-input-select')
|
|
401
|
+
await button.trigger('click')
|
|
402
|
+
|
|
403
|
+
expect(wrapper.find('.v-list').exists()).toBe(true)
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
it('applique des styles différents pour isHeaderToolbar', async () => {
|
|
407
|
+
const wrapper = mount(SyInputSelect, {
|
|
408
|
+
props: { isHeaderToolbar: true },
|
|
409
|
+
global: {
|
|
410
|
+
plugins: [vuetify],
|
|
411
|
+
},
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
const button = wrapper.find('.sy-input-select')
|
|
415
|
+
await button.trigger('click')
|
|
416
|
+
|
|
417
|
+
expect(wrapper.find('.v-list').attributes('is-header-toolbar')).toBeTruthy()
|
|
135
418
|
})
|
|
136
|
-
expect(wrapper.find('.v-messages__message').exists()).toBe(true)
|
|
137
|
-
await wrapper.setProps({ errorMessages: [] })
|
|
138
|
-
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
139
419
|
})
|
|
140
420
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import SySelect from '@/components/Customs/SySelect/SySelect.vue'
|
|
3
3
|
import SyAlert from '@/components/SyAlert/SyAlert.vue'
|
|
4
|
-
import { VBtn, VMenu, VList, VListItem, VListItemTitle } from 'vuetify/components'
|
|
4
|
+
import { VBtn, VMenu, VList, VListItem, VListItemTitle, VForm } from 'vuetify/components'
|
|
5
5
|
import { ref } from 'vue'
|
|
6
6
|
import { fn } from '@storybook/test'
|
|
7
7
|
|
|
@@ -34,6 +34,19 @@ const meta: Meta<typeof SySelect> = {
|
|
|
34
34
|
control: 'boolean',
|
|
35
35
|
description: 'Permet de vider la sélection',
|
|
36
36
|
},
|
|
37
|
+
hideMessages: {
|
|
38
|
+
control: 'boolean',
|
|
39
|
+
description: 'Masque les messages d\'erreur',
|
|
40
|
+
},
|
|
41
|
+
density: {
|
|
42
|
+
control: 'select',
|
|
43
|
+
options: ['default', 'comfortable', 'compact'],
|
|
44
|
+
description: 'Définit la densité du champ de sélection',
|
|
45
|
+
},
|
|
46
|
+
width: {
|
|
47
|
+
control: 'text',
|
|
48
|
+
description: 'Permet de définir une largeur personnalisée pour le champ de sélection (en px)',
|
|
49
|
+
},
|
|
37
50
|
},
|
|
38
51
|
} as Meta<typeof SySelect>
|
|
39
52
|
|
|
@@ -361,9 +374,115 @@ export const Info: Story = {
|
|
|
361
374
|
<li>- Si les items sont un tableau de string, le composant les utilisera directement.</li>
|
|
362
375
|
</ul>
|
|
363
376
|
</template>
|
|
364
|
-
|
|
377
|
+
</SyAlert>
|
|
365
378
|
`,
|
|
366
379
|
}
|
|
367
380
|
},
|
|
368
381
|
tags: ['!dev'],
|
|
369
382
|
}
|
|
383
|
+
|
|
384
|
+
export const FormValidation: Story = {
|
|
385
|
+
parameters: {
|
|
386
|
+
docs: {
|
|
387
|
+
description: {
|
|
388
|
+
story: 'Exemple d\'utilisation du SySelect dans un formulaire.',
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
sourceCode: [
|
|
392
|
+
{
|
|
393
|
+
name: 'Template',
|
|
394
|
+
code: `
|
|
395
|
+
<template>
|
|
396
|
+
<VForm @submit.prevent="submitForm">
|
|
397
|
+
<SySelect
|
|
398
|
+
v-model="formData.option"
|
|
399
|
+
:items="options"
|
|
400
|
+
label="Option"
|
|
401
|
+
required
|
|
402
|
+
display-asterisk
|
|
403
|
+
class="mb-4"
|
|
404
|
+
/>
|
|
405
|
+
<VBtn
|
|
406
|
+
type="submit"
|
|
407
|
+
color="primary"
|
|
408
|
+
class="mt-4"
|
|
409
|
+
>
|
|
410
|
+
Soumettre
|
|
411
|
+
</VBtn>
|
|
412
|
+
</VForm>
|
|
413
|
+
</template>
|
|
414
|
+
`,
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: 'Script',
|
|
418
|
+
code: `
|
|
419
|
+
<script setup lang="ts">
|
|
420
|
+
import { ref } from 'vue'
|
|
421
|
+
import SySelect from '@cnamts/synapse'
|
|
422
|
+
import { VBtn, VForm } from 'vuetify/components'
|
|
423
|
+
|
|
424
|
+
const formData = ref({
|
|
425
|
+
option: ''
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
const options = [
|
|
429
|
+
{ text: 'Option 1', value: '1' },
|
|
430
|
+
{ text: 'Option 2', value: '2' },
|
|
431
|
+
{ text: 'Option 3', value: '3' },
|
|
432
|
+
]
|
|
433
|
+
|
|
434
|
+
const submitForm = () => {
|
|
435
|
+
// Traitement du formulaire
|
|
436
|
+
console.log('Formulaire soumis:', formData.value)
|
|
437
|
+
}
|
|
438
|
+
</script>
|
|
439
|
+
`,
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
args: {
|
|
444
|
+
'items': [
|
|
445
|
+
{ text: 'Option 1', value: '1' },
|
|
446
|
+
{ text: 'Option 2', value: '2' },
|
|
447
|
+
{ text: 'Option 3', value: '3' },
|
|
448
|
+
],
|
|
449
|
+
'label': 'Option',
|
|
450
|
+
'required': true,
|
|
451
|
+
'displayAsterisk': true,
|
|
452
|
+
'onUpdate:modelValue': fn(),
|
|
453
|
+
},
|
|
454
|
+
render: (args) => {
|
|
455
|
+
return {
|
|
456
|
+
components: { SySelect, VBtn, VForm },
|
|
457
|
+
setup() {
|
|
458
|
+
const formData = ref({
|
|
459
|
+
option: '',
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
const submitForm = () => {
|
|
463
|
+
console.log('Formulaire soumis:', formData.value)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return { args, formData, submitForm }
|
|
467
|
+
},
|
|
468
|
+
template: `
|
|
469
|
+
<div class="pa-4">
|
|
470
|
+
<VForm @submit.prevent="submitForm">
|
|
471
|
+
<SySelect
|
|
472
|
+
v-model="formData.option"
|
|
473
|
+
v-bind="args"
|
|
474
|
+
class="mb-4"
|
|
475
|
+
/>
|
|
476
|
+
<VBtn
|
|
477
|
+
type="submit"
|
|
478
|
+
color="primary"
|
|
479
|
+
class="mt-4"
|
|
480
|
+
>
|
|
481
|
+
Soumettre
|
|
482
|
+
</VBtn>
|
|
483
|
+
</VForm>
|
|
484
|
+
</div>
|
|
485
|
+
`,
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
}
|