fix(input) : InputAutocomplete garde la valeur collée après sélection (MUI-48) (#87)
## Contexte — MUI-48 « Le champ adresse disparaît après un copier-coller » (Malio UI, bug frontend). ## Repro exacte 1. Taper une adresse, **sélectionner une suggestion** dans la liste. 2. Sans re-cliquer dans le champ : `Ctrl+A` puis `Ctrl+V` pour remplacer. 3. → Le champ se **vide** (label qui redescend, dropdown « Tapez pour rechercher »), la valeur collée est perdue. À la souris (re-clic dans le champ) le bug ne se produit pas. ## Cause racine `onSelect` repassait `isFocused` à `false` alors que l'input **garde le focus DOM** (l'option est cliquée en `mousedown.prevent`). Au collage, `onInput` émet `update:modelValue(null)` ; le `watch` de synchronisation, protégé par le seul `isFocused`, remettait alors `inputValue` à `''`. ## Correctif `onInput` resynchronise `isFocused = true` : recevoir un évènement `input` prouve que le champ est en cours d'édition. Le `watch` se protège correctement et ne stompe plus la valeur collée. Correctif d'une ligne, au point exact de la cause. ## Tests / vérifs - Test de non-régression colocalisé (séquence sélection → `Ctrl+A`/`Ctrl+V`) — échoue sans le fix, passe avec. - Suite complète : **1057/1057** tests OK, lint sans erreur. - Page playground : nouvelle section **allowCreate + BAN** dédiée au test manuel. - `CHANGELOG.md` : entrée `Fixed` MUI-48. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #87 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #87.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import {describe, expect, it, vi} from 'vitest'
|
||||
import {mount} from '@vue/test-utils'
|
||||
import type {DefineComponent} from 'vue'
|
||||
import {defineComponent, nextTick, ref, type DefineComponent} from 'vue'
|
||||
import {Icon as IconifyIcon} from '@iconify/vue'
|
||||
import InputAutocomplete from './InputAutocomplete.vue'
|
||||
|
||||
@@ -569,4 +569,40 @@ describe('MalioInputAutocomplete', () => {
|
||||
expect(msg.exists()).toBe(true)
|
||||
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||
})
|
||||
|
||||
// MUI-48 : après avoir sélectionné une option dans la liste, le champ garde le focus DOM
|
||||
// mais isFocused interne passe à false (clic option en mousedown.prevent). Un collage qui
|
||||
// remplace tout (Ctrl+A puis Ctrl+V) déclenche update:modelValue(null) ; le watch ne doit
|
||||
// PAS vider la valeur collée. Régression : le champ se vidait au lieu de prendre le texte collé.
|
||||
it('MUI-48 : un collage après sélection dans la liste remplace la valeur (ne la vide pas)', async () => {
|
||||
const Harness = defineComponent({
|
||||
components: {InputAutocomplete},
|
||||
setup() {
|
||||
const val = ref<string | number | null>(null)
|
||||
const opts = ref([{label: '10 Rue de la Paix', value: '10 Rue de la Paix'}])
|
||||
return {val, opts}
|
||||
},
|
||||
template: '<InputAutocomplete v-model="val" :options="opts" allow-create />',
|
||||
})
|
||||
|
||||
const wrapper = mount(Harness, {
|
||||
attachTo: document.body,
|
||||
global: {stubs: {IconifyIcon: {template: '<span data-test="icon" v-bind="$attrs" />'}}},
|
||||
})
|
||||
const input = wrapper.get('input')
|
||||
|
||||
// saisie puis sélection d'une suggestion (commit, focus DOM conservé)
|
||||
await input.trigger('focus')
|
||||
await input.setValue('10')
|
||||
await wrapper.findAll('[data-test="option"]')[0].trigger('click')
|
||||
await nextTick()
|
||||
expect(input.element.value).toBe('10 Rue de la Paix')
|
||||
|
||||
// Ctrl+A puis Ctrl+V : input toujours focalisé DOM, aucun nouvel évènement focus
|
||||
await input.setValue('25 Avenue Victor Hugo')
|
||||
await nextTick()
|
||||
|
||||
expect(input.element.value).toBe('25 Avenue Victor Hugo')
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user