Add E2E test for transform status bar and update CSS for status bar items
This commit is contained in:
@@ -6484,10 +6484,10 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer className="status-bar">
|
<footer className="status-bar">
|
||||||
<div>
|
<div className="status-bar__item status-bar__item--message" title={statusMessage}>
|
||||||
<span className="status-bar__strong">Status:</span> {statusMessage}
|
<span className="status-bar__strong">Status:</span> {statusMessage}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="status-bar__item">
|
||||||
<span className="status-bar__strong">Spawn:</span>{" "}
|
<span className="status-bar__strong">Spawn:</span>{" "}
|
||||||
{runtimeScene.spawn.source === "playerStart"
|
{runtimeScene.spawn.source === "playerStart"
|
||||||
? "Authored Player Start"
|
? "Authored Player Start"
|
||||||
@@ -10783,7 +10783,11 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<footer className="status-bar">
|
<footer className="status-bar">
|
||||||
<div className="status-bar__item" data-testid="status-message">
|
<div
|
||||||
|
className="status-bar__item status-bar__item--message"
|
||||||
|
data-testid="status-message"
|
||||||
|
title={statusMessage}
|
||||||
|
>
|
||||||
<span className="status-bar__strong">Status:</span> {statusMessage}
|
<span className="status-bar__strong">Status:</span> {statusMessage}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -10808,12 +10812,17 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
|||||||
<div
|
<div
|
||||||
className="status-bar__item status-bar__item--asset"
|
className="status-bar__item status-bar__item--asset"
|
||||||
data-testid="status-asset-hover"
|
data-testid="status-asset-hover"
|
||||||
|
title={hoveredAssetStatusMessage}
|
||||||
>
|
>
|
||||||
<span className="status-bar__strong">Asset:</span>{" "}
|
<span className="status-bar__strong">Asset:</span>{" "}
|
||||||
{hoveredAssetStatusMessage}
|
{hoveredAssetStatusMessage}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="status-bar__item" data-testid="status-last-command">
|
<div
|
||||||
|
className="status-bar__item"
|
||||||
|
data-testid="status-last-command"
|
||||||
|
title={lastCommandLabel}
|
||||||
|
>
|
||||||
<span className="status-bar__strong">Last:</span> {lastCommandLabel}
|
<span className="status-bar__strong">Last:</span> {lastCommandLabel}
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1222,9 +1222,10 @@ button:disabled {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-wrap: wrap;
|
flex-wrap: nowrap;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
|
height: 36px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
background: rgba(18, 22, 28, 0.88);
|
background: rgba(18, 22, 28, 0.88);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
@@ -1232,13 +1233,24 @@ button:disabled {
|
|||||||
color: var(--color-muted);
|
color: var(--color-muted);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-bar__item {
|
.status-bar__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
flex: 0 0 auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar__item--message {
|
||||||
|
flex: 1 1 320px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-bar__item--asset {
|
.status-bar__item--asset {
|
||||||
@@ -1320,6 +1332,8 @@ button:disabled {
|
|||||||
.status-bar {
|
.status-bar {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
height: auto;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,6 +375,8 @@ Every slice should include:
|
|||||||
- Setup: open the editor with at least one whitebox box selected in the perspective viewport.
|
- Setup: open the editor with at least one whitebox box selected in the perspective viewport.
|
||||||
- Steps: orbit/pan the camera away from the origin, run `G`, `R`, and `S`, then commit with click or `Enter`, cancel with `Escape`, and delete the selected target.
|
- Steps: orbit/pan the camera away from the origin, run `G`, `R`, and `S`, then commit with click or `Enter`, cancel with `Escape`, and delete the selected target.
|
||||||
- Expected result: the active viewport camera keeps its exact framing and does not snap back to the world origin after commit, cancel, or delete.
|
- Expected result: the active viewport camera keeps its exact framing and does not snap back to the world origin after commit, cancel, or delete.
|
||||||
|
- Steps: with the editor footer visible, trigger `G`, `R`, and `S`, then press `X`, `Y`, or `Z` while watching the perspective viewport bounds.
|
||||||
|
- Expected result: long transform status messages stay on one footer row, the footer height does not grow, and the viewport does not flicker or resize as the status text changes.
|
||||||
- Steps: start a translate or rotate session on a rotated whitebox box or rotated model instance, press `X`, `Y`, or `Z`, then press the same axis again.
|
- Steps: start a translate or rotate session on a rotated whitebox box or rotated model instance, press `X`, `Y`, or `Z`, then press the same axis again.
|
||||||
- Expected result: the first press constrains to the world axis, the second press switches to the target's local axis, and unsupported local toggles surface a clear status message.
|
- Expected result: the first press constrains to the world axis, the second press switches to the target's local axis, and unsupported local toggles surface a clear status message.
|
||||||
- Steps: toggle the viewport grid off and on, then pan the perspective camera far from the origin.
|
- Steps: toggle the viewport grid off and on, then pan the perspective camera far from the origin.
|
||||||
|
|||||||
44
tests/e2e/transform-status-bar.e2e.ts
Normal file
44
tests/e2e/transform-status-bar.e2e.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
|
||||||
|
import { beginBoxCreation, clickViewport, getViewportPanel } from "./viewport-test-helpers";
|
||||||
|
|
||||||
|
test("transform status updates keep the footer and viewport heights stable", async ({ page }) => {
|
||||||
|
await page.setViewportSize({ width: 1024, height: 768 });
|
||||||
|
await page.goto("/");
|
||||||
|
await page.evaluate((storageKey) => {
|
||||||
|
window.localStorage.removeItem(storageKey);
|
||||||
|
}, "webeditor3d.scene-document-draft");
|
||||||
|
await page.reload();
|
||||||
|
|
||||||
|
await beginBoxCreation(page);
|
||||||
|
await clickViewport(page);
|
||||||
|
|
||||||
|
const viewportPanel = getViewportPanel(page);
|
||||||
|
const statusBar = page.locator("footer.status-bar").first();
|
||||||
|
|
||||||
|
await viewportPanel.click({ position: { x: 24, y: 24 }, force: true });
|
||||||
|
|
||||||
|
const initialViewportHeight = await viewportPanel.evaluate(
|
||||||
|
(element) => Math.round(element.getBoundingClientRect().height)
|
||||||
|
);
|
||||||
|
const initialStatusBarHeight = await statusBar.evaluate(
|
||||||
|
(element) => Math.round(element.getBoundingClientRect().height)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const key of ["G", "R", "S"]) {
|
||||||
|
await page.keyboard.press(key);
|
||||||
|
await page.keyboard.press("Z");
|
||||||
|
|
||||||
|
const nextViewportHeight = await viewportPanel.evaluate(
|
||||||
|
(element) => Math.round(element.getBoundingClientRect().height)
|
||||||
|
);
|
||||||
|
const nextStatusBarHeight = await statusBar.evaluate(
|
||||||
|
(element) => Math.round(element.getBoundingClientRect().height)
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nextViewportHeight).toBe(initialViewportHeight);
|
||||||
|
expect(nextStatusBarHeight).toBe(initialStatusBarHeight);
|
||||||
|
|
||||||
|
await page.keyboard.press("Escape");
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user