Files
novalon-website/src/components/ui/metric-card.test.tsx
T
zhangxiang 602ed6a671 test(hooks): finalize mutation test improvements and release acceptance
- Raise use-swipe-gesture mutation score to 66.13% (target 65%+)
- Maintain use-reduced-motion mutation score at 76.32% (target 50%+)
- Fix use-reduced-motion.ts ESLint set-state-in-effect warning
- Add UJ-10 deep searcher journey (category browse → article read → content discovery)
- Add 40 new test files (analytics, detail, sections, ui, lib components)
- Update test-strategy-plan.md to v2.0 (sync test count to 1591)
- Sync README.md with final release metrics

Quality gates: TS 0 errors, ESLint 0 errors, 121 suites / 1591 tests passed
2026-08-02 19:39:27 +08:00

104 lines
3.6 KiB
TypeScript

// @ts-nocheck
import { describe, it, expect, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { MetricCard } from './metric-card';
// ─── Mocks ───────────────────────────────────────────────────────────────
jest.mock('framer-motion', () => ({
motion: {
div: ({ children, className, ...props }: any) => (
<div className={className} {...props}>{children}</div>
),
span: ({ children, className, ...props }: any) => (
<span className={className} {...props}>{children}</span>
),
},
useInView: jest.fn(() => true),
}));
jest.mock('lucide-react', () => ({
ArrowUpRight: (props: any) => <svg data-testid="icon-trend-up" className={props.className} />,
ArrowDownRight: (props: any) => <svg data-testid="icon-trend-down" className={props.className} />,
}));
jest.mock('@/components/ui/animated-counter', () => ({
AnimatedCounter: ({ value, prefix, suffix }: any) => (
<span>{prefix}{value}{suffix}</span>
),
}));
// ─── Tests ───────────────────────────────────────────────────────────────
describe('MetricCard', () => {
it('should render label and value', () => {
render(<MetricCard label="客户数" value={500} />);
expect(screen.getByText('客户数')).toBeInTheDocument();
expect(screen.getByText('500')).toBeInTheDocument();
});
it('should render icon when provided', () => {
render(
<MetricCard
label="收入"
value={1000}
icon={<span data-testid="custom-icon">$</span>}
/>
);
expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
});
it('should render prefix and suffix', () => {
render(<MetricCard label="增长率" value={99} prefix="+" suffix="%" />);
expect(screen.getByText('+99%')).toBeInTheDocument();
});
it('should render description when provided', () => {
render(<MetricCard label="用户" value={1000} description="活跃用户数" />);
expect(screen.getByText('活跃用户数')).toBeInTheDocument();
});
it('should render trend with up direction', () => {
render(
<MetricCard
label="收入"
value={500}
trend={{ value: '+12%', direction: 'up' }}
/>
);
expect(screen.getByText('+12%')).toBeInTheDocument();
expect(screen.getByTestId('icon-trend-up')).toBeInTheDocument();
});
it('should render trend with down direction', () => {
render(
<MetricCard
label="流失率"
value={5}
trend={{ value: '-2%', direction: 'down', label: '较上月' }}
/>
);
expect(screen.getByText('-2%')).toBeInTheDocument();
expect(screen.getByText('较上月')).toBeInTheDocument();
expect(screen.getByTestId('icon-trend-down')).toBeInTheDocument();
});
it('should apply custom className', () => {
const { container } = render(
<MetricCard label="测试" value={1} className="custom-class" />
);
const div = container.querySelector('.custom-class');
expect(div).toBeInTheDocument();
});
it('should render in dark theme', () => {
render(<MetricCard label="Dark" value={100} theme="dark" />);
expect(screen.getByText('Dark')).toBeInTheDocument();
});
it('should render with different accent colors', () => {
render(<MetricCard label="Blue" value={1} accentColor="blue" />);
expect(screen.getByText('Blue')).toBeInTheDocument();
});
});