mitlist/fe/src/components/valerie/VCard.spec.ts

141 lines
5.7 KiB
TypeScript

import { mount } from '@vue/test-utils';
import VCard from './VCard.vue';
import VIcon from './VIcon.vue'; // VCard uses VIcon
import { describe, it, expect, vi } from 'vitest';
// Mock VIcon to simplify testing VCard in isolation,
// especially if VIcon itself has complex rendering or external dependencies.
// vi.mock('./VIcon.vue', ()_ => ({
// name: 'VIcon',
// props: ['name', 'size'],
// template: '<i :class="`mock-icon icon-${name}`"></i>',
// }));
// For now, let's allow it to render as its props are simple.
describe('VCard.vue', () => {
// Default variant tests
describe('Default Variant', () => {
it('renders headerTitle when provided and no header slot', () => {
const headerText = 'My Card Header';
const wrapper = mount(VCard, { props: { headerTitle: headerText } });
const header = wrapper.find('.card-header');
expect(header.exists()).toBe(true);
expect(header.find('.card-header-title').text()).toBe(headerText);
});
it('renders header slot content instead of headerTitle', () => {
const slotContent = '<div class="custom-header">Custom Header</div>';
const wrapper = mount(VCard, {
props: { headerTitle: 'Ignored Title' },
slots: { header: slotContent },
});
const header = wrapper.find('.card-header');
expect(header.exists()).toBe(true);
expect(header.find('.custom-header').exists()).toBe(true);
expect(header.text()).toContain('Custom Header');
expect(header.find('.card-header-title').exists()).toBe(false);
});
it('does not render .card-header if no headerTitle and no header slot', () => {
const wrapper = mount(VCard, { slots: { default: '<p>Body</p>' } });
expect(wrapper.find('.card-header').exists()).toBe(false);
});
it('renders default slot content in .card-body', () => {
const bodyContent = '<p>Main card content here.</p>';
const wrapper = mount(VCard, { slots: { default: bodyContent } });
const body = wrapper.find('.card-body');
expect(body.exists()).toBe(true);
expect(body.html()).toContain(bodyContent);
});
it('renders footer slot content in .card-footer', () => {
const footerContent = '<span>Card Footer Text</span>';
const wrapper = mount(VCard, { slots: { footer: footerContent } });
const footer = wrapper.find('.card-footer');
expect(footer.exists()).toBe(true);
expect(footer.html()).toContain(footerContent);
});
it('does not render .card-footer if no footer slot', () => {
const wrapper = mount(VCard, { slots: { default: '<p>Body</p>' } });
expect(wrapper.find('.card-footer').exists()).toBe(false);
});
it('applies .card class by default', () => {
const wrapper = mount(VCard);
expect(wrapper.classes()).toContain('card');
expect(wrapper.classes()).not.toContain('empty-state-card');
});
});
// Empty state variant tests
describe('Empty State Variant', () => {
const emptyStateProps = {
variant: 'empty-state' as const,
emptyIcon: 'alert',
emptyTitle: 'Nothing to Show',
emptyMessage: 'There is no data available at this moment.',
};
it('applies .card and .empty-state-card classes', () => {
const wrapper = mount(VCard, { props: emptyStateProps });
expect(wrapper.classes()).toContain('card');
expect(wrapper.classes()).toContain('empty-state-card');
});
it('renders empty state icon, title, and message', () => {
const wrapper = mount(VCard, {
props: emptyStateProps,
global: { components: { VIcon } } // Ensure VIcon is available
});
const icon = wrapper.findComponent(VIcon); // Or find by class if not using findComponent
expect(icon.exists()).toBe(true);
expect(icon.props('name')).toBe(emptyStateProps.emptyIcon);
expect(wrapper.find('.empty-state-title').text()).toBe(emptyStateProps.emptyTitle);
expect(wrapper.find('.empty-state-message').text()).toBe(emptyStateProps.emptyMessage);
});
it('does not render icon, title, message if props not provided', () => {
const wrapper = mount(VCard, {
props: { variant: 'empty-state' as const },
global: { components: { VIcon } }
});
expect(wrapper.findComponent(VIcon).exists()).toBe(false); // Or check for .empty-state-icon
expect(wrapper.find('.empty-state-title').exists()).toBe(false);
expect(wrapper.find('.empty-state-message').exists()).toBe(false);
});
it('renders empty-actions slot content', () => {
const actionsContent = '<button>Add Item</button>';
const wrapper = mount(VCard, {
props: emptyStateProps,
slots: { 'empty-actions': actionsContent },
});
const actionsContainer = wrapper.find('.empty-state-actions');
expect(actionsContainer.exists()).toBe(true);
expect(actionsContainer.html()).toContain(actionsContent);
});
it('does not render .empty-state-actions if slot is not provided', () => {
const wrapper = mount(VCard, { props: emptyStateProps });
expect(wrapper.find('.empty-state-actions').exists()).toBe(false);
});
it('does not render standard header, body (main slot), or footer in empty state', () => {
const wrapper = mount(VCard, {
props: { ...emptyStateProps, headerTitle: 'Should not show' },
slots: {
default: '<p>Standard body</p>',
footer: '<span>Standard footer</span>',
},
});
expect(wrapper.find('.card-header').exists()).toBe(false);
// The .card-body is used by empty-state-content, so check for specific standard content
expect(wrapper.text()).not.toContain('Standard body');
expect(wrapper.find('.card-footer').exists()).toBe(false);
});
});
});