fix: align the static fallback with the nightdrive scene

This commit is contained in:
2026-09-02 17:01:40 +03:00
parent 5fee894490
commit 0899b6b00f
4 changed files with 153 additions and 89 deletions

View File

@@ -111,10 +111,12 @@ const captureWorldSequence = async (
intervalMs: number,
): Promise<SampledFrame[]> => {
const frames: SampledFrame[] = [];
const clip = await world.boundingBox();
if (clip === null) throw new Error("Journey world is not visible.");
for (let index = 0; index < frameCount; index += 1) {
frames.push(
await sampleFrame(
await world.screenshot({ animations: "allow", scale: "css" }),
await world.page().screenshot({ animations: "allow", clip, scale: "css" }),
),
);
if (index + 1 < frameCount) await world.page().waitForTimeout(intervalMs);
@@ -264,9 +266,11 @@ test.describe("production visual composition", () => {
boxesFitHorizontally: boxes.every(
(rect) => rect.left >= -1 && rect.right <= root.clientWidth + 1,
),
panelWidthRatios: panels.map(
(panel) => panel.getBoundingClientRect().width / root.clientWidth,
),
panelGeometry: panels.map((panel) => ({
layout: panel.dataset.layout ?? "",
width: panel.getBoundingClientRect().width,
widthRatio: panel.getBoundingClientRect().width / root.clientWidth,
})),
panelBackgroundImage: firstPanelStyle.backgroundImage,
panelFilter: firstPanelStyle.filter,
textShadows: textStyles.map((style) => style.textShadow),
@@ -302,15 +306,28 @@ test.describe("production visual composition", () => {
expect(palette.restrainedAccent).toBeLessThan(0.28);
if (viewport.width >= 1280) {
expect(
composition.panelWidthRatios.every(
(ratio) => ratio >= 0.4 && ratio <= 0.45,
),
).toBe(true);
for (const panel of composition.panelGeometry) {
if (["right-rail", "compact-rail"].includes(panel.layout)) {
expect(panel.widthRatio).toBeGreaterThanOrEqual(0.4);
expect(panel.widthRatio).toBeLessThanOrEqual(0.45);
} else if (panel.layout === "left-timeline") {
expect(panel.widthRatio).toBeGreaterThanOrEqual(0.44);
expect(panel.widthRatio).toBeLessThanOrEqual(0.48);
} else if (["full-diagram", "toolkit-field"].includes(panel.layout)) {
expect(panel.widthRatio).toBeGreaterThanOrEqual(0.75);
expect(panel.widthRatio).toBeLessThanOrEqual(0.8);
} else if (panel.layout === "project-stage") {
expect(panel.widthRatio).toBeGreaterThanOrEqual(0.9);
expect(panel.widthRatio).toBeLessThanOrEqual(0.94);
} else if (panel.layout === "destination") {
expect(panel.width).toBeGreaterThanOrEqual(760);
expect(panel.width).toBeLessThanOrEqual(866);
}
}
} else if (viewport.width < 768) {
expect(
composition.panelWidthRatios.every(
(ratio) => ratio >= 0.85 && ratio <= 1,
composition.panelGeometry.every(
(panel) => panel.widthRatio >= 0.85 && panel.widthRatio <= 1,
),
).toBe(true);
}
@@ -326,6 +343,7 @@ test.describe("production visual composition", () => {
}, testInfo) => {
await page.setViewportSize({ width: 1440, height: 900 });
await waitForRenderedPortfolio(page, distUrl);
await page.getByRole("button", { name: "Drive settings" }).click();
await page.getByLabel("Quality control").selectOption("static");
await expect(page.locator(".journey-world")).toHaveAttribute(
"data-scene-state",
@@ -333,6 +351,9 @@ test.describe("production visual composition", () => {
);
await expect(page.locator(".journey-canvas")).toHaveCount(0);
await expect(page.locator(".journey-poster")).toHaveCount(1);
await page.keyboard.press("Escape");
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur());
await page.mouse.move(1, 1);
const first = await captureViewport(page, testInfo, "visual-static-a");
await page.waitForTimeout(200);
@@ -352,9 +373,13 @@ test.describe("production visual composition", () => {
await page.evaluate(() => document.fonts.ready);
await expect(page.locator(".journey-canvas")).toHaveCount(0);
await expect(page.locator(".journey-poster")).toHaveCount(1);
await page.getByRole("button", { name: "Drive settings" }).click();
await expect(page.getByRole("status")).toContainText(
"reduced motion requested",
);
await page.keyboard.press("Escape");
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur());
await page.mouse.move(1, 1);
await captureViewport(page, testInfo, "visual-reduced-motion");
});
@@ -368,7 +393,8 @@ test.describe("production visual composition", () => {
await expect(
page.getByRole("button", { name: "Mute sound" }),
).toBeVisible();
await expect(page.getByLabel("Sound volume")).toHaveValue("0.4");
await page.getByRole("button", { name: "Sound volume" }).click();
await expect(page.getByLabel("Sound volume level")).toHaveValue("0.4");
await captureViewport(page, testInfo, "visual-audio-running");
});
@@ -480,11 +506,15 @@ test.describe("three-flash safety", () => {
}, testInfo) => {
await page.setViewportSize({ width: 1440, height: 900 });
await waitForRenderedPortfolio(page, distUrl);
await page.getByRole("button", { name: "Drive settings" }).click();
await page.getByLabel("Quality control").selectOption("static");
await expect(page.locator(".journey-world")).toHaveAttribute(
"data-scene-state",
"static",
);
await page.keyboard.press("Escape");
await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur());
await page.mouse.move(1, 1);
const staticResult = analyzeFlashSequence(
await captureWorldSequence(page.locator(".journey-world"), 8, 100),
10,

View File

@@ -62,6 +62,10 @@ describe('SceneCanvas', () => {
expect(sceneMocks.build).not.toHaveBeenCalled();
expect(wrapper.findAll('canvas')).toHaveLength(0);
expect(wrapper.get('img').attributes()).toMatchObject({ alt: '', width: '1600', height: '900' });
expect(wrapper.findAll('.journey-poster-composition > span')).toHaveLength(7);
expect(wrapper.find('.journey-poster__sun').exists()).toBe(true);
expect(wrapper.find('.journey-poster__road').exists()).toBe(true);
expect(wrapper.find('.journey-poster__car').exists()).toBe(true);
expect(wrapper.text()).toContain('A decorative night road behind the portfolio content.');
wrapper.unmount();
});