import { describe, it, expect, vi } from 'vitest' import { mount } from '@vue/test-utils' import ActionButton from '~/components/UI/ActionButton.vue' describe('ActionButton', () => { describe('Rendering', () => { it('renders slot content', () => { const wrapper = mount(ActionButton, { slots: { default: 'Click Me', }, }) expect(wrapper.text()).toContain('Click Me') }) it('renders with default props', () => { const wrapper = mount(ActionButton, { slots: { default: 'Test', }, }) const button = wrapper.find('button') expect(button.attributes('type')).toBe('button') expect(button.classes()).toContain('from-primary') }) }) describe('Variants', () => { it('applies primary variant classes', () => { const wrapper = mount(ActionButton, { props: { variant: 'primary' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('from-primary') expect(wrapper.find('button').classes()).toContain('to-blue-600') }) it('applies secondary variant classes', () => { const wrapper = mount(ActionButton, { props: { variant: 'secondary' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('from-gray-600') }) it('applies success variant classes', () => { const wrapper = mount(ActionButton, { props: { variant: 'success' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('from-green-600') }) it('applies danger variant classes', () => { const wrapper = mount(ActionButton, { props: { variant: 'danger' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('from-red-600') }) it('applies warning variant classes', () => { const wrapper = mount(ActionButton, { props: { variant: 'warning' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('from-yellow-500') }) }) describe('Sizes', () => { it('applies small size classes', () => { const wrapper = mount(ActionButton, { props: { size: 'sm' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('px-3') expect(wrapper.find('button').classes()).toContain('py-1.5') }) it('applies medium size classes', () => { const wrapper = mount(ActionButton, { props: { size: 'md' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('px-4') expect(wrapper.find('button').classes()).toContain('py-2.5') }) it('applies large size classes', () => { const wrapper = mount(ActionButton, { props: { size: 'lg' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('px-6') expect(wrapper.find('button').classes()).toContain('py-3') }) }) describe('States', () => { it('shows loading spinner when loading', () => { const wrapper = mount(ActionButton, { props: { loading: true }, slots: { default: 'Test' }, }) expect(wrapper.find('svg.animate-spin').exists()).toBe(true) expect(wrapper.find('button').attributes('disabled')).toBe('') }) it('hides content when loading', () => { const wrapper = mount(ActionButton, { props: { loading: true }, slots: { default: 'Test' }, }) const contentSpan = wrapper.find('span.invisible') expect(contentSpan.exists()).toBe(true) }) it('disables button when disabled prop is true', () => { const wrapper = mount(ActionButton, { props: { disabled: true }, slots: { default: 'Test' }, }) expect(wrapper.find('button').attributes('disabled')).toBe('') }) it('disables button when loading', () => { const wrapper = mount(ActionButton, { props: { loading: true }, slots: { default: 'Test' }, }) expect(wrapper.find('button').attributes('disabled')).toBe('') }) }) describe('Full Width', () => { it('applies full width class when fullWidth is true', () => { const wrapper = mount(ActionButton, { props: { fullWidth: true }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).toContain('w-full') }) it('does not apply full width class by default', () => { const wrapper = mount(ActionButton, { props: { fullWidth: false }, slots: { default: 'Test' }, }) expect(wrapper.find('button').classes()).not.toContain('w-full') }) }) describe('Events', () => { it('emits click event when clicked', async () => { const wrapper = mount(ActionButton, { slots: { default: 'Test' }, }) await wrapper.find('button').trigger('click') expect(wrapper.emitted('click')).toBeTruthy() expect(wrapper.emitted('click')).toHaveLength(1) }) it('does not emit click when disabled', async () => { const wrapper = mount(ActionButton, { props: { disabled: true }, slots: { default: 'Test' }, }) await wrapper.find('button').trigger('click') expect(wrapper.emitted('click')).toBeFalsy() }) it('does not emit click when loading', async () => { const wrapper = mount(ActionButton, { props: { loading: true }, slots: { default: 'Test' }, }) await wrapper.find('button').trigger('click') expect(wrapper.emitted('click')).toBeFalsy() }) it('emits MouseEvent in click handler', async () => { const wrapper = mount(ActionButton, { slots: { default: 'Test' }, }) await wrapper.find('button').trigger('click') const emitted = wrapper.emitted('click') expect(emitted).toBeTruthy() expect(emitted![0][0]).toBeInstanceOf(MouseEvent) }) }) describe('Type Attribute', () => { it('sets type to button by default', () => { const wrapper = mount(ActionButton, { slots: { default: 'Test' }, }) expect(wrapper.find('button').attributes('type')).toBe('button') }) it('sets type to submit when specified', () => { const wrapper = mount(ActionButton, { props: { type: 'submit' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').attributes('type')).toBe('submit') }) it('sets type to reset when specified', () => { const wrapper = mount(ActionButton, { props: { type: 'reset' }, slots: { default: 'Test' }, }) expect(wrapper.find('button').attributes('type')).toBe('reset') }) }) })