import {describe, expect, it} from 'vitest' import {mount} from '@vue/test-utils' import type {DefineComponent} from 'vue' import {Icon as IconifyIcon} from '@iconify/vue' import ButtonIcon from './ButtonIcon.vue' type ButtonIconProps = { id?: string icon: string ariaLabel: string disabled?: boolean buttonClass?: string iconSize?: string | number variant?: 'filled' | 'ghost' } const ButtonIconForTest = ButtonIcon as DefineComponent const mountComponent = (props: ButtonIconProps = {icon: 'mdi:arrow-left', ariaLabel: 'Retour'}) => mount(ButtonIconForTest, { props, global: { stubs: { IconifyIcon: { template: '', }, }, }, }) describe('MalioButtonIcon', () => { it('renders a button with the icon', () => { const wrapper = mountComponent() expect(wrapper.find('button').exists()).toBe(true) expect(wrapper.find('[data-test="icon"]').exists()).toBe(true) }) it('uses provided id on button', () => { const wrapper = mountComponent({id: 'custom-id', icon: 'mdi:arrow-left', ariaLabel: 'Retour'}) expect(wrapper.get('button').attributes('id')).toBe('custom-id') }) it('generates an id when missing', () => { const wrapper = mountComponent() const buttonId = wrapper.get('button').attributes('id') expect(buttonId?.startsWith('malio-button-icon-')).toBe(true) }) it('sets aria-label on button', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour'}) expect(wrapper.get('button').attributes('aria-label')).toBe('Retour') }) it('sets type="button" on the button', () => { const wrapper = mountComponent() expect(wrapper.get('button').attributes('type')).toBe('button') }) it('passes icon name to icon component', () => { const wrapper = mount(ButtonIconForTest, { props: {icon: 'mdi:pencil-outline', ariaLabel: 'Modifier'}, }) const iconComponent = wrapper.findComponent(IconifyIcon) expect(iconComponent.props('icon')).toBe('mdi:pencil-outline') }) it('passes icon size to icon component', () => { const wrapper = mount(ButtonIconForTest, { props: {icon: 'mdi:arrow-left', ariaLabel: 'Retour', iconSize: 32}, }) const iconComponent = wrapper.findComponent(IconifyIcon) expect(iconComponent.props('width')).toBe(32) expect(iconComponent.props('height')).toBe(32) }) it('emits click event when clicked', async () => { const wrapper = mountComponent() await wrapper.get('button').trigger('click') expect(wrapper.emitted('click')).toHaveLength(1) }) it('does not emit click when disabled', async () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', disabled: true}) await wrapper.get('button').trigger('click') expect(wrapper.emitted('click')).toBeUndefined() }) it('sets disabled attribute when disabled', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', disabled: true}) expect(wrapper.get('button').attributes('disabled')).toBeDefined() }) it('applies disabled styles when disabled', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', disabled: true}) expect(wrapper.get('button').classes()).toContain('cursor-not-allowed') expect(wrapper.get('button').classes()).toContain('bg-m-btn-disabled') }) it('applies cursor-pointer when not disabled', () => { const wrapper = mountComponent() expect(wrapper.get('button').classes()).toContain('cursor-pointer') }) it('applies white text color for icon visibility', () => { const wrapper = mountComponent() expect(wrapper.get('button').classes()).toContain('text-white') }) it('applies default background color', () => { const wrapper = mountComponent() expect(wrapper.get('button').classes()).toContain('bg-m-btn-default') }) it('applies buttonClass', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', buttonClass: 'rounded-full'}) expect(wrapper.get('button').classes()).toContain('rounded-full') }) it('applies ghost variant with no background and colored icon', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', variant: 'ghost'}) expect(wrapper.get('button').classes()).toContain('text-m-btn-default') expect(wrapper.get('button').classes()).not.toContain('bg-m-btn-default') expect(wrapper.get('button').classes()).not.toContain('text-white') }) it('applies ghost disabled styles with no background', () => { const wrapper = mountComponent({icon: 'mdi:arrow-left', ariaLabel: 'Retour', variant: 'ghost', disabled: true}) expect(wrapper.get('button').classes()).toContain('text-m-btn-disabled') expect(wrapper.get('button').classes()).toContain('cursor-not-allowed') expect(wrapper.get('button').classes()).not.toContain('bg-m-btn-disabled') }) })