import { mount } from '@vue/test-utils'; import VAlert from './VAlert.vue'; import VIcon from './VIcon.vue'; // VAlert uses VIcon import { nextTick } from 'vue'; // Mock VIcon vi.mock('./VIcon.vue', () => ({ name: 'VIcon', props: ['name'], template: '', })); describe('VAlert.vue', () => { it('renders message prop when no default slot', () => { const messageText = 'This is a test alert.'; const wrapper = mount(VAlert, { props: { message: messageText } }); expect(wrapper.find('.alert-content').text()).toBe(messageText); }); it('renders default slot content instead of message prop', () => { const slotContent = 'Custom Alert Content'; const wrapper = mount(VAlert, { props: { message: 'Ignored message' }, slots: { default: slotContent }, }); expect(wrapper.find('.alert-content').html()).toContain(slotContent); }); it('applies correct class based on type prop', () => { const wrapperInfo = mount(VAlert, { props: { type: 'info' } }); expect(wrapperInfo.classes()).toContain('alert-info'); const wrapperSuccess = mount(VAlert, { props: { type: 'success' } }); expect(wrapperSuccess.classes()).toContain('alert-success'); const wrapperWarning = mount(VAlert, { props: { type: 'warning' } }); expect(wrapperWarning.classes()).toContain('alert-warning'); const wrapperError = mount(VAlert, { props: { type: 'error' } }); expect(wrapperError.classes()).toContain('alert-error'); }); it('shows close button and emits events when closable is true', async () => { const wrapper = mount(VAlert, { props: { closable: true, modelValue: true } }); const closeButton = wrapper.find('.alert-close-btn'); expect(closeButton.exists()).toBe(true); await closeButton.trigger('click'); expect(wrapper.emitted()['update:modelValue']).toBeTruthy(); expect(wrapper.emitted()['update:modelValue'][0]).toEqual([false]); expect(wrapper.emitted()['close']).toBeTruthy(); // Check if alert is hidden after internalModelValue updates (due to transition) await nextTick(); // Allow internalModelValue to update and transition to start // Depending on how transition is handled, the element might still be in DOM but display:none // or completely removed. VAlert uses v-if, so it should be removed. // Forcing internalModelValue directly for test simplicity if needed, or wait for transition. // wrapper.vm.internalModelValue = false; // If directly manipulating for test // await nextTick(); expect(wrapper.find('.alert').exists()).toBe(false); // After click and model update, it should be gone }); it('does not show close button when closable is false (default)', () => { const wrapper = mount(VAlert); expect(wrapper.find('.alert-close-btn').exists()).toBe(false); }); it('displays icon by default and uses type-specific default icons', () => { const wrapperSuccess = mount(VAlert, { props: { type: 'success' } }); expect(wrapperSuccess.find('.alert-icon').exists()).toBe(true); expect(wrapperSuccess.find('.icon-check-circle').exists()).toBe(true); // Mocked VIcon class const wrapperError = mount(VAlert, { props: { type: 'error' } }); expect(wrapperError.find('.icon-alert-octagon').exists()).toBe(true); }); it('displays custom icon when icon prop is provided', () => { const customIconName = 'custom-bell'; const wrapper = mount(VAlert, { props: { icon: customIconName } }); expect(wrapper.find('.alert-icon').exists()).toBe(true); expect(wrapper.find(`.icon-${customIconName}`).exists()).toBe(true); }); it('does not display icon when showIcon is false', () => { const wrapper = mount(VAlert, { props: { showIcon: false } }); expect(wrapper.find('.alert-icon').exists()).toBe(false); }); it('renders actions slot content', () => { const actionsContent = ''; const wrapper = mount(VAlert, { slots: { actions: actionsContent }, }); const actionsDiv = wrapper.find('.alert-actions'); expect(actionsDiv.exists()).toBe(true); expect(actionsDiv.html()).toContain(actionsContent); }); it('does not render .alert-actions if slot is not provided', () => { const wrapper = mount(VAlert); expect(wrapper.find('.alert-actions').exists()).toBe(false); }); it('is visible by default (modelValue true)', () => { const wrapper = mount(VAlert); expect(wrapper.find('.alert').exists()).toBe(true); }); it('is hidden when modelValue is initially false', () => { const wrapper = mount(VAlert, { props: { modelValue: false } }); expect(wrapper.find('.alert').exists()).toBe(false); }); it('updates visibility when modelValue prop changes', async () => { const wrapper = mount(VAlert, { props: { modelValue: true } }); expect(wrapper.find('.alert').exists()).toBe(true); await wrapper.setProps({ modelValue: false }); // Wait for transition if any, or internalModelValue update await nextTick(); expect(wrapper.find('.alert').exists()).toBe(false); await wrapper.setProps({ modelValue: true }); await nextTick(); expect(wrapper.find('.alert').exists()).toBe(true); }); });