Files
ozone-tech_owl_prime/e2e/visual.spec.ts
Даня Архипов 4413f01ce4 chore: preserve pre-cleanup product baseline
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 17:48:00 +00:00

178 lines
6.3 KiB
TypeScript

import { test, expect, type Page } from '@playwright/test';
test.setTimeout(90_000);
async function waitScene(page: Page) {
await page.goto('/?debug=1&playback=paused');
await expect(page.locator('canvas')).toBeVisible({ timeout: 60_000 });
await page.evaluate(() => document.fonts.ready);
await expect(page.getByTestId('demo-hud')).toBeVisible();
// seek pins case 0 and starts running — pause again for deterministic HUD snaps
await page.getByTestId('demo-case-0').click();
const pause = page.getByTestId('demo-pause');
if (await pause.isVisible().catch(() => false)) await pause.click();
await page.getByTestId('demo-speed-2').click();
}
async function dismissFinishedIfNeeded(page: Page) {
const finished = page.getByTestId('demo-finished');
if (await finished.isVisible().catch(() => false)) {
await finished.getByRole('button', { name: /Replay/i }).click();
await expect(finished).toHaveCount(0);
}
}
async function jumpCase(page: Page, index: number) {
await dismissFinishedIfNeeded(page);
await page.getByTestId(`demo-case-${index}`).click();
await expect(page.getByTestId('demo-case-label')).toHaveText(`${index + 1}/12`, {
timeout: 10_000,
});
}
async function ensureRunning(page: Page) {
await dismissFinishedIfNeeded(page);
const pause = page.getByTestId('demo-pause');
if (await pause.isVisible().catch(() => false)) return;
await page.getByTestId('demo-play').click();
}
async function snapHud(page: Page, name: string) {
await dismissFinishedIfNeeded(page);
const hud = page.getByTestId('demo-hud');
await expect(hud).toBeVisible();
await expect(hud).toHaveScreenshot(name, {
threshold: 0.35,
maxDiffPixelRatio: 0.08,
});
}
test.describe('visual regression', () => {
test('01 home idle HUD', async ({ page }) => {
await waitScene(page);
// Pause for a stable idle-ish HUD
const pause = page.getByTestId('demo-pause');
if (await pause.isVisible().catch(() => false)) {
await pause.click();
}
await expect(page.getByTestId('demo-case-label')).toHaveText('1/12');
await snapHud(page, '01-home-idle-hud.png');
});
test('02 class B after seek case 0', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 0);
await ensureRunning(page);
await expect(page.getByTestId('demo-category')).toHaveText('B', { timeout: 25_000 });
await page.getByTestId('demo-pause').click().catch(() => undefined);
await snapHud(page, '02-class-b-hud.png');
});
test('03 class C oversized case 2', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 2);
await ensureRunning(page);
await expect(page.getByTestId('demo-category')).toHaveText('C', { timeout: 25_000 });
await page.getByTestId('demo-pause').click().catch(() => undefined);
await snapHud(page, '03-class-c-hud.png');
});
test('04 class D plate case 4', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 4);
await ensureRunning(page);
await expect(page.getByTestId('demo-category')).toHaveText('D', { timeout: 25_000 });
await page.getByTestId('demo-pause').click().catch(() => undefined);
await snapHud(page, '04-class-d-hud.png');
});
test('05 jam fault HUD', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 9);
await ensureRunning(page);
await expect
.poll(async () => {
const status = await page.getByTestId('demo-status').innerText();
const cmd = await page.getByTestId('demo-command').innerText();
return `${status} ${cmd}`;
}, { timeout: 30_000 })
.toMatch(/FAULT|JAM/i);
await page.getByTestId('demo-pause').click().catch(() => undefined);
await snapHud(page, '05-jam-fault-hud.png');
});
test('06 emergency stop HUD', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 10);
await ensureRunning(page);
await expect
.poll(async () => {
const status = await page.getByTestId('demo-status').innerText();
const cmd = await page.getByTestId('demo-command').innerText();
return `${status} ${cmd}`;
}, { timeout: 30_000 })
.toMatch(/EMERGENCY/i);
await page.getByTestId('demo-pause').click().catch(() => undefined);
await snapHud(page, '06-emergency-hud.png');
});
test('07 presentation mode hides HUD', async ({ page }) => {
await waitScene(page);
await dismissFinishedIfNeeded(page);
await page.getByTestId('demo-presentation').click();
await expect(page.getByTestId('demo-hud')).toHaveCount(0);
await expect(page.locator('.main-page')).toHaveScreenshot('07-presentation-mode.png', {
threshold: 0.4,
maxDiffPixelRatio: 0.12,
animations: 'disabled',
});
});
test('08 documentation page', async ({ page }) => {
await page.goto('/documentation');
await expect(page.getByTestId('documentation-page')).toBeVisible();
await page.waitForTimeout(800);
await expect(page).toHaveScreenshot('08-documentation-page.png', {
threshold: 0.4,
maxDiffPixelRatio: 0.12,
fullPage: true,
animations: 'disabled',
});
});
test('09 recovery after jam stop', async ({ page }) => {
await waitScene(page);
await jumpCase(page, 9);
await ensureRunning(page);
await expect
.poll(async () => {
const status = await page.getByTestId('demo-status').innerText();
const cmd = await page.getByTestId('demo-command').innerText();
return `${status} ${cmd}`;
}, { timeout: 30_000 })
.toMatch(/FAULT|JAM/i);
// Stop resets toward recovery
const stop = page.getByTestId('demo-stop');
if (await stop.isVisible().catch(() => false)) {
await stop.click({ force: true });
} else {
await dismissFinishedIfNeeded(page);
await page.getByTestId('demo-case-0').click();
}
await expect(page.getByTestId('demo-case-label')).toBeVisible();
await snapHud(page, '09-recovery-hud.png');
});
test('10 perf overlay engineering snapshot', async ({ page }) => {
await page.goto('/?perf=1&quality=demo');
await expect(page.locator('canvas')).toBeVisible({ timeout: 60_000 });
await page.waitForTimeout(2000);
const overlay = page.locator('.perf-overlay');
await expect(overlay).toBeVisible({ timeout: 15_000 });
await expect(overlay).toHaveScreenshot('10-perf-overlay.png', {
threshold: 0.4,
maxDiffPixelRatio: 0.15,
});
});
});