feat: introduce the compact vehicle HUD

This commit is contained in:
2026-09-02 15:44:50 +03:00
parent 8deb56ed0c
commit c4f1a38a78
12 changed files with 668 additions and 192 deletions

View File

@@ -1,4 +1,4 @@
import { expect, test } from '../helpers/serve-dist';
import { expect, expectInsetFocusIndicator, test } from '../helpers/serve-dist';
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
@@ -30,15 +30,17 @@ test('starts Web Audio synchronously from the visitor gesture and exposes access
});
});
await expect(page.getByRole('button', { name: 'START THE DRIVE' })).toBeVisible();
await expect(page.getByText('Enables the interactive soundtrack.')).toBeVisible();
await expect(page.getByLabel('Sound volume')).toHaveCount(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.getByLabel('Sound volume')).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);
@@ -46,24 +48,60 @@ test('starts Web Audio synchronously from the visitor gesture and exposes access
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();
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' });
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(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);
});
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: 'Start the drive' }).click();
const volume = page.getByLabel('Sound volume');
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 expect(volume).toHaveCount(0);
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();
await page.getByRole('button', { name: 'Start the drive' }).click();
await page.evaluate(() => {
const context = (window as unknown as { __audioContexts: AudioContext[] }).__audioContexts[0];
@@ -88,7 +126,7 @@ test('shows a concise non-blocking message when initial audio start is rejected'
});
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();