2026-04-23 20:52:43 +03:00
|
|
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
|
|
import { ExperienceCard } from './ExperienceCard';
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
|
|
|
|
|
const DEFAULT_PROPS = {
|
|
|
|
|
|
title: 'Senior Developer',
|
|
|
|
|
|
company: 'Acme Corp',
|
|
|
|
|
|
period: '2021 – 2024',
|
|
|
|
|
|
description: 'Built scalable frontend systems.',
|
2026-05-18 12:39:41 +03:00
|
|
|
|
stack: [],
|
2026-04-23 20:52:43 +03:00
|
|
|
|
};
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
|
|
|
|
|
describe('ExperienceCard', () => {
|
|
|
|
|
|
describe('rendering', () => {
|
|
|
|
|
|
it('renders the job title', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
expect(screen.getByText('Senior Developer')).toBeInTheDocument();
|
|
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
|
|
|
|
|
it('renders the company name', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
expect(screen.getByText('Acme Corp')).toBeInTheDocument();
|
|
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
|
|
|
|
|
it('renders the period badge', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
expect(screen.getByText('2021 – 2024')).toBeInTheDocument();
|
|
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
|
|
|
|
|
it('renders the description', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
expect(screen.getByText('Built scalable frontend systems.')).toBeInTheDocument();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
2026-05-18 12:51:33 +03:00
|
|
|
|
describe('layout', () => {
|
|
|
|
|
|
it('period badge is inside the sidebar column', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const badge = screen.getByText('2021 – 2024');
|
|
|
|
|
|
expect(badge.closest('.brutal-border-sidebar')).toBeInTheDocument();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('company name is inside the sidebar column', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const company = screen.getByText('Acme Corp');
|
|
|
|
|
|
expect(company.closest('.brutal-border-sidebar')).toBeInTheDocument();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('title is outside the sidebar column', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const title = screen.getByText('Senior Developer');
|
|
|
|
|
|
expect(title.closest('.brutal-border-sidebar')).toBeNull();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('description is outside the sidebar column', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const desc = screen.getByText('Built scalable frontend systems.');
|
|
|
|
|
|
expect(desc.closest('.brutal-border-sidebar')).toBeNull();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-19 08:37:24 +03:00
|
|
|
|
describe('structure', () => {
|
2026-05-18 12:39:41 +03:00
|
|
|
|
it('title is rendered as an h3', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
2026-05-18 12:39:41 +03:00
|
|
|
|
expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('Senior Developer');
|
2026-04-23 20:52:43 +03:00
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
2026-05-18 13:02:07 +03:00
|
|
|
|
it('period badge has brutal-border, bg-blue, text-cream, md size', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const badge = screen.getByText('2021 – 2024');
|
2026-05-18 13:02:07 +03:00
|
|
|
|
expect(badge).toHaveClass('brutal-border', 'bg-blue', 'text-cream', 'px-4', 'py-2', 'text-sm');
|
2026-04-23 20:52:43 +03:00
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
2026-05-16 19:04:18 +03:00
|
|
|
|
it('description renders via RichText with rich-text class', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
const desc = screen.getByText('Built scalable frontend systems.');
|
2026-05-16 19:04:18 +03:00
|
|
|
|
expect(desc.closest('.rich-text')).toBeInTheDocument();
|
2026-04-23 20:52:43 +03:00
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
2026-05-18 12:51:33 +03:00
|
|
|
|
it('card has brutal-border class', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
const { container } = render(<ExperienceCard {...DEFAULT_PROPS} />);
|
|
|
|
|
|
expect(container.firstChild).toHaveClass('brutal-border');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2026-04-19 08:37:24 +03:00
|
|
|
|
|
2026-05-18 12:51:33 +03:00
|
|
|
|
describe('stack tags', () => {
|
|
|
|
|
|
it('renders stack tags in the sidebar', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} stack={['React', 'TypeScript']} />);
|
|
|
|
|
|
const react = screen.getByText('React');
|
|
|
|
|
|
const ts = screen.getByText('TypeScript');
|
|
|
|
|
|
expect(react.closest('.brutal-border-sidebar')).toBeInTheDocument();
|
|
|
|
|
|
expect(ts.closest('.brutal-border-sidebar')).toBeInTheDocument();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('renders nothing extra when stack is empty', () => {
|
|
|
|
|
|
render(<ExperienceCard {...DEFAULT_PROPS} stack={[]} />);
|
|
|
|
|
|
expect(screen.queryByRole('list')).toBeNull();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-19 08:37:24 +03:00
|
|
|
|
describe('className passthrough', () => {
|
|
|
|
|
|
it('forwards className to the card', () => {
|
2026-04-23 20:52:43 +03:00
|
|
|
|
const { container } = render(<ExperienceCard {...DEFAULT_PROPS} className="custom-class" />);
|
|
|
|
|
|
expect(container.firstChild).toHaveClass('custom-class');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|