e78df62cd1
- 重构 Button、Card、Badge、Input、Textarea 等基础组件 - 新增 Accordion、Alert、Dialog、Dropdown、Form 等 shadcn/ui 组件 - 新增 AnimatedCounter、StatsShowcase、MetricCard 等数据展示组件 - 新增 ScrollReveal 滚动动画组件 - 重构 Toast 通知系统与 Tooltip 提示组件 - 更新设计令牌系统,对齐新品牌视觉
151 lines
5.2 KiB
TypeScript
151 lines
5.2 KiB
TypeScript
import { describe, it, expect } from '@jest/globals';
|
||
import { render } from '@testing-library/react';
|
||
import '@testing-library/jest-dom';
|
||
import {
|
||
Skeleton,
|
||
CardSkeleton,
|
||
ServiceCardSkeleton,
|
||
CaseCardSkeleton,
|
||
ProductCardSkeleton,
|
||
NewsCardSkeleton,
|
||
SectionSkeleton,
|
||
} from './loading-skeleton';
|
||
|
||
describe('Loading Skeleton Components', () => {
|
||
describe('Skeleton', () => {
|
||
it('should render skeleton element', () => {
|
||
const { container } = render(<Skeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should apply default styles', () => {
|
||
const { container } = render(<Skeleton />);
|
||
const skeleton = container.firstChild as HTMLElement;
|
||
// loading-skeleton.tsx 使用 skeleton-brand 自定义类
|
||
expect(skeleton).toHaveClass('skeleton-brand');
|
||
expect(skeleton).toHaveClass('rounded-md');
|
||
});
|
||
|
||
it('should apply custom className', () => {
|
||
const { container } = render(<Skeleton className="custom-class" />);
|
||
const skeleton = container.firstChild as HTMLElement;
|
||
expect(skeleton).toHaveClass('custom-class');
|
||
});
|
||
});
|
||
|
||
describe('CardSkeleton', () => {
|
||
it('should render card skeleton', () => {
|
||
const { container } = render(<CardSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should have correct structure', () => {
|
||
const { container } = render(<CardSkeleton />);
|
||
// CardSkeleton 包含 4 个子 Skeleton,使用 skeleton-brand 类
|
||
const skeletonElements = container.querySelectorAll('.skeleton-brand');
|
||
expect(skeletonElements.length).toBeGreaterThan(0);
|
||
});
|
||
});
|
||
|
||
describe('ServiceCardSkeleton', () => {
|
||
it('should render service card skeleton', () => {
|
||
const { container } = render(<ServiceCardSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should have full height', () => {
|
||
const { container } = render(<ServiceCardSkeleton />);
|
||
const card = container.firstChild as HTMLElement;
|
||
expect(card).toHaveClass('h-full');
|
||
});
|
||
});
|
||
|
||
describe('CaseCardSkeleton', () => {
|
||
it('should render case card skeleton', () => {
|
||
const { container } = render(<CaseCardSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should have image placeholder', () => {
|
||
const { container } = render(<CaseCardSkeleton />);
|
||
const imageSkeleton = container.querySelector('.h-48');
|
||
expect(imageSkeleton).toBeInTheDocument();
|
||
});
|
||
});
|
||
|
||
describe('ProductCardSkeleton', () => {
|
||
it('should render product card skeleton', () => {
|
||
const { container } = render(<ProductCardSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should have flex column layout', () => {
|
||
const { container } = render(<ProductCardSkeleton />);
|
||
const card = container.firstChild as HTMLElement;
|
||
expect(card).toHaveClass('flex');
|
||
expect(card).toHaveClass('flex-col');
|
||
});
|
||
});
|
||
|
||
describe('NewsCardSkeleton', () => {
|
||
it('should render news card skeleton', () => {
|
||
const { container } = render(<NewsCardSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should have image placeholder', () => {
|
||
const { container } = render(<NewsCardSkeleton />);
|
||
const imageSkeleton = container.querySelector('.h-48');
|
||
expect(imageSkeleton).toBeInTheDocument();
|
||
});
|
||
});
|
||
|
||
describe('SectionSkeleton', () => {
|
||
it('should render section skeleton', () => {
|
||
const { container } = render(<SectionSkeleton />);
|
||
expect(container.firstChild).toBeInTheDocument();
|
||
});
|
||
|
||
it('should render multiple service card skeletons', () => {
|
||
const { container } = render(<SectionSkeleton />);
|
||
// SectionSkeleton 渲染 4 个 ServiceCardSkeleton
|
||
// ServiceCardSkeleton 容器使用 var(--color-bg-primary)
|
||
const cards = container.querySelectorAll('.skeleton-brand');
|
||
// 每个 ServiceCardSkeleton 包含 4 个 Skeleton,4 个卡片共 16 个
|
||
expect(cards.length).toBeGreaterThanOrEqual(4);
|
||
});
|
||
});
|
||
|
||
describe('Accessibility', () => {
|
||
it('should not have any accessible content', () => {
|
||
const { container } = render(<CardSkeleton />);
|
||
const textContent = container.textContent;
|
||
expect(textContent).toBe('');
|
||
});
|
||
|
||
it('should be purely decorative', () => {
|
||
const { container } = render(<SectionSkeleton />);
|
||
const elements = container.querySelectorAll('*');
|
||
elements.forEach(element => {
|
||
expect(element).not.toHaveAttribute('aria-label');
|
||
expect(element).not.toHaveAttribute('aria-labelledby');
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('Animation', () => {
|
||
it('should have pulse animation', () => {
|
||
const { container } = render(<Skeleton />);
|
||
const skeleton = container.firstChild as HTMLElement;
|
||
// loading-skeleton.tsx 使用 skeleton-brand 自定义类(CSS 中包含动画)
|
||
expect(skeleton).toHaveClass('skeleton-brand');
|
||
});
|
||
|
||
it('should apply animation to all skeleton elements', () => {
|
||
const { container } = render(<CardSkeleton />);
|
||
const skeletons = container.querySelectorAll('.skeleton-brand');
|
||
expect(skeletons.length).toBeGreaterThan(0);
|
||
});
|
||
});
|
||
});
|