import { nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, test } from 'vitest'
import { ElFormItem } from '@element-plus/components/form'
import Checkbox from '../src/checkbox.vue'
import CheckboxButton from '../src/checkbox-button.vue'
import CheckboxGroup from '../src/checkbox-group.vue'
import type { CheckboxValueType } from '../src/checkbox'
describe('Checkbox', () => {
test('create', async () => {
const checked = ref(false)
const wrapper = mount(() => )
expect(wrapper.classes()).toContain('el-checkbox')
expect(wrapper.classes()).not.toContain('is-disabled')
await wrapper.trigger('click')
expect(wrapper.classes()).toContain('is-checked')
await wrapper.trigger('click')
expect(wrapper.classes('is-checked')).toBe(false)
})
describe('no v-model', () => {
test('checkbox without label', async () => {
const checked = ref(false)
const wrapper = mount(() => )
expect(wrapper.classes('is-checked')).toBe(false)
})
test('checkbox with label attribute', async () => {
const checked = ref(false)
const wrapper = mount(() => (
))
expect(wrapper.classes('is-checked')).toBe(false)
})
})
describe('disabled', () => {
test('checkbox without label', async () => {
const checked = ref(false)
const wrapper = mount(() => (
))
const checkbox = wrapper.findComponent(Checkbox)
expect(checkbox.classes()).toContain('is-disabled')
expect(checked.value).toBe(false)
await checkbox.trigger('click')
await nextTick()
expect(checkbox.classes()).toContain('is-disabled')
expect(checked.value).toBe(false)
})
test('checkbox with label attribute', async () => {
const checked = ref(false)
const wrapper = mount(() => (
))
expect(wrapper.classes()).toContain('is-disabled')
expect(checked.value).toBe(false)
await wrapper.trigger('click')
await nextTick()
expect(wrapper.classes()).toContain('is-disabled')
expect(checked.value).toBe(false)
})
})
describe('change event', () => {
test('checkbox without label', async () => {
const checked = ref(false)
const data = ref()
const onChange = (val: CheckboxValueType) => (data.value = val)
const wrapper = mount(() => (
))
await wrapper.findComponent(Checkbox).trigger('click')
expect(data.value).toBe(true)
})
test('checkbox with label attribute', async () => {
const checked = ref(false)
const data = ref()
const onChange = (val: CheckboxValueType) => (data.value = val)
const wrapper = mount(() => (
))
await wrapper.trigger('click')
expect(data.value).toBe(true)
})
test('checkbox with label as slot content', async () => {
const checked = ref(false)
const data = ref()
const onChange = (val: CheckboxValueType) => (data.value = val)
const wrapper = mount(() => (
Foobar
))
await wrapper.trigger('click')
expect(data.value).toBe(true)
})
})
test('checkbox group', async () => {
const checkList = ref([])
const wrapper = mount({
setup() {
return () => (
)
},
})
expect(checkList.value.length).toBe(0)
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value.length).toBe(1)
expect(checkList.value).toContain('a')
await wrapper.findComponent({ ref: 'b' }).trigger('click')
expect(checkList.value.length).toBe(2)
expect(checkList.value).toContain('a')
expect(checkList.value).toContain('b')
})
test('checkbox group without modelValue', async () => {
const checkList = ref([])
const wrapper = mount({
setup() {
return () => (
)
},
})
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value.length).toBe(1)
expect(checkList.value).toContain('a')
})
test('checkbox group change', async () => {
const checkList = ref([])
const data = ref([])
const onChange = (val: CheckboxValueType[]) => (data.value = val)
const wrapper = mount({
setup() {
return () => (
)
},
})
await wrapper.findComponent({ ref: 'a' }).trigger('click')
await nextTick()
expect(data.value.length).toBe(1)
expect(data.value).toEqual(['a'])
})
test('nested group', async () => {
const checkList = ref([])
const wrapper = mount({
setup() {
return () => (
)
},
})
expect(checkList.value.length).toBe(0)
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value).toEqual(['a'])
})
describe('true false label', () => {
test('without label', async () => {
const checked = ref('a')
const wrapper = mount(() => (
))
const checkbox = wrapper.findComponent(Checkbox)
await checkbox.trigger('click')
await nextTick()
expect(checked.value).toBe(3)
await checkbox.trigger('click')
await nextTick()
expect(checked.value).toBe('a')
})
test('with label attribute', async () => {
const checked = ref('a')
const wrapper = mount(() => (
))
await wrapper.trigger('click')
await nextTick()
expect(checked.value).toBe(3)
await wrapper.trigger('click')
await nextTick()
expect(checked.value).toBe('a')
})
test('with label as slot content', async () => {
const checked = ref('a')
const wrapper = mount(() => (
Foobar
))
await wrapper.trigger('click')
await nextTick()
expect(checked.value).toBe(3)
await wrapper.trigger('click')
await nextTick()
expect(checked.value).toBe('a')
})
})
test('check', () => {
const checked = ref(false)
const checklist = ref([])
mount(() => (
))
expect(checked.value).toBe(true)
expect(checklist.value).toEqual(['a'])
})
test('label', async () => {
const checklist = ref([])
const wrapper = mount(() => (
all
a
b
))
const checkbox = wrapper.find('.el-checkbox')
await checkbox.trigger('click')
expect(checklist.value[0]).toEqual('')
})
})
describe('check-button', () => {
test('create', async () => {
const checked = ref(false)
const wrapper = mount(() => (
))
expect(wrapper.classes()).toContain('el-checkbox-button')
await wrapper.trigger('click')
expect(wrapper.classes()).toContain('is-checked')
await wrapper.trigger('click')
expect(wrapper.classes('is-checked')).toBe(false)
})
test('disabled', async () => {
const checked = ref(false)
const wrapper = mount(() => (
))
expect(wrapper.classes()).toContain('is-disabled')
await wrapper.trigger('click')
expect(wrapper.classes()).toContain('is-disabled')
})
test('change event', async () => {
const checked = ref(false)
const data = ref()
const onChange = (val: CheckboxValueType) => (data.value = val)
const wrapper = mount(() => (
))
await wrapper.trigger('click')
expect(data.value).toBe(true)
})
test('button group change', async () => {
const checkList = ref([])
const data = ref([])
const onChange = (val: CheckboxValueType[]) => (data.value = val)
const wrapper = mount({
setup() {
return () => (
)
},
})
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(data.value).toEqual(['a'])
await wrapper.findComponent({ ref: 'b' }).trigger('click')
expect(data.value).toEqual(['a', 'b'])
})
test('button group props', () => {
const checkList = ref(['a', 'b'])
const wrapper = mount({
setup() {
return () => (
)
},
})
const checkbox = wrapper.findComponent({ ref: 'a' })
expect(checkList.value.length).toBe(2)
expect(checkbox.classes()).contains('is-checked')
expect(
checkbox.find('.el-checkbox-button__inner').attributes('style')
).contains('border-color: #ff0000;')
})
test('button group tag', () => {
const checkList = ref(['a', 'b'])
const wrapper = mount(() => (
))
expect(wrapper.find('tr').classes('el-checkbox-group')).toBeTruthy()
})
test('button group min and max', async () => {
const checkList = ref(['a', 'b'])
const wrapper = mount({
setup() {
return () => (
)
},
})
expect(checkList.value.length).toBe(2)
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value.length).toBe(2)
await wrapper.findComponent({ ref: 'c' }).trigger('click')
expect(checkList.value.length).toBe(3)
expect(checkList.value).toEqual(['a', 'b', 'c'])
expect(wrapper.findComponent({ ref: 'd' }).vm.isDisabled).toBe(true)
expect(wrapper.findComponent({ ref: 'e' }).vm.isDisabled).toBe(true)
checkList.value = []
await nextTick()
await wrapper.findComponent({ ref: 'a' }).trigger('click')
await wrapper.findComponent({ ref: 'd' }).trigger('click')
expect(checkList.value).toEqual(['a', 'd'])
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value).toEqual(['a', 'd'])
expect(wrapper.findComponent({ ref: 'a' }).vm.isDisabled).toBe(true)
})
test('nested group', async () => {
const checkList = ref([])
const wrapper = mount({
setup() {
return () => (
)
},
})
expect(checkList.value.length).toBe(0)
await wrapper.findComponent({ ref: 'a' }).trigger('click')
expect(checkList.value).toEqual(['a'])
})
describe('checked prop', () => {
test('check', () => {
const checked = ref(false)
const checklist = ref([])
mount(() => (
))
expect(checked.value).toBe(true)
expect(checklist.value).toEqual(['a'])
})
test('checked', () => {
const wrapper = mount(() => )
expect(wrapper.find('.el-checkbox').classes()).contains('is-checked')
})
})
describe('form item accessibility integration', () => {
test('checkbox, no label, automatic label attachment', async () => {
const wrapper = mount(() => (
))
const formItem = await wrapper.findComponent(ElFormItem)
const checkbox = await wrapper.findComponent(Checkbox)
const formItemLabel = formItem.find('.el-form-item__label')
const checkboxInput = checkbox.find('.el-checkbox__original')
expect(checkboxInput.attributes('id')).toBe(
formItemLabel.attributes('for')
)
})
test('checkbox with label, form item is group', async () => {
const wrapper = mount(() => (
))
const formItem = await wrapper.findComponent(ElFormItem)
const checkbox = await wrapper.findComponent(Checkbox)
const checkboxLabel = checkbox.find('.el-checkbox__label')
const checkboxInput = checkbox.find('.el-checkbox__original')
expect(checkboxLabel.element.textContent).toBe('Foo')
expect(checkboxInput.attributes('id')).toBeFalsy()
expect(formItem.attributes('role')).toBe('group')
})
test('single checkbox group in form item', async () => {
const wrapper = mount(() => (
))
const formItem = await wrapper.findComponent(ElFormItem)
const checkboxGroup = await wrapper.findComponent(CheckboxGroup)
const formItemLabel = formItem.find('.el-form-item__label')
expect(formItem.attributes('role')).toBeFalsy()
expect(checkboxGroup.attributes('role')).toBe('group')
expect(formItemLabel.attributes('for')).toBe(
checkboxGroup.attributes('id')
)
expect(formItemLabel.attributes('id')).toBe(
checkboxGroup.attributes('aria-labelledby')
)
})
test('single checkbox group in form item, override label', async () => {
const wrapper = mount(() => (
))
const formItem = await wrapper.findComponent(ElFormItem)
const checkboxGroup = await wrapper.findComponent(CheckboxGroup)
const formItemLabel = formItem.find('.el-form-item__label')
expect(formItemLabel.attributes('for')).toBe(
checkboxGroup.attributes('id')
)
expect(checkboxGroup.attributes('role')).toBe('group')
expect(checkboxGroup.attributes()['aria-label']).toBe('Foo')
expect(checkboxGroup.attributes()['aria-labelledby']).toBeFalsy()
})
test('multiple checkbox groups in form item', async () => {
const wrapper = mount({
setup() {
return () => (
)
},
})
const formItem = await wrapper.findComponent(ElFormItem)
const checkboxGroup1 = await wrapper.findComponent({
ref: 'checkboxGroup1',
})
const checkboxGroup2 = await wrapper.findComponent({
ref: 'checkboxGroup2',
})
const formItemLabel = formItem.find('.el-form-item__label')
expect(formItem.attributes('role')).toBe('group')
expect(formItem.attributes()['aria-labelledby']).toBe(
formItemLabel.attributes('id')
)
expect(checkboxGroup1.attributes('role')).toBe('group')
expect(checkboxGroup1.attributes()['aria-label']).toBe('Foo')
expect(checkboxGroup1.attributes()['aria-labelledby']).toBeFalsy()
expect(checkboxGroup2.attributes('role')).toBe('group')
expect(checkboxGroup2.attributes()['aria-label']).toBe('Bar')
expect(checkboxGroup2.attributes()['aria-labelledby']).toBeFalsy()
})
})
})