feat: refine portfolio content, contact, and supporting media
This commit is contained in:
@@ -79,7 +79,7 @@ async function enterState(
|
||||
for (const link of links) link.closest("li")?.remove();
|
||||
});
|
||||
await expect(page.locator('#contact a[target="_blank"]')).toHaveCount(0);
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ test("forced colors preserves visible focus, controls, content, and the Contact
|
||||
|
||||
await clickNavigationLink(page, "#contact");
|
||||
await expect(page.locator("#contact-heading")).toBeFocused();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
expect(
|
||||
await page.evaluate(
|
||||
() =>
|
||||
|
||||
@@ -151,7 +151,7 @@ async function assertReflowGeometry(page: Page): Promise<void> {
|
||||
|
||||
await clickNavigationLink(page, "#contact");
|
||||
await expect(page.locator("#contact-heading")).toBeFocused();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
}
|
||||
|
||||
test("reflows at a 320 CSS pixel mobile viewport without lost content or controls", async ({
|
||||
|
||||
96
tests/browser/contact-refinements.spec.ts
Normal file
96
tests/browser/contact-refinements.spec.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
import { expect, test } from '../helpers/serve-dist';
|
||||
|
||||
test('start navigation, contact identity, and toolkit icons use the approved content', async ({ page, distUrl }) => {
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
const response = await page.goto(distUrl);
|
||||
const html = await response!.text();
|
||||
expect(html).not.toContain('luca.pislaru@gmail.com');
|
||||
expect(html).not.toContain('mailto:');
|
||||
await expect(page.locator('.contact-email')).toHaveAttribute('data-enhanced', 'true');
|
||||
await page.locator('.hero-journey__action--primary').click();
|
||||
await expect(page).toHaveURL(/#contact$/);
|
||||
await expect(page.locator('#contact')).toBeInViewport();
|
||||
await expect(page.locator('.contact-avatar')).toBeVisible();
|
||||
await expect(page.locator('.contact-social-link')).toHaveText(['LinkedIn', 'GitHub', 'GitLab']);
|
||||
const missing = await page.locator('[data-testid="toolkit-technology"]').evaluateAll(items => items.filter(item => !item.querySelector('svg')).map(item => item.textContent));
|
||||
expect(missing).toEqual([]);
|
||||
for (const name of ['SPSS', 'SoccerNet', 'Microsoft Excel', 'Btrfs', 'rsync']) {
|
||||
await expect(page.locator('#toolkit')).not.toContainText(name);
|
||||
}
|
||||
});
|
||||
|
||||
test('email is revealed on focus, with an explicit disclosure and copy fallback', async ({ page, distUrl }) => {
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await page.goto(`${distUrl}/#contact`);
|
||||
const email = page.getByRole('link', { name: 'Email Me', exact: true });
|
||||
await expect(email).toHaveAttribute('href', '#contact-email-details');
|
||||
await expect(page.locator('.contact-email__preview')).not.toBeVisible();
|
||||
await email.focus();
|
||||
await expect(email).toHaveAttribute('href', 'mailto:luca.pislaru@gmail.com');
|
||||
await page.locator('#contact summary').click();
|
||||
await expect(page.locator('.contact-email__address')).toHaveText('luca.pislaru@gmail.com');
|
||||
await page.getByRole('button', { name: 'Copy email' }).click();
|
||||
await expect(page.locator('.contact-email__status')).toHaveText(/Copied|Select the address to copy it\./);
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(page.locator('#contact summary')).toBeFocused();
|
||||
await expect(page.locator('#contact-email-details')).not.toHaveAttribute('open');
|
||||
});
|
||||
|
||||
test('contact fits desktop and stays aligned and usable across narrow widths', async ({ page, distUrl }, testInfo) => {
|
||||
test.skip(testInfo.project.name !== 'desktop-chromium', 'Viewport matrix is run once.');
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await page.goto(`${distUrl}/#contact`);
|
||||
for (const [width, height] of [[1440, 900], [1280, 720], [768, 1024], [390, 844], [320, 740], [844, 390]]) {
|
||||
await page.setViewportSize({ width: width!, height: height! });
|
||||
await page.locator('#contact').scrollIntoViewIfNeeded();
|
||||
const geometry = await page.locator('#contact').evaluate(section => {
|
||||
const box = section.getBoundingClientRect();
|
||||
const avatar = section.querySelector('.contact-avatar')!.getBoundingClientRect();
|
||||
return {
|
||||
height: box.height,
|
||||
overflow: document.documentElement.scrollWidth > innerWidth,
|
||||
socialY: [...section.querySelectorAll('.contact-social-link')].map(el => el.getBoundingClientRect().y),
|
||||
avatarInside: avatar.right <= box.right && avatar.bottom < section.querySelector('.contact-destination__copy')!.getBoundingClientRect().top,
|
||||
};
|
||||
});
|
||||
expect(geometry.overflow, `${width}px overflow`).toBe(false);
|
||||
expect(Math.max(...geometry.socialY) - Math.min(...geometry.socialY), `${width}px social alignment`).toBeLessThan(1);
|
||||
expect(geometry.avatarInside, `${width}px avatar`).toBe(true);
|
||||
if (width! >= 1280) expect(geometry.height).toBeLessThan(height! - 140);
|
||||
await page.screenshot({ path: testInfo.outputPath(`contact-${width}x${height}.png`) });
|
||||
}
|
||||
});
|
||||
|
||||
test('native email disclosure remains usable without JavaScript', async ({ browser, distUrl }) => {
|
||||
const context = await browser.newContext({ javaScriptEnabled: false, viewport: { width: 390, height: 844 } });
|
||||
const page = await context.newPage();
|
||||
await page.goto(`${distUrl}/#contact`);
|
||||
await expect(page.locator('.contact-email__address')).not.toBeVisible();
|
||||
await page.locator('#contact summary').click();
|
||||
await expect(page.locator('.contact-email__address')).toHaveText('luca.pislaru [at] gmail [dot] com');
|
||||
await expect(page.locator('.video-fallback')).toHaveAttribute('href', '/assets/project-private-game-loop.mp4');
|
||||
await context.close();
|
||||
});
|
||||
|
||||
test('reduced motion keeps the gameplay still until Play and supports pause', async ({ page, distUrl }) => {
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await page.goto(distUrl);
|
||||
const figure = page.locator('.project-media--video');
|
||||
await figure.scrollIntoViewIfNeeded();
|
||||
await expect(figure.locator('source')).toHaveCount(0);
|
||||
await figure.getByRole('button', { name: 'Play video' }).click();
|
||||
await expect(figure.getByRole('button', { name: 'Pause video' })).toBeVisible();
|
||||
expect(await figure.locator('video').evaluate(element => { const video = element as HTMLVideoElement; return { muted: video.muted, loop: video.loop, paused: video.paused }; })).toEqual({ muted: true, loop: true, paused: false });
|
||||
await figure.getByRole('button', { name: 'Pause video' }).click();
|
||||
await expect(figure.getByRole('button', { name: 'Play video' })).toBeVisible();
|
||||
await expect(figure.locator('source')).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('contact and supporting media have no serious accessibility violations', async ({ page, distUrl }) => {
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await page.goto(`${distUrl}/#contact`);
|
||||
await page.locator('#contact summary').click();
|
||||
const result = await new AxeBuilder({ page }).include('#contact').include('#additional-work').analyze();
|
||||
expect(result.violations.filter(violation => ['serious', 'critical'].includes(violation.impact ?? ''))).toEqual([]);
|
||||
});
|
||||
@@ -226,10 +226,10 @@ test('an aborted generated client entry leaves the complete SSR portfolio usable
|
||||
await expect(page.locator('main > section')).toHaveCount(8);
|
||||
await expect(page.locator('nav a')).toHaveCount(8);
|
||||
await expect(
|
||||
page.locator('a[href="mailto:luca.pislaru@gmail.com"]'),
|
||||
page.locator('#contact summary'),
|
||||
).toBeVisible();
|
||||
await page.locator('nav a[href="#contact"]').click();
|
||||
await expect(page).toHaveURL(`${distUrl}/#contact`);
|
||||
await expect(page.locator('#contact')).toBeInViewport();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ 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--primary', href: 'mailto:luca.pislaru@gmail.com' },
|
||||
{ selector: '.hero-journey__action--primary', href: '#contact' },
|
||||
{ selector: '.hero-journey__actions a[href="#selected-builds"]', href: "#selected-builds" },
|
||||
{
|
||||
selector: 'a[href="https://github.com/LucaPisl/footy-tracker"]',
|
||||
@@ -66,6 +66,14 @@ test("tabs from the skip link through navigation and every contact action", asyn
|
||||
'a[href="https://github.com/LucaPisl/opinion-dynamics-simulation"]',
|
||||
href: "https://github.com/LucaPisl/opinion-dynamics-simulation",
|
||||
},
|
||||
{
|
||||
selector: '.video-controls button',
|
||||
href: null,
|
||||
},
|
||||
{
|
||||
selector: '.video-fallback',
|
||||
href: '/assets/project-private-game-loop.mp4',
|
||||
},
|
||||
{
|
||||
selector:
|
||||
'a[href="https://github.com/LucaPisl/CurrencyConverterAvalonia"]',
|
||||
@@ -76,9 +84,17 @@ test("tabs from the skip link through navigation and every contact action", asyn
|
||||
href: "https://github.com/LucaPisl/LinuxModdingGuide",
|
||||
},
|
||||
{
|
||||
selector: '#contact a[href^="mailto:"]',
|
||||
selector: '#contact :is(a, summary):text-is("Email Me")',
|
||||
href: "mailto:luca.pislaru@gmail.com",
|
||||
},
|
||||
{
|
||||
selector: '#contact summary',
|
||||
href: null,
|
||||
},
|
||||
{
|
||||
selector: '#contact a[href="https://linkedin.com/in/luca-pisl"]',
|
||||
href: "https://linkedin.com/in/luca-pisl",
|
||||
},
|
||||
{
|
||||
selector: '#contact a[href="https://github.com/LucaPisl"]',
|
||||
href: "https://github.com/LucaPisl",
|
||||
@@ -87,17 +103,13 @@ test("tabs from the skip link through navigation and every contact action", asyn
|
||||
selector: '#contact a[href="https://gitlab.com/luca_pisl"]',
|
||||
href: "https://gitlab.com/luca_pisl",
|
||||
},
|
||||
{
|
||||
selector: '#contact a[href="https://linkedin.com/in/luca-pisl"]',
|
||||
href: "https://linkedin.com/in/luca-pisl",
|
||||
},
|
||||
];
|
||||
|
||||
for (const target of expectedTargets) {
|
||||
await page.keyboard.press("Tab");
|
||||
const locator = page.locator(target.selector);
|
||||
await expect(locator).toBeFocused();
|
||||
await expect(locator).toHaveAttribute("href", target.href);
|
||||
if (target.href !== null) await expect(locator).toHaveAttribute("href", target.href);
|
||||
await assertVisibleUnobscuredFocus(page);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ test('F7 replaces a failed poster with exactly one CSS fallback and keeps its de
|
||||
expect(await readUnhandledRejections(page)).toEqual([]);
|
||||
});
|
||||
|
||||
test('F8 remains authenticated and request-free while the public manifest has no approved video', async ({ page, distUrl }) => {
|
||||
test('F8 remains authenticated and request-free before the gameplay video is requested', async ({ page, distUrl }) => {
|
||||
const mediaRequests: string[] = [];
|
||||
page.on('request', (request) => {
|
||||
if (/\.(?:mp4|webm)(?:$|[?#])/iu.test(request.url())) mediaRequests.push(request.url());
|
||||
@@ -40,7 +40,8 @@ test('F8 remains authenticated and request-free while the public manifest has no
|
||||
await page.goto(authorizedFaultUrl(distUrl, 'F8-video-failure'), { waitUntil: 'networkidle' });
|
||||
|
||||
expect((await readFaultSnapshot(page)).fault).toBe('F8-video-failure');
|
||||
await expect(page.locator('video, video source')).toHaveCount(0);
|
||||
await expect(page.locator('video')).toHaveCount(1);
|
||||
await expect(page.locator('video source')).toHaveCount(0);
|
||||
expect(mediaRequests).toEqual([]);
|
||||
await assertSemanticFaultOracle(page);
|
||||
expect(errors.pageErrors).toEqual([]);
|
||||
|
||||
@@ -31,7 +31,7 @@ test('approved still evidence uses manifest assets and intrinsic lazy image sema
|
||||
await expect(page.locator('main > section')).toHaveCount(8);
|
||||
await expect(page.locator('#selected-builds article')).toHaveCount(3);
|
||||
await expect(page.locator('#additional-work article')).toHaveCount(4);
|
||||
await expect(page.locator('[data-project-media]')).toHaveCount(approvedStillCount);
|
||||
await expect(page.locator('[data-project-media]')).toHaveCount(projectPresentations.length);
|
||||
await expect(page.locator('[data-project-media] img')).toHaveCount(expectedImages.length);
|
||||
expect(await page.locator('[data-project-media] img').evaluateAll((images) => images.map((image) => ({
|
||||
src: new URL((image as HTMLImageElement).src).pathname,
|
||||
@@ -41,8 +41,9 @@ test('approved still evidence uses manifest assets and intrinsic lazy image sema
|
||||
loading: (image as HTMLImageElement).loading,
|
||||
decoding: (image as HTMLImageElement).decoding,
|
||||
})))).toEqual(expectedImages.map((image) => ({ ...image, loading: 'lazy', decoding: 'async' })));
|
||||
await expect(page.locator('video, video source')).toHaveCount(0);
|
||||
await expect(page.locator('[data-project-id="private-medication-tracker"] a')).toHaveCount(0);
|
||||
await expect(page.locator('video')).toHaveCount(1);
|
||||
await expect(page.locator('video source')).toHaveCount(0);
|
||||
await expect(page.locator('[data-project-id="private-medication-tracker"] a.project-link')).toHaveCount(0);
|
||||
await expect(page.locator('.journey-poster')).not.toHaveAttribute('src', /.+/u);
|
||||
expect(videoRequests).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -37,10 +37,10 @@ const navigationLabels: Readonly<Record<(typeof sectionIds)[number], string>> =
|
||||
};
|
||||
|
||||
const visibleTextLeafSelector =
|
||||
"h1,h2,h3,h4,p,dt,dd,li,figcaption,caption,th,td,a,svg text";
|
||||
"h1,h2,h3,h4,p,dt,dd,li,figcaption,caption,th,td,a,summary,svg text";
|
||||
const visibleTextSelector = [
|
||||
".site-header :is(h1,h2,h3,h4,p,dt,dd,li,figcaption,caption,th,td,a)",
|
||||
".portfolio-main :is(h1,h2,h3,h4,p,dt,dd,li,figcaption,caption,th,td,a)",
|
||||
".portfolio-main :is(h1,h2,h3,h4,p,dt,dd,li,figcaption,caption,th,td,a,summary)",
|
||||
".portfolio-main svg text",
|
||||
].join(",");
|
||||
|
||||
@@ -111,6 +111,7 @@ const expectedVisibleTextSegments = (
|
||||
(project.media ?? []).flatMap((presentation) => [
|
||||
presentation.caption,
|
||||
presentation.longDescription,
|
||||
...(presentation.kind === "video" ? ["Open gameplay video"] : []),
|
||||
...(presentation.kind === "chart"
|
||||
? [
|
||||
"Variables",
|
||||
@@ -136,7 +137,7 @@ const expectedVisibleTextSegments = (
|
||||
content.identity.role,
|
||||
content.identity.valueProposition,
|
||||
content.identity.availability,
|
||||
"Email Luca",
|
||||
"Contact Me",
|
||||
"Explore work",
|
||||
...section("profile", [
|
||||
content.profile.introduction,
|
||||
@@ -197,7 +198,6 @@ const expectedVisibleTextSegments = (
|
||||
project.summary,
|
||||
...projectMediaText(project),
|
||||
project.contribution,
|
||||
project.outcome,
|
||||
...projectLinkText(project),
|
||||
]),
|
||||
),
|
||||
@@ -212,8 +212,7 @@ const expectedVisibleTextSegments = (
|
||||
"contact",
|
||||
[
|
||||
content.contact.introduction,
|
||||
"Email Luca",
|
||||
content.contact.email,
|
||||
"Email Me",
|
||||
content.contact.cvMessage,
|
||||
...content.contact.social.map((link) => link.service),
|
||||
],
|
||||
@@ -230,6 +229,7 @@ const rawVisibleTextSegments = async (
|
||||
({ html, leafSelector, rootSelector }) => {
|
||||
const document = new DOMParser().parseFromString(html, "text/html");
|
||||
const isHidden = (element: Element): boolean => {
|
||||
if (element.closest('.project-media--video[data-enhanced="false"] .video-controls')) return true;
|
||||
for (
|
||||
let current: Element | null = element;
|
||||
current;
|
||||
@@ -420,12 +420,14 @@ test("keeps every raw SSR reading-path segment visible without JavaScript", asyn
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
const email = page.locator('a[href="mailto:luca.pislaru@gmail.com"]');
|
||||
await expect(email).toHaveCount(2);
|
||||
await expect(email).toHaveText(["Email Luca", "Email Luca"]);
|
||||
await expect(page.locator('a[href^="mailto:"]')).toHaveCount(0);
|
||||
const email = page.locator('#contact-email-details');
|
||||
await email.locator('summary').click();
|
||||
await expect(email.locator('.contact-email__address')).toBeVisible();
|
||||
await expect(email.locator('.contact-email__address')).toHaveText('luca.pislaru [at] gmail [dot] com');
|
||||
await expect(
|
||||
page.getByText(
|
||||
"For a current CV or role-specific information, contact me directly.",
|
||||
"Get in touch for my CV or to talk about a role.",
|
||||
{ exact: true },
|
||||
),
|
||||
).toBeVisible();
|
||||
@@ -528,5 +530,5 @@ test("retains native section navigation when scripts are disabled", async ({
|
||||
|
||||
await expect(page).toHaveURL(`${distUrl}/#contact`);
|
||||
await expect(page.locator("#contact")).toBeInViewport();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ test('boots reduced motion without requesting the live scene or automatic media'
|
||||
await expect(page.locator('.journey-canvas')).toHaveCount(0);
|
||||
await expect(page.locator('.journey-hud')).toBeVisible();
|
||||
await expect(page.locator('nav[aria-label="Portfolio sections"]')).toBeVisible();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
await expect(page.getByRole('status')).toContainText('reduced motion requested');
|
||||
expect(requests.some((url) => environmentChunkPattern.test(url))).toBe(false);
|
||||
await expect(page.locator('video[src], video source[src]')).toHaveCount(0);
|
||||
|
||||
@@ -151,7 +151,7 @@ test('renders the validated eight-section portfolio structure before responsive
|
||||
.toEqual(['#start', '#profile', '#experience', '#infrastructure', '#selected-builds', '#additional-work', '#toolkit', '#contact']);
|
||||
await expect(page.locator('#selected-builds article, #additional-work article')).not.toHaveCount(0);
|
||||
await expect(page.locator('#toolkit [data-testid="toolkit-technology"]')).not.toHaveCount(0);
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toHaveCount(1);
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toHaveCount(1);
|
||||
await expect(page.locator('#contact a[target="_blank"]')).not.toHaveCount(0);
|
||||
});
|
||||
|
||||
|
||||
@@ -100,11 +100,10 @@ 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: 'Email Luca' })).toHaveCount(2);
|
||||
await expect(page.getByRole('link', { name: 'Contact Me' })).toHaveAttribute('href', '#contact');
|
||||
await expect(page.getByRole('link', { name: 'Email Me' })).toHaveCount(1);
|
||||
await expect(page.locator('[data-featured-operation]')).toContainText('without data loss');
|
||||
expect(await page.locator('[data-testid="toolkit-technology"]', { hasText: 'DNS' }).locator('span').evaluate(
|
||||
(label) => getComputedStyle(label).gridColumn,
|
||||
)).toBe('1 / -1');
|
||||
await expect(page.locator('[data-testid="toolkit-technology"]', { hasText: 'DNS' }).locator('svg')).toHaveCount(1);
|
||||
expect(await page.locator('.hero-journey').evaluate((hero) => {
|
||||
const content = hero.querySelector('.hero-journey__content')!;
|
||||
const heroStyle = getComputedStyle(hero);
|
||||
@@ -172,8 +171,10 @@ test('keeps canonical native anchors and safe external destinations', async ({
|
||||
}
|
||||
|
||||
const email = page.locator('a[href^="mailto:"]');
|
||||
await expect(email).toHaveCount(2);
|
||||
await expect(email).toHaveText(['Email Luca', 'Email Luca']);
|
||||
await expect(email).toHaveCount(0);
|
||||
await page.getByRole('link', { name: 'Email Me' }).focus();
|
||||
await expect(email).toHaveCount(1);
|
||||
await expect(email).toHaveText('Email Me');
|
||||
expect(await email.evaluateAll((links) => [...new Set(links.map((link) => link.getAttribute('href')))])).toEqual(
|
||||
['mailto:luca.pislaru@gmail.com'],
|
||||
);
|
||||
|
||||
@@ -25,7 +25,7 @@ test("falls back to one poster and no scene loop when the deferred scene chunk i
|
||||
await expect(page.locator("main > section")).toHaveCount(8);
|
||||
await revealNavigationLinks(page);
|
||||
await expect(page.locator('nav a[href="#contact"]')).toBeVisible();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
await expect
|
||||
.poll(
|
||||
async () => (await readSceneInstrumentation(page)).activeAnimationFrames,
|
||||
@@ -74,7 +74,7 @@ test("contains a WebGL initialization failure without hiding the portfolio", asy
|
||||
await expect(page.locator(".journey-poster")).toHaveCount(1);
|
||||
await expect(page.locator(".journey-canvas")).toHaveCount(0);
|
||||
await expect(page.locator("#portfolio-content")).toBeVisible();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
await expect
|
||||
.poll(
|
||||
async () => (await readSceneInstrumentation(page)).activeAnimationFrames,
|
||||
|
||||
@@ -466,7 +466,7 @@ test.describe("production visual composition", () => {
|
||||
});
|
||||
await page.locator('nav a[href="#contact"]').click();
|
||||
await expect(page.locator("#contact-heading")).toBeFocused();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
await expect(page.locator('#contact a[target="_blank"]')).toHaveCount(0);
|
||||
await captureViewport(page, testInfo, "visual-missing-social");
|
||||
});
|
||||
@@ -482,7 +482,7 @@ test.describe("production visual composition", () => {
|
||||
await expect(page.locator(".journey-hud__section")).toHaveText("Contact");
|
||||
await expect(page.locator(".journey-hud__arrival")).toHaveText("ARRIVED");
|
||||
await expect(page.locator("#contact")).toBeInViewport();
|
||||
await expect(page.locator('#contact a[href^="mailto:"]')).toBeVisible();
|
||||
await expect(page.locator('#contact :is(a, summary):text-is("Email Me")')).toBeVisible();
|
||||
await captureViewport(page, testInfo, "visual-contact-arrival");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user