diff --git a/app/components/malio/input/InputEmail.test.ts b/app/components/malio/input/InputEmail.test.ts index 4809772..96f01f9 100644 --- a/app/components/malio/input/InputEmail.test.ts +++ b/app/components/malio/input/InputEmail.test.ts @@ -258,4 +258,20 @@ describe('MalioInputEmail', () => { const emits = wrapper.emitted('update:modelValue')! expect(emits[emits.length - 1]).toEqual(['user@example.com']) }) + + it('émet la valeur sanitisée en mode contrôlé', async () => { + const wrapper = mountComponent({modelValue: ''}) + await wrapper.get('input').setValue(' a b @ c.com ') + expect(wrapper.emitted('update:modelValue')!.at(-1)).toEqual(['ab@c.com']) + }) + + it('resynchronise le DOM en mode contrôlé même quand la valeur sanitisée égale déjà modelValue', async () => { + // L'utilisateur ajoute un espace en fin alors que la valeur nettoyée vaut déjà modelValue. + // Le parent ne « changera » pas modelValue → Vue ne re-patche pas le DOM ; l'écriture + // manuelle target.value = sanitized est donc indispensable pour retirer l'espace affiché. + const wrapper = mountComponent({modelValue: 'ab@c.com'}) + const input = wrapper.get('input') + await input.setValue('ab@c.com ') + expect(input.element.value).toBe('ab@c.com') + }) }) diff --git a/app/components/malio/input/InputEmail.vue b/app/components/malio/input/InputEmail.vue index 519c802..6586996 100644 --- a/app/components/malio/input/InputEmail.vue +++ b/app/components/malio/input/InputEmail.vue @@ -185,7 +185,8 @@ const onInput = (event: Event) => { if (sanitized !== raw) { // `` ne supporte pas l'API de sélection : - // selectionStart vaut null, setSelectionRange lève. On garde défensivement. + // selectionStart vaut null et setSelectionRange lève en navigateur. + // (En jsdom selectionStart peut renvoyer un nombre, d'où le code gardé ci-dessous.) const caret = target.selectionStart target.value = sanitized if (caret !== null) {