feat: surface availability and operations evidence

This commit is contained in:
2026-09-04 20:34:19 +03:00
parent 3509f5fbdf
commit 55158d490e
13 changed files with 147 additions and 22 deletions

View File

@@ -55,7 +55,8 @@ test("tabs from the skip link through navigation and every contact action", asyn
const expectedTargets = [
{ selector: ".skip-link", href: "#portfolio-content" },
...navHrefs.map((href) => ({ selector: `nav a[href="${href}"]`, href })),
{ selector: ".hero-journey__action", href: "#selected-builds" },
{ selector: '.hero-journey__action--primary', href: 'mailto:luca.pislaru@gmail.com' },
{ selector: '.hero-journey__actions a[href="#selected-builds"]', href: "#selected-builds" },
{
selector: 'a[href="https://github.com/LucaPisl/footy-tracker"]',
href: "https://github.com/LucaPisl/footy-tracker",

View File

@@ -110,6 +110,8 @@ const expectedVisibleTextSegments = (
content.identity.name,
content.identity.role,
content.identity.valueProposition,
content.identity.availability,
"Email Luca",
"Explore work",
...section("profile", [
content.profile.introduction,
@@ -140,6 +142,11 @@ const expectedVisibleTextSegments = (
...content.infrastructure.bands.map(
(band) => `${band.title}: ${band.summary}`,
),
content.infrastructure.featuredOperation.title,
content.infrastructure.featuredOperation.context,
...content.infrastructure.featuredOperation.actions,
"Outcome:",
content.infrastructure.featuredOperation.outcome,
]),
...section(
"selected-builds",
@@ -178,8 +185,8 @@ const expectedVisibleTextSegments = (
...section(
"contact",
[
"Thanks for making the trip. The road's open if you'd like to build something together.",
"Start a conversation",
content.contact.introduction,
"Email Luca",
content.contact.email,
content.contact.cvMessage,
...content.contact.social.map((link) => link.service),

View File

@@ -100,7 +100,8 @@ test('exposes the complete semantic portfolio from the generated document', asyn
);
await expect(page.locator('.route-label')).toHaveCount(0);
await expect(page.getByRole('link', { name: 'Explore work' })).toHaveAttribute('href', '#selected-builds');
await expect(page.getByRole('link', { name: 'Start a conversation' })).toHaveAttribute('href', 'mailto:luca.pislaru@gmail.com');
await expect(page.getByRole('link', { name: 'Email Luca' })).toHaveCount(2);
await expect(page.locator('[data-featured-operation]')).toContainText('without data loss');
expect(
await page.locator('h1, h2, h3').evaluateAll((headings) => {
const levels = headings.map((heading) =>
@@ -150,8 +151,11 @@ test('keeps canonical native anchors and safe external destinations', async ({
}
const email = page.locator('a[href^="mailto:"]');
await expect(email).toHaveCount(1);
await expect(email).toHaveText('Start a conversation');
await expect(email).toHaveCount(2);
await expect(email).toHaveText(['Email Luca', 'Email Luca']);
expect(await email.evaluateAll((links) => new Set(links.map((link) => link.getAttribute('href'))))).toEqual(
new Set(['mailto:luca.pislaru@gmail.com']),
);
const externalLinks = page.locator('#contact a[target="_blank"]');
await expect(externalLinks).toHaveCount(3);
@@ -162,6 +166,7 @@ test('keeps canonical native anchors and safe external destinations', async ({
return (
link instanceof HTMLAnchorElement &&
link.protocol === 'https:' &&
rel.has('me') &&
rel.has('noopener') &&
rel.has('noreferrer')
);

View File

@@ -53,15 +53,23 @@ describe('semantic portfolio document', () => {
const document = await renderedDocument();
const hero = document.querySelector('.hero-journey__content')!;
expect([...hero.children].map((element) => element.textContent?.trim())).toEqual([
expect([...hero.children].flatMap((element) =>
element.classList.contains('hero-journey__actions')
? [...element.children].map((action) => action.textContent?.trim())
: [element.textContent?.trim()],
)).toEqual([
'Luca Pîslaru',
'System Administrator & Full-Stack Developer',
'Building and operating reliable systems and software.',
validInputs.content.identity.valueProposition,
validInputs.content.identity.availability,
'Email Luca',
'Explore work',
]);
expect(hero.querySelector('a')?.getAttribute('href')).toBe('#selected-builds');
expect(document.querySelector('a[href="mailto:hello@example.test"]')?.textContent).toBe('Start a conversation');
expect(document.body.textContent).toContain("Thanks for making the trip. The road's open if you'd like to build something together.");
expect(hero.querySelector('a[href="mailto:hello@example.test"]')?.textContent).toBe('Email Luca');
expect(document.querySelector('[data-featured-operation]')?.textContent).toContain(
validInputs.content.infrastructure.featuredOperation.title,
);
expect(document.querySelector('#contact')?.textContent).toContain('System Administrator');
expect(document.body.textContent).not.toMatch(/[–—]/u);
});
@@ -87,7 +95,7 @@ describe('semantic portfolio document', () => {
'#start', '#profile', '#experience', '#infrastructure', '#selected-builds', '#additional-work', '#toolkit', '#contact',
]);
const email = document.querySelector('a[href="mailto:hello@example.test"]');
expect(email?.textContent).toBe('Start a conversation');
expect(email?.textContent).toBe('Email Luca');
expect(document.body.textContent).toContain('For a current CV or role-specific information, contact me directly.');
});

View File

@@ -178,13 +178,11 @@ describe("semantic section components", () => {
});
expect(wrapper.get('a[href="mailto:hello@example.test"]').text()).toBe(
"Start a conversation",
);
expect(wrapper.text()).toContain(
"Thanks for making the trip. The road's open if you'd like to build something together.",
"Email Luca",
);
expect(wrapper.text()).toContain(contact.introduction);
const social = wrapper.get('a[href="https://github.com/example"]');
expect(social.text()).toBe("GitHub");
expect(social.attributes("rel")).toBe("noopener noreferrer");
expect(social.attributes("rel")).toBe("me noopener noreferrer");
});
});