feat: compose the portfolio journey layer

This commit is contained in:
2026-09-02 16:21:13 +03:00
parent 7e48aad6a8
commit 8c17af22a0
26 changed files with 962 additions and 368 deletions

View File

@@ -15,14 +15,13 @@ const sectionIds = [
] as const;
const sectionHeadings = [
'START',
'PROFILE',
'EXPERIENCE',
'INFRASTRUCTURE',
'SELECTED BUILDS',
'ADDITIONAL WORK',
'TOOLKIT',
'CONTACT',
'Profile',
'Experience',
'Infrastructure',
'Selected builds',
'Additional work',
'Toolkit',
'Contact',
] as const;
const navigationLabels: Readonly<Record<(typeof sectionIds)[number], string>> = {
@@ -90,14 +89,15 @@ const expectedVisibleTextSegments = (
content.navigation.map((item) => [item.id, item.label]),
);
const section = (
id: (typeof sectionIds)[number],
index: number,
id: Exclude<(typeof sectionIds)[number], 'start'>,
body: readonly string[],
eyebrow?: string,
): string[] => {
const label = navigationById.get(id);
if (label === undefined) throw new Error(`Missing navigation label: ${id}`);
const heading = label.toUpperCase();
return [`${String(index).padStart(2, '0')} / ${heading}`, heading, ...body];
return [eyebrow, label, ...body].filter(
(segment): segment is string => segment !== undefined,
);
};
const projectLinkText = (
project: PortfolioContent['projects']['selected'][number],
@@ -105,18 +105,19 @@ const expectedVisibleTextSegments = (
project.visibility === 'public' && project.url ? [project.title] : [];
return [
...sectionIds.map((id) => navigationLabels[id]),
content.identity.name,
content.identity.role,
...sectionIds.map((id) => navigationLabels[id]),
...section('start', 1, [content.identity.valueProposition]),
...section('profile', 2, [
content.identity.valueProposition,
'Explore work',
...section('profile', [
content.profile.introduction,
...content.profile.screeningFacts.flatMap((fact) => [
fact.label,
fact.value,
]),
]),
...section('experience', 3, [
...section('experience', [
...content.experience.flatMap((record) => [
record.role,
`${record.organization} · ${record.dates}${record.location === undefined ? '' : ` · ${record.location}`}`,
@@ -126,7 +127,7 @@ const expectedVisibleTextSegments = (
content.systemsOperations.summary,
...content.systemsOperations.evidence,
]),
...section('infrastructure', 4, [
...section('infrastructure', [
content.infrastructure.title,
content.infrastructure.summary,
...content.infrastructure.bands.map((band) => band.title),
@@ -137,7 +138,6 @@ const expectedVisibleTextSegments = (
]),
...section(
'selected-builds',
5,
content.projects.selected.flatMap((project) => [
project.title,
project.summary,
@@ -151,10 +151,10 @@ const expectedVisibleTextSegments = (
project.outcome,
...projectLinkText(project),
]),
'Selected work',
),
...section(
'additional-work',
6,
content.projects.additional.flatMap((project) => [
project.title,
project.summary,
@@ -165,19 +165,18 @@ const expectedVisibleTextSegments = (
),
...section(
'toolkit',
7,
content.toolkit.flatMap((group) => [
group.title,
...group.technologies.map((technology) => technology.name),
]),
),
...section('contact', 8, [
content.identity.name,
content.identity.role,
...section('contact', [
"Thanks for making the trip. The road's open if you'd like to build something together.",
'Start a conversation',
content.contact.email,
content.contact.cvMessage,
...content.contact.social.map((link) => link.service),
]),
], 'Destination'),
];
};
@@ -347,7 +346,7 @@ test('keeps every raw SSR reading-path segment visible without JavaScript', asyn
await expect(page.locator('h1:visible')).toHaveCount(1);
await expect(page.locator('h1')).toHaveText('Luca Pîslaru');
await expect(page.locator('.site-header > p').first()).toHaveText(
await expect(page.locator('.hero-journey__role')).toHaveText(
'System Administrator & Full-Stack Developer',
);
await expect(page.locator('main')).toBeVisible();
@@ -381,7 +380,7 @@ test('keeps every raw SSR reading-path segment visible without JavaScript', asyn
const email = page.locator('a[href="mailto:luca.pislaru@gmail.com"]');
await expect(email).toBeVisible();
await expect(email).toHaveText('luca.pislaru@gmail.com');
await expect(email).toHaveText('Start a conversation');
await expect(
page.getByText(
'For a current CV or role-specific information, contact me directly.',