2026-04-23 20:52:43 +03:00
|
|
|
import { render, screen } from '@testing-library/react';
|
2026-05-18 12:51:33 +03:00
|
|
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardSidebar, CardTitle } from './Card';
|
2026-04-19 08:19:58 +03:00
|
|
|
|
|
|
|
|
describe('Card', () => {
|
|
|
|
|
describe('rendering', () => {
|
|
|
|
|
it('renders children', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<Card>Content</Card>);
|
|
|
|
|
expect(screen.getByText('Content')).toBeInTheDocument();
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
it('has brutal-border and brutal-shadow classes', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
const { container } = render(<Card>Content</Card>);
|
|
|
|
|
expect(container.firstChild).toHaveClass('brutal-border', 'brutal-shadow');
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('background variants', () => {
|
2026-05-11 12:59:32 +03:00
|
|
|
it('defaults to cream background', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
const { container } = render(<Card>Content</Card>);
|
2026-05-11 12:59:32 +03:00
|
|
|
expect(container.firstChild).toHaveClass('bg-cream');
|
2026-04-23 20:52:43 +03:00
|
|
|
});
|
2026-05-11 12:59:32 +03:00
|
|
|
it('applies blue background', () => {
|
|
|
|
|
const { container } = render(<Card background="blue">Content</Card>);
|
|
|
|
|
expect(container.firstChild).toHaveClass('bg-blue');
|
2026-04-23 20:52:43 +03:00
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('padding', () => {
|
|
|
|
|
it('has default padding', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
const { container } = render(<Card>Content</Card>);
|
|
|
|
|
expect(container.firstChild).toHaveClass('p-6');
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
it('removes padding when noPadding is true', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
const { container } = render(<Card noPadding>Content</Card>);
|
|
|
|
|
expect(container.firstChild).not.toHaveClass('p-6');
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('className passthrough', () => {
|
|
|
|
|
it('merges custom className', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
const { container } = render(<Card className="group">Content</Card>);
|
|
|
|
|
expect(container.firstChild).toHaveClass('group');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('CardHeader', () => {
|
|
|
|
|
it('renders children with bottom margin', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<CardHeader>Header</CardHeader>);
|
2026-05-18 12:39:20 +03:00
|
|
|
expect(screen.getByText('Header')).toHaveClass('mb-6');
|
2026-04-23 20:52:43 +03:00
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('CardTitle', () => {
|
|
|
|
|
it('renders children as h3', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<CardTitle>Title</CardTitle>);
|
|
|
|
|
expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('Title');
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('CardDescription', () => {
|
|
|
|
|
it('renders children as paragraph with opacity', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<CardDescription>Desc</CardDescription>);
|
|
|
|
|
const el = screen.getByText('Desc');
|
|
|
|
|
expect(el.tagName).toBe('P');
|
|
|
|
|
expect(el).toHaveClass('opacity-80');
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('CardContent', () => {
|
|
|
|
|
it('renders children in a div', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<CardContent>Body</CardContent>);
|
|
|
|
|
expect(screen.getByText('Body')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-19 08:19:58 +03:00
|
|
|
describe('CardFooter', () => {
|
|
|
|
|
it('renders children with top border', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
render(<CardFooter>Footer</CardFooter>);
|
|
|
|
|
const el = screen.getByText('Footer');
|
2026-05-18 12:39:20 +03:00
|
|
|
expect(el).toHaveClass('brutal-border-top', 'mt-6', 'pt-6', 'md:mt-8', 'md:pt-8');
|
2026-04-23 20:52:43 +03:00
|
|
|
});
|
|
|
|
|
});
|
2026-05-18 12:51:33 +03:00
|
|
|
describe('CardSidebar', () => {
|
|
|
|
|
describe('rendering', () => {
|
|
|
|
|
it('renders sidebar content', () => {
|
|
|
|
|
render(<CardSidebar sidebar={<span>Sidebar</span>}>Main</CardSidebar>);
|
|
|
|
|
expect(screen.getByText('Sidebar')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders main content', () => {
|
|
|
|
|
render(<CardSidebar sidebar={<span>Sidebar</span>}>Main</CardSidebar>);
|
|
|
|
|
expect(screen.getByText('Main')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('structure', () => {
|
|
|
|
|
it('root wrapper is a flex container', () => {
|
|
|
|
|
const { container } = render(<CardSidebar sidebar={<span>S</span>}>M</CardSidebar>);
|
|
|
|
|
expect(container.firstChild).toHaveClass('flex');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('sidebar column has brutal-border-sidebar class', () => {
|
|
|
|
|
render(<CardSidebar sidebar={<span>Sidebar</span>}>Main</CardSidebar>);
|
|
|
|
|
const sidebar = screen.getByText('Sidebar').parentElement;
|
|
|
|
|
expect(sidebar).toHaveClass('brutal-border-sidebar');
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-18 13:11:53 +03:00
|
|
|
it('sidebar column has fixed width on lg', () => {
|
2026-05-18 12:51:33 +03:00
|
|
|
render(<CardSidebar sidebar={<span>Sidebar</span>}>Main</CardSidebar>);
|
|
|
|
|
const sidebar = screen.getByText('Sidebar').parentElement;
|
2026-05-18 13:11:53 +03:00
|
|
|
expect(sidebar).toHaveClass('lg:w-64');
|
2026-05-18 12:51:33 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('main column fills remaining space', () => {
|
|
|
|
|
render(<CardSidebar sidebar={<span>Sidebar</span>}>Main</CardSidebar>);
|
|
|
|
|
expect(screen.getByText('Main')).toHaveClass('flex-1');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('className passthrough', () => {
|
|
|
|
|
it('forwards className to the root wrapper', () => {
|
|
|
|
|
const { container } = render(
|
|
|
|
|
<CardSidebar sidebar={<span>S</span>} className="custom">
|
|
|
|
|
M
|
|
|
|
|
</CardSidebar>,
|
|
|
|
|
);
|
|
|
|
|
expect(container.firstChild).toHaveClass('custom');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|