feat(inputs) : sanitisation email (suppression des espaces + option lowercase)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ type InputEmailProps = {
|
|||||||
iconPosition?: 'left' | 'right'
|
iconPosition?: 'left' | 'right'
|
||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
|
lowercase?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputEmailForTest = InputEmail as DefineComponent<InputEmailProps>
|
const InputEmailForTest = InputEmail as DefineComponent<InputEmailProps>
|
||||||
@@ -235,4 +236,26 @@ describe('MalioInputEmail', () => {
|
|||||||
|
|
||||||
expect(wrapper.get('input').attributes('autocomplete')).toBe('email')
|
expect(wrapper.get('input').attributes('autocomplete')).toBe('email')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('supprime tous les espaces saisis', async () => {
|
||||||
|
const wrapper = mountComponent()
|
||||||
|
await wrapper.get('input').setValue(' a b @ c.com ')
|
||||||
|
const emits = wrapper.emitted('update:modelValue')!
|
||||||
|
expect(emits[emits.length - 1]).toEqual(['ab@c.com'])
|
||||||
|
expect(wrapper.get('input').element.value).toBe('ab@c.com')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('conserve la casse par défaut', async () => {
|
||||||
|
const wrapper = mountComponent()
|
||||||
|
await wrapper.get('input').setValue('User@Example.COM')
|
||||||
|
const emits = wrapper.emitted('update:modelValue')!
|
||||||
|
expect(emits[emits.length - 1]).toEqual(['User@Example.COM'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('met en minuscules quand lowercase est vrai', async () => {
|
||||||
|
const wrapper = mountComponent({lowercase: true})
|
||||||
|
await wrapper.get('input').setValue('User@Example.COM')
|
||||||
|
const emits = wrapper.emitted('update:modelValue')!
|
||||||
|
expect(emits[emits.length - 1]).toEqual(['user@example.com'])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ const props = withDefaults(
|
|||||||
iconPosition?: 'left' | 'right'
|
iconPosition?: 'left' | 'right'
|
||||||
iconSize?: string | number
|
iconSize?: string | number
|
||||||
iconColor?: string
|
iconColor?: string
|
||||||
|
lowercase?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
@@ -106,6 +107,7 @@ const props = withDefaults(
|
|||||||
success: '',
|
success: '',
|
||||||
iconSize: 24,
|
iconSize: 24,
|
||||||
iconColor: 'text-m-muted',
|
iconColor: 'text-m-muted',
|
||||||
|
lowercase: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -170,12 +172,36 @@ const emit = defineEmits<{
|
|||||||
(event: 'update:modelValue', value: string): void
|
(event: 'update:modelValue', value: string): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const sanitizeEmail = (v: string) => {
|
||||||
|
let out = v.replace(/\s+/g, '')
|
||||||
|
if (props.lowercase) out = out.toLowerCase()
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
const onInput = (event: Event) => {
|
const onInput = (event: Event) => {
|
||||||
const target = event.target as HTMLInputElement
|
const target = event.target as HTMLInputElement
|
||||||
if (!isControlled.value) {
|
const raw = target.value
|
||||||
localValue.value = target.value
|
const sanitized = sanitizeEmail(raw)
|
||||||
|
|
||||||
|
if (sanitized !== raw) {
|
||||||
|
// `<input type="email">` ne supporte pas l'API de sélection :
|
||||||
|
// selectionStart vaut null, setSelectionRange lève. On garde défensivement.
|
||||||
|
const caret = target.selectionStart
|
||||||
|
target.value = sanitized
|
||||||
|
if (caret !== null) {
|
||||||
|
const newCaret = sanitizeEmail(raw.slice(0, caret)).length
|
||||||
|
try {
|
||||||
|
target.setSelectionRange(newCaret, newCaret)
|
||||||
|
} catch {
|
||||||
|
/* type d'input sans support de sélection — ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit('update:modelValue', target.value)
|
|
||||||
|
if (!isControlled.value) {
|
||||||
|
localValue.value = sanitized
|
||||||
|
}
|
||||||
|
emit('update:modelValue', sanitized)
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconInputPaddingClass = computed(() => {
|
const iconInputPaddingClass = computed(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user