feat: compose the portfolio journey layer
This commit is contained in:
@@ -29,22 +29,56 @@ describe('semantic portfolio document', () => {
|
||||
it('renders the complete landmark and heading reading structure on the server', async () => {
|
||||
const document = await renderedDocument();
|
||||
|
||||
expect(document.querySelectorAll('header')).toHaveLength(1);
|
||||
expect(document.querySelectorAll('.site-header')).toHaveLength(1);
|
||||
expect(document.querySelector('nav[aria-label="Portfolio sections"]')).not.toBeNull();
|
||||
expect(document.querySelectorAll('main')).toHaveLength(1);
|
||||
expect(document.querySelectorAll('footer')).toHaveLength(1);
|
||||
expect(document.querySelectorAll('h1')).toHaveLength(1);
|
||||
expect(document.querySelector('h1')?.textContent).toBe('Luca Pîslaru');
|
||||
expect(document.querySelector('#start h1')?.textContent).toBe('Luca Pîslaru');
|
||||
expect([...document.querySelectorAll('main > section')].map((section) => section.id)).toEqual([
|
||||
'start', 'profile', 'experience', 'infrastructure', 'selected-builds', 'additional-work', 'toolkit', 'contact',
|
||||
]);
|
||||
expect([...document.querySelectorAll('main > section')].every((section) => section.hasAttribute('aria-labelledby'))).toBe(true);
|
||||
expect([...document.querySelectorAll('main > section > h2')].map((heading) => heading.textContent)).toEqual([
|
||||
'START', 'PROFILE', 'EXPERIENCE', 'INFRASTRUCTURE', 'SELECTED BUILDS', 'ADDITIONAL WORK', 'TOOLKIT', 'CONTACT',
|
||||
'Profile', 'Experience', 'Infrastructure', 'Selected builds', 'Additional work', 'Toolkit', 'Contact',
|
||||
]);
|
||||
expect([...document.querySelectorAll('main > section')].map((section) => section.getAttribute('data-layout'))).toEqual([
|
||||
'hero', 'right-rail', 'left-timeline', 'full-diagram', 'project-stage', 'compact-rail', 'toolkit-field', 'destination',
|
||||
]);
|
||||
expect(document.querySelectorAll('.route-label')).toHaveLength(0);
|
||||
expect(document.querySelector('h2 + h4')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders the exact first-screen hierarchy and destination actions', async () => {
|
||||
const document = await renderedDocument();
|
||||
const hero = document.querySelector('.hero-journey__content')!;
|
||||
|
||||
expect([...hero.children].map((element) => element.textContent?.trim())).toEqual([
|
||||
'Luca Pîslaru',
|
||||
'System Administrator & Full-Stack Developer',
|
||||
'Building and operating reliable systems and software.',
|
||||
'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(document.body.textContent).not.toMatch(/[–—]/u);
|
||||
});
|
||||
|
||||
it('assigns explicit project priority without promoting research exploration', async () => {
|
||||
const document = await renderedDocument();
|
||||
const priorities = [...document.querySelectorAll('#selected-builds article')].map((article) => [
|
||||
article.querySelector('h3')?.textContent,
|
||||
article.getAttribute('data-project-priority'),
|
||||
]);
|
||||
|
||||
expect(priorities).toEqual([
|
||||
['Private self-hosted medication tracker', 'primary'],
|
||||
['Footy Tracker', 'primary'],
|
||||
['Opinion Dynamics Simulation', 'supporting'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps native section links and visible contact available without JavaScript', async () => {
|
||||
const document = await renderedDocument();
|
||||
const navigation = document.querySelector('nav[aria-label="Portfolio sections"]')!;
|
||||
@@ -53,7 +87,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('hello@example.test');
|
||||
expect(email?.textContent).toBe('Start a conversation');
|
||||
expect(document.body.textContent).toContain('For a current CV or role-specific information, contact me directly.');
|
||||
});
|
||||
|
||||
@@ -89,7 +123,7 @@ describe('semantic portfolio document', () => {
|
||||
const document = await renderedDocumentFor(reorderedInputs);
|
||||
|
||||
expect([...document.querySelectorAll('main > section > h2')].map((heading) => heading.textContent)).toEqual([
|
||||
'START', 'PROFILE', 'EXPERIENCE', 'INFRASTRUCTURE', 'SELECTED BUILDS', 'ADDITIONAL WORK', 'TOOLKIT', 'CONTACT',
|
||||
'Profile', 'Experience', 'Infrastructure', 'Selected builds', 'Additional work', 'Toolkit', 'Contact',
|
||||
]);
|
||||
expect([...document.querySelectorAll('nav a')].map((link) => [link.getAttribute('href'), link.textContent])).toEqual([
|
||||
['#start', 'Start'], ['#profile', 'Profile'], ['#experience', 'Career'], ['#infrastructure', 'Infra'],
|
||||
|
||||
Reference in New Issue
Block a user