fix: readonly component style + TabList + required component (#61)
Release / release (push) Successful in 1m24s
Release / release (push) Successful in 1m24s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié --------- Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-authored-by: matthieu <matthieu@yuno.malio.fr> Reviewed-on: #61 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #61.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {describe, expect, it} from 'vitest'
|
||||
import {mount} from '@vue/test-utils'
|
||||
import {mount, renderToString} from '@vue/test-utils'
|
||||
import type {DefineComponent} from 'vue'
|
||||
import SelectCheckbox from './SelectCheckbox.vue'
|
||||
|
||||
@@ -9,7 +9,7 @@ type Option = {
|
||||
}
|
||||
|
||||
type SelectCheckboxProps = {
|
||||
modelValue: Array<string | number>
|
||||
modelValue?: Array<string | number>
|
||||
options?: Option[]
|
||||
emptyOptionLabel?: string
|
||||
label?: string
|
||||
@@ -24,7 +24,10 @@ type SelectCheckboxProps = {
|
||||
displaySelectAll?: boolean
|
||||
selectAllLabel?: string
|
||||
disabled?: boolean
|
||||
readonly?: boolean
|
||||
groupClass?: string
|
||||
required?: boolean
|
||||
reserveMessageSpace?: boolean
|
||||
}
|
||||
|
||||
const SelectCheckboxForTest = SelectCheckbox as DefineComponent<SelectCheckboxProps>
|
||||
@@ -36,6 +39,18 @@ const options: Option[] = [
|
||||
]
|
||||
|
||||
describe('MalioSelectCheckbox', () => {
|
||||
it('rend sans planter quand modelValue n’est pas fourni (non contrôlé)', () => {
|
||||
expect(() =>
|
||||
mount(SelectCheckboxForTest, {props: {label: 'Catégories', options}}),
|
||||
).not.toThrow()
|
||||
})
|
||||
|
||||
it('rend en SSR sans planter quand modelValue est absent (cause du crash playground)', async () => {
|
||||
await expect(
|
||||
renderToString(SelectCheckboxForTest, {props: {label: 'Catégories', readonly: true, options}}),
|
||||
).resolves.toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders checkbox inputs for options', async () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], options},
|
||||
@@ -235,6 +250,38 @@ describe('MalioSelectCheckbox', () => {
|
||||
expect(wrapper.get('[data-test="chevron"]').classes()).toContain('text-m-success')
|
||||
})
|
||||
|
||||
it('affiche l\'astérisque quand required est vrai', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], label: 'Champ', required: true},
|
||||
})
|
||||
|
||||
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('n\'affiche pas l\'astérisque par défaut', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], label: 'Champ'},
|
||||
})
|
||||
|
||||
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('expose aria-required quand required est vrai', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], options, required: true},
|
||||
})
|
||||
|
||||
expect(wrapper.find('[aria-required="true"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('n\'expose pas aria-required par défaut', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], options},
|
||||
})
|
||||
|
||||
expect(wrapper.find('[aria-required="true"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('keeps the bottom border allocation when open downward (transparent, not zero)', async () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {modelValue: [], options},
|
||||
@@ -248,4 +295,75 @@ describe('MalioSelectCheckbox', () => {
|
||||
expect(buttonClasses).not.toContain('!border-b-0')
|
||||
expect(buttonClasses).toContain('!border-b-transparent')
|
||||
})
|
||||
|
||||
it('readonly : bordure noire même sans sélection, pas de grow/bleu', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {label: 'Champ', readonly: true, modelValue: [], options: [{label: 'A', value: 'a'}]},
|
||||
})
|
||||
const trigger = wrapper.get('button')
|
||||
expect(trigger.classes()).toContain('border-black')
|
||||
expect(trigger.classes()).not.toContain('border-m-muted')
|
||||
expect(trigger.classes()).not.toContain('grow-height')
|
||||
expect(trigger.classes()).not.toContain('focus-visible:border-m-primary')
|
||||
})
|
||||
|
||||
it('readonly vide : label gris, pas de bleu', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {label: 'Champ', readonly: true, modelValue: [], options: [{label: 'A', value: 'a'}]},
|
||||
})
|
||||
const label = wrapper.get('label')
|
||||
expect(label.classes()).not.toContain('text-m-primary')
|
||||
expect(label.classes()).toContain('text-m-muted')
|
||||
})
|
||||
|
||||
it('readonly sélectionné : label noir + chevron noir', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {label: 'Champ', readonly: true, modelValue: ['a'], options: [{label: 'A', value: 'a'}]},
|
||||
})
|
||||
expect(wrapper.get('label').classes()).toContain('text-black')
|
||||
expect(wrapper.get('[data-test="chevron"]').classes()).toContain('text-black')
|
||||
})
|
||||
|
||||
it('readonly empêche l’ouverture du dropdown', async () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {label: 'Champ', readonly: true, modelValue: [], options: [{label: 'A', value: 'a'}]},
|
||||
})
|
||||
await wrapper.get('button').trigger('click')
|
||||
expect(wrapper.find('[role="listbox"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('readonly expose aria-readonly et reste focusable (pas disabled)', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {
|
||||
props: {label: 'Champ', readonly: true, modelValue: [], options},
|
||||
})
|
||||
const trigger = wrapper.get('button')
|
||||
expect(trigger.attributes('aria-readonly')).toBe('true')
|
||||
expect(trigger.attributes('disabled')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('disabled + readonly : pas d’aria-readonly (disabled prime)', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {props: {modelValue: [], label: 'Champ', disabled: true, readonly: true, options: [{label: 'A', value: 'a'}]}})
|
||||
const trigger = wrapper.get('button')
|
||||
expect(trigger.attributes('aria-readonly')).toBeUndefined()
|
||||
expect(trigger.attributes('disabled')).toBeDefined()
|
||||
})
|
||||
|
||||
it('réserve l’espace message par défaut même sans message', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {props: {label: 'Champ', options}})
|
||||
const msg = wrapper.find('[id$="-describedby"]')
|
||||
expect(msg.exists()).toBe(true)
|
||||
expect(msg.classes()).toContain('min-h-[1rem]')
|
||||
})
|
||||
|
||||
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {props: {label: 'Champ', options, reserveMessageSpace: false}})
|
||||
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
|
||||
const wrapper = mount(SelectCheckboxForTest, {props: {label: 'Champ', options, reserveMessageSpace: false, error: 'Erreur'}})
|
||||
const msg = wrapper.find('[id$="-describedby"]')
|
||||
expect(msg.exists()).toBe(true)
|
||||
expect(msg.classes()).not.toContain('min-h-[1rem]')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user