import { mount } from '@vue/test-utils' import { describe, it, expect } from 'vitest' import { nextTick } from 'vue' import SyCheckbox from '../SyCheckbox.vue' describe('SyCheckbox', () => { it('should render correctly', () => { const wrapper = mount(SyCheckbox, { props: { label: 'Test checkbox', }, }) expect(wrapper.find('.v-checkbox').exists()).toBe(true) expect(wrapper.text()).toContain('Test checkbox') }) it('should handle v-model correctly', async () => { const wrapper = mount(SyCheckbox, { props: { 'modelValue': false, 'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }), }, }) await wrapper.find('input[type="checkbox"]').setValue(true) expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([true]) expect(wrapper.emitted('change')?.[0]).toEqual([true]) }) it('should handle indeterminate state correctly', async () => { const wrapper = mount(SyCheckbox, { props: { 'modelValue': false, 'indeterminate': true, 'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }), 'onUpdate:indeterminate': e => wrapper.setProps({ indeterminate: e }), }, }) // Vérifier que l'état indéterminé est actif expect(wrapper.props('indeterminate')).toBe(true) // Cliquer sur la case à cocher devrait changer l'état indéterminé à checked await wrapper.find('.v-selection-control').trigger('click') expect(wrapper.emitted('update:indeterminate')?.[0]).toEqual([false]) expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([true]) }) it('should toggle between states correctly', async () => { // Monter le composant avec des handlers pour les événements const wrapper = mount(SyCheckbox, { props: { modelValue: false, controlsIds: ['child-1', 'child-2'], }, }) // État initial: non coché expect(wrapper.props('modelValue')).toBe(false) // Premier toggle: passe à indéterminé (car controlsIds est défini) await wrapper.vm.toggleMixed() await nextTick() // Vérifier que l'événement update:indeterminate a été émis const indeterminateEvents = wrapper.emitted('update:indeterminate') expect(indeterminateEvents).toBeTruthy() expect(indeterminateEvents && indeterminateEvents[0]).toEqual([true]) // Simuler la mise à jour des props par le parent await wrapper.setProps({ indeterminate: true, modelValue: false, }) // Deuxième toggle: passe à coché await wrapper.vm.toggleMixed() await nextTick() // Vérifier que les événements ont été émis const updatedIndeterminateEvents = wrapper.emitted('update:indeterminate') const modelValueEvents = wrapper.emitted('update:modelValue') expect(updatedIndeterminateEvents && updatedIndeterminateEvents[1]).toEqual([false]) expect(modelValueEvents).toBeTruthy() expect(modelValueEvents && modelValueEvents[0]).toEqual([true]) // Simuler la mise à jour des props par le parent await wrapper.setProps({ indeterminate: false, modelValue: true, }) // Troisième toggle: passe à non coché await wrapper.vm.toggleMixed() await nextTick() // Vérifier que l'événement update:modelValue a été émis avec false const finalModelValueEvents = wrapper.emitted('update:modelValue') expect(finalModelValueEvents && finalModelValueEvents[1]).toEqual([false]) }) it('should handle validation correctly', async () => { const wrapper = mount(SyCheckbox, { props: { 'modelValue': false, 'label': 'Required checkbox', 'required': true, 'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }), }, }) // Simuler un événement blur pour déclencher la validation await wrapper.find('.v-checkbox').trigger('blur') // Vérifier que le message d'erreur est affiché expect(wrapper.find('.v-messages').exists()).toBe(true) expect(wrapper.find('.v-messages').text()).toContain('Required checkbox est requis') }) it('should handle custom validation rules', async () => { // Créer une règle de validation au format attendu par le composant const customRule = { type: 'custom', options: { validate: (value: boolean) => value === true, message: 'This checkbox must be checked', fieldIdentifier: 'Custom checkbox', }, } // Monter le composant avec la règle de validation personnalisée const wrapper = mount(SyCheckbox, { props: { 'modelValue': false, 'customRules': [customRule], 'isValidateOnBlur': false, // Valider immédiatement 'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }), }, }) // Vérifier l'état initial expect(wrapper.props('modelValue')).toBe(false) // Simuler la validation du formulaire const isValid = await wrapper.vm.validateOnSubmit() await wrapper.vm.$nextTick() // La validation devrait échouer car la case n'est pas cochée expect(isValid).toBe(false) // Cocher la case await wrapper.setProps({ modelValue: true }) // Simuler à nouveau la validation du formulaire const isValidAfterCheck = await wrapper.vm.validateOnSubmit() await wrapper.vm.$nextTick() // La validation devrait réussir maintenant expect(isValidAfterCheck).toBe(true) }) it('should handle readonly and disabled states', async () => { const wrapper = mount(SyCheckbox, { props: { 'modelValue': false, 'readonly': true, 'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }), }, }) // Cliquer sur une case à cocher en lecture seule ne devrait pas changer sa valeur await wrapper.find('.v-checkbox').trigger('click') expect(wrapper.emitted('update:modelValue')).toBeFalsy() // Tester l'état désactivé await wrapper.setProps({ readonly: false, disabled: true }) await wrapper.find('.v-checkbox').trigger('click') expect(wrapper.emitted('update:modelValue')).toBeFalsy() }) })