chore: add mock API route handlers and dev env config
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export { default as ExperienceSection } from './ui/ExperienceSection/ExperienceSection';
|
||||
@@ -0,0 +1,87 @@
|
||||
vi.mock('$shared/api', () => ({
|
||||
getCollection: vi.fn(),
|
||||
}));
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { getCollection } from '$shared/api';
|
||||
import ExperienceSection from './ExperienceSection';
|
||||
|
||||
const mockItems = [
|
||||
{
|
||||
id: '1',
|
||||
collectionId: 'c1',
|
||||
collectionName: 'experience',
|
||||
created: '',
|
||||
updated: '',
|
||||
company: 'Acme Corp',
|
||||
role: 'Senior Developer',
|
||||
start_date: '2022-01-01T00:00:00Z',
|
||||
end_date: null,
|
||||
description: 'Built critical systems.',
|
||||
order: 1,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
collectionId: 'c1',
|
||||
collectionName: 'experience',
|
||||
created: '',
|
||||
updated: '',
|
||||
company: 'Beta Ltd',
|
||||
role: 'Junior Developer',
|
||||
start_date: '2020-01-01T00:00:00Z',
|
||||
end_date: '2021-12-31T00:00:00Z',
|
||||
description: 'Learned the ropes.',
|
||||
order: 2,
|
||||
},
|
||||
];
|
||||
|
||||
const listResponse = (items: typeof mockItems) => ({
|
||||
items,
|
||||
page: 1,
|
||||
perPage: 50,
|
||||
totalItems: items.length,
|
||||
totalPages: 1,
|
||||
});
|
||||
|
||||
describe('ExperienceSection', () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(getCollection).mockResolvedValue(listResponse(mockItems) as never);
|
||||
});
|
||||
|
||||
describe('rendering', () => {
|
||||
it('renders a card for each experience record', async () => {
|
||||
render(await ExperienceSection());
|
||||
expect(screen.getByText('Senior Developer')).toBeInTheDocument();
|
||||
expect(screen.getByText('Junior Developer')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders company names', async () => {
|
||||
render(await ExperienceSection());
|
||||
expect(screen.getByText('Acme Corp')).toBeInTheDocument();
|
||||
expect(screen.getByText('Beta Ltd')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('formats open-ended period as "Present"', async () => {
|
||||
render(await ExperienceSection());
|
||||
expect(screen.getByText('2022 — Present')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('formats closed period with year range', async () => {
|
||||
render(await ExperienceSection());
|
||||
expect(screen.getByText('2020 — 2021')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders description text', async () => {
|
||||
render(await ExperienceSection());
|
||||
expect(screen.getByText('Built critical systems.')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('empty state', () => {
|
||||
it('renders empty container when no items', async () => {
|
||||
vi.mocked(getCollection).mockResolvedValue(listResponse([]) as never);
|
||||
const { container } = render(await ExperienceSection());
|
||||
expect(container.firstChild).toBeEmptyDOMElement();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ExperienceCard } from '$entities/experience';
|
||||
import type { ExperienceRecord } from '$shared/api';
|
||||
import { getCollection } from '$shared/api';
|
||||
import { formatYearRange } from '$shared/lib';
|
||||
|
||||
/**
|
||||
* Experience section component.
|
||||
* Lists work history entries sorted by order field.
|
||||
*/
|
||||
export default async function ExperienceSection() {
|
||||
const { items } = await getCollection<ExperienceRecord>('experience', {
|
||||
sort: 'order',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{items.map((exp) => (
|
||||
<ExperienceCard
|
||||
key={exp.id}
|
||||
title={exp.role}
|
||||
company={exp.company}
|
||||
period={formatYearRange(exp.start_date, exp.end_date)}
|
||||
description={exp.description}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user