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(); expect(container.firstChild).toBeInTheDocument(); }); it('should apply default styles', () => { const { container } = render(); 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(); const skeleton = container.firstChild as HTMLElement; expect(skeleton).toHaveClass('custom-class'); }); }); describe('CardSkeleton', () => { it('should render card skeleton', () => { const { container } = render(); expect(container.firstChild).toBeInTheDocument(); }); it('should have correct structure', () => { const { container } = render(); // 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(); expect(container.firstChild).toBeInTheDocument(); }); it('should have full height', () => { const { container } = render(); const card = container.firstChild as HTMLElement; expect(card).toHaveClass('h-full'); }); }); describe('CaseCardSkeleton', () => { it('should render case card skeleton', () => { const { container } = render(); expect(container.firstChild).toBeInTheDocument(); }); it('should have image placeholder', () => { const { container } = render(); const imageSkeleton = container.querySelector('.h-48'); expect(imageSkeleton).toBeInTheDocument(); }); }); describe('ProductCardSkeleton', () => { it('should render product card skeleton', () => { const { container } = render(); expect(container.firstChild).toBeInTheDocument(); }); it('should have flex column layout', () => { const { container } = render(); 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(); expect(container.firstChild).toBeInTheDocument(); }); it('should have image placeholder', () => { const { container } = render(); const imageSkeleton = container.querySelector('.h-48'); expect(imageSkeleton).toBeInTheDocument(); }); }); describe('SectionSkeleton', () => { it('should render section skeleton', () => { const { container } = render(); expect(container.firstChild).toBeInTheDocument(); }); it('should render multiple service card skeletons', () => { const { container } = render(); // 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(); const textContent = container.textContent; expect(textContent).toBe(''); }); it('should be purely decorative', () => { const { container } = render(); 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(); 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(); const skeletons = container.querySelectorAll('.skeleton-brand'); expect(skeletons.length).toBeGreaterThan(0); }); }); });