/** * Card 组件测试 * 测试覆盖: Card, CardHeader, CardTitle, CardContent, CardFooter */ import { render, screen, fireEvent } from '@testing-library/react'; import { describe, it, expect, vi } from 'vitest'; import { Card, CardHeader, CardTitle, CardContent, CardFooter } from './Card'; describe('Card', () => { // ==================== 基础渲染测试 ==================== describe('基础渲染', () => { it('渲染子元素', () => { render(卡片内容); expect(screen.getByText('卡片内容')).toBeInTheDocument(); }); it('默认使用 default variant 和 mobile padding', () => { render(内容); const card = screen.getByTestId('card'); expect(card).toHaveClass('bg-bg-card', 'rounded-card'); }); }); // ==================== Variant 测试 ==================== describe('Variant 样式', () => { it('default variant 应用基础样式', () => { render(Default); const card = screen.getByText('Default').closest('div'); expect(card).toHaveClass('bg-bg-card'); expect(card).not.toHaveClass('shadow-elevated'); }); it('elevated variant 应用阴影样式', () => { render(Elevated); const card = screen.getByText('Elevated').closest('div'); expect(card).toHaveClass('bg-bg-elevated', 'shadow-elevated'); }); }); // ==================== Padding 测试 ==================== describe('Padding 样式', () => { it('mobile padding 应用正确样式', () => { render(Mobile); const card = screen.getByText('Mobile').closest('div'); expect(card).toHaveClass('p-[14px_16px]'); }); it('desktop padding 应用正确样式', () => { render(Desktop); const card = screen.getByText('Desktop').closest('div'); expect(card).toHaveClass('p-[16px_20px]'); }); it('none padding 应用正确样式', () => { render(No Padding); const card = screen.getByText('No Padding').closest('div'); expect(card).toHaveClass('p-0'); }); }); // ==================== Hoverable 测试 ==================== describe('Hoverable 属性', () => { it('hoverable 应用 hover 样式', () => { render(Hoverable); const card = screen.getByText('Hoverable').closest('div'); expect(card).toHaveClass('cursor-pointer', 'transition-all'); }); it('非 hoverable 不应用 hover 样式', () => { render(Not Hoverable); const card = screen.getByText('Not Hoverable').closest('div'); expect(card).not.toHaveClass('hover:bg-bg-elevated'); }); }); // ==================== onClick 测试 ==================== describe('onClick 事件', () => { it('点击触发 onClick', () => { const handleClick = vi.fn(); render(Clickable); fireEvent.click(screen.getByText('Clickable')); expect(handleClick).toHaveBeenCalledTimes(1); }); it('有 onClick 时显示 pointer 样式', () => { const handleClick = vi.fn(); render(Clickable); const card = screen.getByText('Clickable').closest('div'); expect(card).toHaveClass('cursor-pointer'); }); }); // ==================== 自定义 className 测试 ==================== describe('自定义 className', () => { it('支持自定义 className', () => { render(Custom); const card = screen.getByText('Custom').closest('div'); expect(card).toHaveClass('custom-card'); }); }); }); describe('CardHeader', () => { it('渲染子元素', () => { render(头部内容); expect(screen.getByText('头部内容')).toBeInTheDocument(); }); it('应用 flex 布局', () => { render(Header); const header = screen.getByText('Header').closest('div'); expect(header).toHaveClass('flex', 'items-center', 'justify-between'); }); it('支持自定义 className', () => { render(Header); const header = screen.getByText('Header').closest('div'); expect(header).toHaveClass('custom-header'); }); }); describe('CardTitle', () => { it('渲染为 h3 标签', () => { render(标题); expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('标题'); }); it('应用标题样式', () => { render(Title); const title = screen.getByRole('heading'); expect(title).toHaveClass('text-section-title', 'text-text-primary', 'font-semibold'); }); it('支持自定义 className', () => { render(Title); expect(screen.getByRole('heading')).toHaveClass('custom-title'); }); }); describe('CardContent', () => { it('渲染子元素', () => { render(内容区域); expect(screen.getByText('内容区域')).toBeInTheDocument(); }); it('支持自定义 className', () => { render(Content); const content = screen.getByText('Content').closest('div'); expect(content).toHaveClass('custom-content'); }); }); describe('CardFooter', () => { it('渲染子元素', () => { render(页脚内容); expect(screen.getByText('页脚内容')).toBeInTheDocument(); }); it('应用边框和间距样式', () => { render(Footer); const footer = screen.getByText('Footer').closest('div'); expect(footer).toHaveClass('mt-4', 'pt-4', 'border-t', 'border-border-subtle'); }); it('支持自定义 className', () => { render(Footer); const footer = screen.getByText('Footer').closest('div'); expect(footer).toHaveClass('custom-footer'); }); }); describe('Card 组合使用', () => { it('完整卡片结构渲染正确', () => { render( 卡片标题 卡片内容 卡片页脚 ); expect(screen.getByRole('heading', { name: '卡片标题' })).toBeInTheDocument(); expect(screen.getByText('卡片内容')).toBeInTheDocument(); expect(screen.getByText('卡片页脚')).toBeInTheDocument(); }); });