fix: close final portfolio quality gaps

This commit is contained in:
2026-09-02 17:38:11 +03:00
parent 0899b6b00f
commit b4728ceef0
24 changed files with 1822 additions and 889 deletions

View File

@@ -1,133 +1,251 @@
import { expect, expectInsetFocusIndicator, test } from '../helpers/serve-dist';
import { expect, expectInsetFocusIndicator, test } from "../helpers/serve-dist";
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
const OriginalAudioContext = window.AudioContext;
(window as unknown as { __audioConstructed: number }).__audioConstructed = 0;
(window as unknown as { __audioContexts: AudioContext[] }).__audioContexts = [];
(window as unknown as { __audioConstructed: number }).__audioConstructed =
0;
(window as unknown as { __audioContexts: AudioContext[] }).__audioContexts =
[];
if (!OriginalAudioContext) return;
class TrackingAudioContext extends OriginalAudioContext {
constructor(options?: AudioContextOptions) {
super(options);
const state = window as unknown as { __audioConstructed: number; __audioContexts: AudioContext[] };
const state = window as unknown as {
__audioConstructed: number;
__audioContexts: AudioContext[];
};
state.__audioConstructed += 1;
state.__audioContexts.push(this);
}
}
Object.defineProperty(window, 'AudioContext', { configurable: true, value: TrackingAudioContext });
Object.defineProperty(window, "AudioContext", {
configurable: true,
value: TrackingAudioContext,
});
});
});
test('starts Web Audio synchronously from the visitor gesture and exposes accessible controls', async ({ page, distUrl }) => {
await page.goto(distUrl, { waitUntil: 'domcontentloaded' });
test("starts Web Audio synchronously from the visitor gesture and exposes accessible controls", async ({
page,
distUrl,
}) => {
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
await page.evaluate(() => {
(window as unknown as { __constructedDuringGesture?: number }).__constructedDuringGesture = -1;
window.addEventListener('click', (event) => {
if ((event.target as HTMLElement | null)?.textContent?.includes('START THE DRIVE')) {
const state = window as unknown as { __audioConstructed: number; __constructedDuringGesture: number };
(
window as unknown as { __constructedDuringGesture?: number }
).__constructedDuringGesture = -1;
window.addEventListener("click", (event) => {
if (
(event.target as HTMLElement | null)?.textContent?.includes(
"START THE DRIVE",
)
) {
const state = window as unknown as {
__audioConstructed: number;
__constructedDuringGesture: number;
};
state.__constructedDuringGesture = state.__audioConstructed;
}
});
});
await expect(page.getByRole('button', { name: 'Start the drive' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Mute sound' })).toHaveCount(0);
await expect(page.getByRole('button', { name: 'Sound volume' })).toHaveCount(0);
await expect.poll(() => page.evaluate(() => (window as unknown as { __audioConstructed: number }).__audioConstructed)).toBe(0);
await expect(
page.getByRole("button", { name: "Start the drive" }),
).toBeVisible();
await expect(page.getByRole("button", { name: "Mute sound" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Sound volume" })).toHaveCount(
0,
);
await expect
.poll(() =>
page.evaluate(
() =>
(window as unknown as { __audioConstructed: number })
.__audioConstructed,
),
)
.toBe(0);
await page.getByRole('button', { name: 'Start the drive' }).click();
await page.getByRole("button", { name: "Start the drive" }).click();
await expect(page.getByRole('button', { name: 'Mute sound' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Sound volume' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Pause motion' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Drive settings' })).toBeVisible();
await expect.poll(() => page.evaluate(() => (window as unknown as { __constructedDuringGesture: number }).__constructedDuringGesture)).toBe(1);
await expect.poll(() => page.evaluate(() => (window as unknown as { __audioConstructed: number }).__audioConstructed)).toBe(1);
await expect(page.getByRole("button", { name: "Mute sound" })).toBeVisible();
await expect(
page.getByRole("button", { name: "Sound volume" }),
).toBeVisible();
await expect(
page.getByRole("button", { name: "Pause motion" }),
).toBeVisible();
await expect(
page.getByRole("button", { name: "Drive settings" }),
).toBeVisible();
await expect
.poll(() =>
page.evaluate(
() =>
(window as unknown as { __constructedDuringGesture: number })
.__constructedDuringGesture,
),
)
.toBe(1);
await expect
.poll(() =>
page.evaluate(
() =>
(window as unknown as { __audioConstructed: number })
.__audioConstructed,
),
)
.toBe(1);
await page.getByRole('button', { name: 'Mute sound' }).click();
await expect(page.getByRole('button', { name: 'Unmute sound' })).toBeVisible();
await page.getByRole("button", { name: "Mute sound" }).click();
await expect(
page.getByRole("button", { name: "Unmute sound" }),
).toBeVisible();
});
test('keeps the compact controls usable and dismisses the upward panels', async ({ page, distUrl }) => {
await page.goto(distUrl, { waitUntil: 'domcontentloaded' });
await page.getByRole('button', { name: 'Start the drive' }).click();
test("keeps the compact controls usable and dismisses the upward panels", async ({
page,
distUrl,
}) => {
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "Start the drive" }).click();
const controls = page.getByRole('group', { name: 'Drive controls' }).getByRole('button');
const targets = await controls.evaluateAll((buttons) => buttons.map((button) => {
const rect = button.getBoundingClientRect();
return { width: rect.width, height: rect.height };
}));
expect(targets.every((target) => target.width >= 44 && target.height >= 44)).toBe(true);
const controls = page
.getByRole("group", { name: "Drive controls" })
.getByRole("button");
const targets = await controls.evaluateAll((buttons) =>
buttons.map((button) => {
const rect = button.getBoundingClientRect();
return { width: rect.width, height: rect.height };
}),
);
expect(
targets.every((target) => target.width >= 44 && target.height >= 44),
).toBe(true);
const settings = page.getByRole('button', { name: 'Drive settings' });
const settings = page.getByRole("button", { name: "Drive settings" });
await settings.focus();
await expectInsetFocusIndicator(page, 'button[aria-label="Drive settings"]');
await settings.click();
await expect(page.getByRole('dialog', { name: 'Drive settings' })).toBeVisible();
const surfaces = await page.locator('.journey-hud, .drive-controls__dock, .drive-popover').evaluateAll((elements) =>
elements.map((element) => {
const style = getComputedStyle(element);
const alpha = Number.parseFloat(style.backgroundColor.match(/[\d.]+(?=\))/u)?.[0] ?? '1');
return { alpha, backdropFilter: style.backdropFilter };
}));
expect(surfaces.every((surface) => surface.alpha >= 0.95 && surface.backdropFilter === 'none')).toBe(true);
await page.keyboard.press('Escape');
await expect(page.getByRole('dialog', { name: 'Drive settings' })).toHaveCount(0);
await expect(
page.getByRole("dialog", { name: "Drive settings" }),
).toBeVisible();
const surfaces = await page
.locator(".journey-hud, .drive-controls__dock, .drive-popover")
.evaluateAll((elements) =>
elements.map((element) => {
const style = getComputedStyle(element);
const alpha = Number.parseFloat(
style.backgroundColor.match(/[\d.]+(?=\))/u)?.[0] ?? "1",
);
return { alpha, backdropFilter: style.backdropFilter };
}),
);
expect(
surfaces.every(
(surface) => surface.alpha >= 0.95 && surface.backdropFilter === "none",
),
).toBe(true);
await page.keyboard.press("Escape");
await expect(
page.getByRole("dialog", { name: "Drive settings" }),
).toHaveCount(0);
await expect(settings).toBeFocused();
await settings.click();
await page.locator('main#portfolio-content').click({ position: { x: 8, y: 8 } });
await expect(page.getByRole('dialog', { name: 'Drive settings' })).toHaveCount(0);
await page
.locator(".hero-journey__content")
.click({ position: { x: 8, y: 8 } });
await expect(
page.getByRole("dialog", { name: "Drive settings" }),
).toHaveCount(0);
});
test('persists native volume and keeps sound independent from Static motion', async ({ page, distUrl }) => {
await page.goto(distUrl, { waitUntil: 'domcontentloaded' });
await page.getByRole('button', { name: 'Start the drive' }).click();
test("persists native volume and keeps sound independent from Static motion", async ({
page,
distUrl,
}) => {
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "Start the drive" }).click();
await page.getByRole('button', { name: 'Sound volume' }).click();
const volume = page.getByLabel('Sound volume level');
await volume.fill('0.65');
await expect(volume).toHaveValue('0.65');
await expect.poll(() => page.evaluate(() => localStorage.getItem('portfolio.audio.volume'))).toBe('0.65');
await page.getByRole("button", { name: "Sound volume" }).click();
const volume = page.getByLabel("Sound volume level");
await volume.fill("0.65");
await expect(volume).toHaveValue("0.65");
await expect
.poll(() =>
page.evaluate(() => localStorage.getItem("portfolio.audio.volume")),
)
.toBe("0.65");
await page.getByRole('button', { name: 'Drive settings' }).click();
await page.getByLabel('Quality control').selectOption('static');
await expect(page.getByRole('button', { name: 'Unmute sound' })).toHaveCount(0);
await expect(page.getByRole('button', { name: 'Mute sound' })).toBeVisible();
await page.getByRole("button", { name: "Drive settings" }).click();
await page.getByLabel("Quality control").selectOption("static");
await expect(page.getByRole("button", { name: "Unmute sound" })).toHaveCount(
0,
);
await expect(page.getByRole("button", { name: "Mute sound" })).toBeVisible();
await expect(volume).toHaveCount(0);
await page.getByRole('button', { name: 'Sound volume' }).click();
await page.getByRole("button", { name: "Sound volume" }).click();
await expect(volume).toBeVisible();
});
test('requires a direct visitor action after browser interruption without creating another graph', async ({ page, distUrl }) => {
await page.goto(distUrl, { waitUntil: 'domcontentloaded' });
await page.getByRole('button', { name: 'Start the drive' }).click();
test("requires a direct visitor action after browser interruption without creating another graph", async ({
page,
distUrl,
}) => {
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "Start the drive" }).click();
await page.evaluate(() => {
const context = (window as unknown as { __audioContexts: AudioContext[] }).__audioContexts[0];
Object.defineProperty(context, 'state', { configurable: true, value: 'interrupted' });
context?.dispatchEvent(new Event('statechange'));
const context = (window as unknown as { __audioContexts: AudioContext[] })
.__audioContexts[0];
Object.defineProperty(context, "state", {
configurable: true,
value: "interrupted",
});
context?.dispatchEvent(new Event("statechange"));
});
await expect(page.getByRole('button', { name: 'Resume sound' })).toBeVisible();
await page.getByRole('button', { name: 'Resume sound' }).click();
await expect(page.getByRole('button', { name: 'Mute sound' })).toBeVisible();
await expect.poll(() => page.evaluate(() => (window as unknown as { __audioConstructed: number }).__audioConstructed)).toBe(1);
await expect(
page.getByRole("button", { name: "Resume sound" }),
).toBeVisible();
await page.getByRole("button", { name: "Resume sound" }).click();
await expect(page.getByRole("button", { name: "Mute sound" })).toBeVisible();
await expect
.poll(() =>
page.evaluate(
() =>
(window as unknown as { __audioConstructed: number })
.__audioConstructed,
),
)
.toBe(1);
});
test('shows a concise non-blocking message when initial audio start is rejected', async ({ page, distUrl }) => {
test("shows a concise non-blocking message when initial audio start is rejected", async ({
page,
distUrl,
}) => {
await page.addInitScript(() => {
const OriginalAudioContext = window.AudioContext;
if (!OriginalAudioContext) return;
class RejectingAudioContext extends OriginalAudioContext {
override resume(): Promise<void> { return Promise.reject(new DOMException('blocked', 'NotAllowedError')); }
override resume(): Promise<void> {
return Promise.reject(new DOMException("blocked", "NotAllowedError"));
}
}
Object.defineProperty(window, 'AudioContext', { configurable: true, value: RejectingAudioContext });
Object.defineProperty(window, "AudioContext", {
configurable: true,
value: RejectingAudioContext,
});
});
await page.goto(distUrl, { waitUntil: 'domcontentloaded' });
await page.goto(distUrl, { waitUntil: "domcontentloaded" });
await page.getByRole('button', { name: 'Start the drive' }).click();
await page.getByRole("button", { name: "Start the drive" }).click();
await expect(page.getByText('Audio unavailable. Continue without sound.')).toBeVisible();
await expect(page.locator('main#portfolio-content')).toBeVisible();
await expect(
page.getByText("Audio unavailable. Continue without sound."),
).toBeVisible();
await expect(page.locator("main#portfolio-content")).toBeVisible();
});