import {describe, expect, it} from 'vitest' import {mount} from '@vue/test-utils' import type {DefineComponent} from 'vue' import SelectCheckbox from './SelectCheckbox.vue' type Option = { label: string value: string | number } type SelectCheckboxProps = { modelValue: Array options?: Option[] emptyOptionLabel?: string label?: string hint?: string error?: string success?: string textField?: string textValue?: string textLabel?: string rounded?: string displayTag?: boolean displaySelectAll?: boolean selectAllLabel?: string disabled?: boolean groupClass?: string } const SelectCheckboxForTest = SelectCheckbox as DefineComponent const options: Option[] = [ {label: 'France', value: 'fr'}, {label: 'Belgique', value: 'be'}, {label: 'Canada', value: 'ca'}, ] describe('MalioSelectCheckbox', () => { it('renders checkbox inputs for options', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') expect(checkboxes).toHaveLength(options.length) }) it('emits an array with the toggled option value', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr'], options}, }) await wrapper.get('button').trigger('click') const checkboxInputs = wrapper.findAll('input[type="checkbox"]') await checkboxInputs[1].setValue(true) expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['fr', 'be']]) }) it('shows the selected count over the total count in the trigger', () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr', 'ca'], options}, }) expect(wrapper.text()).toContain('2/3') }) it('shows 0 over the total count when nothing is selected', () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options}, }) expect(wrapper.text()).toContain('0/3') }) it('hides the summary when displayTag is enabled and options are selected', () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr', 'ca'], options, displayTag: true}, }) expect(wrapper.text()).not.toContain('2/3') expect(wrapper.text()).toContain('France') expect(wrapper.text()).toContain('Canada') }) it('hides the summary when displayTag is enabled and nothing is selected', () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options, displayTag: true, emptyOptionLabel: 'Aucune selection'}, }) expect(wrapper.text()).not.toContain('0/3') expect(wrapper.text()).toContain('Aucune selection') }) it('does not show select all checkbox by default', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') expect(checkboxes).toHaveLength(options.length) }) it('shows select all checkbox when displaySelectAll is true', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options, displaySelectAll: true}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') expect(checkboxes).toHaveLength(options.length + 1) expect(wrapper.text()).toContain('Tout sélectionner') }) it('shows custom select all label', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options, displaySelectAll: true, selectAllLabel: 'Sélectionner tout'}, }) await wrapper.get('button').trigger('click') expect(wrapper.text()).toContain('Sélectionner tout') }) it('emits all values when select all is clicked and none selected', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options, displaySelectAll: true}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') await checkboxes[0].setValue(true) expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['fr', 'be', 'ca']]) }) it('emits empty array when select all is clicked and all selected', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr', 'be', 'ca'], options, displaySelectAll: true}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') await checkboxes[0].setValue(false) expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([[]]) }) it('select all checkbox is checked when all options are selected', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr', 'be', 'ca'], options, displaySelectAll: true}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') expect((checkboxes[0].element as HTMLInputElement).checked).toBe(true) }) it('select all checkbox is unchecked when not all options are selected', async () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: ['fr'], options, displaySelectAll: true}, }) await wrapper.get('button').trigger('click') const checkboxes = wrapper.findAll('input[type="checkbox"]') expect((checkboxes[0].element as HTMLInputElement).checked).toBe(false) }) it('applies groupClass via twMerge', () => { const wrapper = mount(SelectCheckboxForTest, { props: {modelValue: [], options: [], groupClass: 'mt-4'}, }) const root = wrapper.find('button').element.parentElement expect(root?.className).toContain('mt-4') }) })