jest.mock('../../../src/renderer/lib/utils', () => ({ cn: (...classes: string[]) => classes.join(' '), })); jest.mock('../../../src/renderer/components/ui/skeleton', () => { const React = require('react'); const { cn } = require('../../../src/renderer/lib/utils'); const Skeleton = ({ className, ...props }: React.ComponentProps<'div'>) => { return React.createElement('div', { 'data-slot': 'skeleton', className: cn('bg-accent animate-pulse rounded-md', className), 'data-testid': 'skeleton', ...props, }); }; return { Skeleton }; }); import React from 'react'; import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import { Skeleton } from '../../../src/renderer/components/ui/skeleton'; describe('Skeleton Component', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Basic Rendering', () => { test('renders with default props', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); expect(skeleton).toHaveClass('bg-accent', 'animate-pulse', 'rounded-md'); }); test('renders with custom className', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('custom-skeleton'); }); test('forwards additional props', () => { render(); const skeleton = screen.getByTestId('custom-skeleton'); expect(skeleton).toHaveAttribute('id', 'skeleton-123'); }); test('applies default styling', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('bg-accent'); expect(skeleton).toHaveClass('animate-pulse'); expect(skeleton).toHaveClass('rounded-md'); }); }); describe('Styling and Classes', () => { test('merges custom classes with default classes', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass( 'bg-accent', 'animate-pulse', 'rounded-md', 'w-32', 'h-8' ); }); test('handles empty className', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('bg-accent', 'animate-pulse', 'rounded-md'); }); test('handles undefined className', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('bg-accent', 'animate-pulse', 'rounded-md'); }); }); describe('Accessibility', () => { test('has correct data-slot attribute', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveAttribute('data-slot', 'skeleton'); }); test('supports aria attributes', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveAttribute('aria-label', 'Loading content'); }); test('supports role attribute', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveAttribute('role', 'presentation'); }); test('forwards all standard HTML div props', () => { render( ); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveAttribute('title', 'Loading...'); expect(skeleton).toHaveAttribute('tabIndex', '-1'); expect(skeleton).toHaveAttribute('aria-live', 'polite'); expect(skeleton).toHaveAttribute('aria-describedby', 'loading-desc'); }); }); describe('Animation', () => { test('has pulse animation by default', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('animate-pulse'); }); test('can be used with custom animations', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('animate-pulse', 'animate-bounce'); }); }); describe('Content and Children', () => { test('renders without children', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeEmptyDOMElement(); }); test('renders with children', () => { render( Loading... ); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveTextContent('Loading...'); }); test('renders with complex children', () => { render(

Loading content

Please wait...
); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveTextContent('Loading content'); expect(skeleton).toHaveTextContent('Please wait...'); }); }); describe('Sizing and Layout', () => { test('can be used for different sizes', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('w-full', 'h-4'); }); test('can be used for avatar placeholders', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('w-10', 'h-10', 'rounded-full'); }); test('can be used for text line placeholders', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('h-4', 'w-3/4'); }); test('can be used for card placeholders', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toHaveClass('h-32', 'w-full', 'rounded-lg'); }); }); describe('Edge Cases and Error Conditions', () => { test('handles null props gracefully', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); }); test('handles undefined props gracefully', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); }); test('handles empty props object', () => { render(); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); }); }); describe('Integration Scenarios', () => { test('can be used as a loading placeholder for text', () => { render(

Article Title

); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(3); }); test('can be used as a loading placeholder for cards', () => { render(
{[1, 2, 3].map((i) => (
))}
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(9); // 3 cards × 3 skeletons each }); test('can be used as a loading placeholder for user profiles', () => { render(
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(3); }); test('can be used for loading states in forms', () => { render(
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(5); }); test('can be used for table loading states', () => { render( {[1, 2, 3].map((i) => ( ))}
Name Email Status
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(9); // 3 rows × 3 columns }); }); describe('Real-world Usage Patterns', () => { test('loading state for a blog post', () => { render(
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(6); }); test('loading state for a product card', () => { render(
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(5); }); test('loading state for a chat message', () => { render(
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(5); }); test('loading state for a data table with pagination', () => { render(
{[1, 2, 3, 4, 5].map((i) => ( ))}
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(23); // 5 rows × 4 columns + 3 pagination buttons }); }); describe('Performance and Best Practices', () => { test('renders efficiently with many instances', () => { render(
{Array.from({ length: 50 }, (_, i) => ( ))}
); const skeletons = screen.getAllByTestId('skeleton'); expect(skeletons).toHaveLength(50); }); test('maintains performance with deep nesting', () => { render(
); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); }); test('works well with conditional rendering', () => { const { rerender } = render(); expect(screen.getByTestId('skeleton')).toBeInTheDocument(); rerender(
No skeleton
); expect(screen.queryByTestId('skeleton')).not.toBeInTheDocument(); rerender(); expect(screen.getByTestId('skeleton')).toBeInTheDocument(); }); }); describe('TypeScript and Prop Forwarding', () => { test('accepts all standard HTML div props', () => { render( {}} onMouseEnter={() => {}} style={{ margin: '10px' }} data-custom='test' /> ); const skeleton = screen.getByTestId('skeleton'); expect(skeleton).toBeInTheDocument(); expect(skeleton).toHaveAttribute('data-custom', 'test'); }); test('works with React refs', () => { const ref = React.createRef(); render(); expect(ref.current).toBeInstanceOf(HTMLDivElement); }); test('supports all React.ComponentProps', () => { render(