feat(radio) : contexte de groupe injectable pour RadioButton
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import {describe, expect, it} from 'vitest'
|
||||
import {computed, ref} from 'vue'
|
||||
import {describe, expect, it, vi} from 'vitest'
|
||||
import {mount} from '@vue/test-utils'
|
||||
import type {DefineComponent} from 'vue'
|
||||
import RadioButton from './RadioButton.vue'
|
||||
import {radioGroupContextKey, type RadioGroupContext, type RadioValue} from './context'
|
||||
|
||||
type RadioButtonProps = {
|
||||
id?: string
|
||||
@@ -193,3 +195,67 @@ describe('MalioRadioButton', () => {
|
||||
expect(wrapper.get('.radio-text').classes()).toContain('text-black')
|
||||
})
|
||||
})
|
||||
|
||||
const makeGroupCtx = (over: Partial<{
|
||||
selected: RadioValue; error: boolean; success: boolean
|
||||
disabled: boolean; readonly: boolean; required: boolean
|
||||
}> = {}) => {
|
||||
const selected = ref<RadioValue>(over.selected ?? null)
|
||||
const select = vi.fn((v: RadioValue) => { selected.value = v })
|
||||
const ctx: RadioGroupContext = {
|
||||
name: computed(() => 'grp'),
|
||||
isSelected: (v) => selected.value === v,
|
||||
select,
|
||||
hasError: computed(() => !!over.error),
|
||||
hasSuccess: computed(() => !!over.success),
|
||||
disabled: computed(() => !!over.disabled),
|
||||
readonly: computed(() => !!over.readonly),
|
||||
required: computed(() => !!over.required),
|
||||
describedBy: computed(() => 'grp-describedby'),
|
||||
}
|
||||
return {ctx, select, selected}
|
||||
}
|
||||
|
||||
const mountInGroup = (props: RadioButtonProps, ctx: RadioGroupContext) =>
|
||||
mount(RadioButtonForTest, {
|
||||
props,
|
||||
global: {provide: {[radioGroupContextKey as symbol]: ctx}},
|
||||
})
|
||||
|
||||
describe('MalioRadioButton dans un groupe', () => {
|
||||
it('hérite du name du groupe', () => {
|
||||
const {ctx} = makeGroupCtx()
|
||||
const wrapper = mountInGroup({value: 'a', label: 'A'}, ctx)
|
||||
expect(wrapper.get('input').attributes('name')).toBe('grp')
|
||||
})
|
||||
|
||||
it('coché selon isSelected du groupe', () => {
|
||||
const {ctx} = makeGroupCtx({selected: 'a'})
|
||||
const wrapper = mountInGroup({value: 'a', label: 'A'}, ctx)
|
||||
expect((wrapper.get('input').element as HTMLInputElement).checked).toBe(true)
|
||||
})
|
||||
|
||||
it('appelle ctx.select au change au lieu d\'émettre', async () => {
|
||||
const {ctx, select} = makeGroupCtx()
|
||||
const wrapper = mountInGroup({value: 'b', label: 'B'}, ctx)
|
||||
await wrapper.get('input').trigger('change')
|
||||
expect(select).toHaveBeenCalledWith('b')
|
||||
expect(wrapper.emitted('update:modelValue')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('reflète l\'erreur du groupe et ne rend aucun message propre', () => {
|
||||
const {ctx} = makeGroupCtx({error: true})
|
||||
const wrapper = mountInGroup({value: 'a', label: 'A', hint: 'ignoré'}, ctx)
|
||||
expect(wrapper.get('.radio-control').classes()).toContain('is-error')
|
||||
expect(wrapper.get('input').attributes('aria-invalid')).toBe('true')
|
||||
expect(wrapper.find('.radio-message').exists()).toBe(false)
|
||||
expect(wrapper.get('input').attributes('aria-describedby')).toBe('grp-describedby')
|
||||
})
|
||||
|
||||
it('hérite de disabled/required du groupe', () => {
|
||||
const {ctx} = makeGroupCtx({disabled: true, required: true})
|
||||
const wrapper = mountInGroup({value: 'a', label: 'A'}, ctx)
|
||||
expect(wrapper.get('input').attributes('disabled')).toBeDefined()
|
||||
expect(wrapper.get('input').attributes('required')).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user