feat: refine portfolio content, contact, and supporting media

This commit is contained in:
2026-09-05 20:08:57 +03:00
parent 15bcdf7cec
commit 103427f95b
53 changed files with 824 additions and 204 deletions

View File

@@ -67,9 +67,11 @@ describe('raw prerendered document', () => {
expect(document.body.textContent).toContain('Secure self-hosted platform and lifecycle');
expect(document.body.textContent).toContain('Private self-hosted medication tracker');
expect(document.body.textContent).toContain('Linux');
const mailLinks = document.querySelectorAll('a[href="mailto:luca.pislaru@gmail.com"]');
expect(mailLinks).toHaveLength(2);
expect([...mailLinks].map((link) => link.textContent)).toEqual(['Email Luca', 'Email Luca']);
expect(document.querySelectorAll('a[href^="mailto:"]')).toHaveLength(0);
expect(html).not.toContain('luca.pislaru@gmail.com');
expect(document.querySelector('#start a[href="#contact"]')?.textContent).toBe('Contact Me');
expect(document.querySelector('#contact-email-details summary')?.textContent).toBe('Email Me');
expect(document.querySelector('.contact-email__address')?.textContent).toBe('luca.pislaru [at] gmail [dot] com');
expect(document.querySelector('nav a[href="#infrastructure"]')).not.toBeNull();
expect(snapshot).not.toBeNull();
expect(moduleScript).not.toBeNull();

View File

@@ -86,7 +86,7 @@ describe('approved public portfolio projection', () => {
]);
expect(content.projects.selected[1]?.contribution).toMatch(/collaborator/iu);
expect(content.projects.selected[1]?.outcome).toMatch(/0\.942 mAP@0\.5.*0\.198/iu);
expect(content.projects.selected[0]?.outcome).toContain('not presented as production-ready.');
expect(content.projects.selected[0]?.outcome).toContain('further work needed before a wider release.');
expect(content.systemsOperations.title).toBe('Professional systems operations');
expect(content.infrastructure.title).toBe('Secure self-hosted platform and lifecycle');
expect(content.projects.selected).toHaveLength(3);
@@ -98,13 +98,14 @@ describe('approved public portfolio projection', () => {
.toBe('Private game prototype');
expect(content.toolkit.flatMap((group) => group.technologies).map((technology) => technology.name))
.toEqual(expect.arrayContaining(['Linux', 'Docker', 'Python', 'Vue.js', 'Java']));
expect(content.contact).toEqual(expect.objectContaining({ email: 'luca.pislaru@gmail.com' }));
expect(content.contact).toEqual(expect.objectContaining({ email: { localPart: 'luca.pislaru', domain: 'gmail.com' } }));
expect(content.contact.social.map((link) => link.url)).toEqual([
'https://linkedin.com/in/luca-pisl',
'https://github.com/LucaPisl',
'https://gitlab.com/luca_pisl',
'https://linkedin.com/in/luca-pisl',
]);
const publishedReferences = [
content.contact.avatarAssetId,
...content.projects.selected.flatMap((project) => project.assetIds),
...content.projects.additional.flatMap((project) => project.assetIds),
...content.toolkit.flatMap((group) => group.technologies.flatMap((technology) =>

View File

@@ -158,32 +158,30 @@ describe('artifact verification', () => {
it.each([
{
name: 'a missing hero mailto link',
mutate: (html: string) => html.replace('href="mailto:luca.pislaru@gmail.com">Email Luca</a>', 'href="#selected-builds">Email Luca</a>'),
name: 'a missing hero contact link',
mutate: (html: string) => html.replace('href="#contact">Contact Me</a>', 'href="#selected-builds">Contact Me</a>'),
},
{
name: 'a duplicate mailto link beyond the hero and contact actions',
mutate: (html: string) => html.replace('</main>', '<a href="mailto:luca.pislaru@gmail.com">Email Luca</a></main>'),
},
{
name: 'a mailto link with an address that differs from public content',
mutate: (html: string) => html.replace('href="mailto:luca.pislaru@gmail.com">Email Luca</a>', 'href="mailto:wrong@example.test">Email Luca</a>'),
name: 'a missing native email disclosure',
mutate: (html: string) => html.replace('<summary>Email Me</summary>', '<span>Email Me</span>'),
},
{
name: 'a hidden mailto link outside the app root',
mutate: (html: string) => html.replace('</body>', '<a hidden href="mailto:luca.pislaru@gmail.com">Email Luca</a></body>'),
},
{
name: 'two mailto links placed beneath contact instead of one per section',
mutate: (html: string) => html
.replace('href="mailto:luca.pislaru@gmail.com">Email Luca</a>', 'href="#selected-builds">Email Luca</a>')
.replace('</footer>', '<a href="mailto:luca.pislaru@gmail.com">Email Luca</a></footer>'),
name: 'a plain address hidden in initial page data',
mutate: (html: string) => html.replace('</footer>', '<span hidden>luca.pislaru@gmail.com</span></footer>'),
},
])('rejects $name', async ({ mutate }) => {
const { directory, html, inputs, contract } = await writeValidArtifacts();
await writeFile(join(directory, 'index.html'), mutate(html));
await expect(verifyArtifactDirectory(directory, inputs, contract)).rejects.toThrow(/mailto/i);
await expect(verifyArtifactDirectory(directory, inputs, contract)).rejects.toThrow(/contact|email|mailto/i);
});
it.each([