Files
fusion/packages/dashboard/app/__tests__/dev-server-layout-css.test.ts
Fusion 315892a286 feat(FN-2173): add auto-fallback flow for dev server preview
- Add preview embed diagnostics with richer error classification and fallback state handling
- Improve PreviewIframe and DevServerView retry UX for timeout and iframe failure states
- Adjust preview layout/styles to prevent clipping and header overflow while keeping fallback panels centered
- Expand dashboard tests to cover fallback transitions, retry flows, and responsive CSS behavior
2026-04-20 22:10:07 -07:00

68 lines
2.9 KiB
TypeScript

import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
const css = readFileSync(resolve(__dirname, "../styles.css"), "utf-8");
function getRule(selector: string, options: { last?: boolean } = {}): string {
const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const matches = [...css.matchAll(new RegExp(`${escapedSelector}\\s*\\{[^}]*\\}`, "g"))];
expect(matches.length, `Expected CSS rule for ${selector}`).toBeGreaterThan(0);
if (options.last) {
return matches[matches.length - 1]?.[0] ?? "";
}
return matches[0]?.[0] ?? "";
}
describe("Dev server view CSS layout regressions", () => {
it("allows vertical page scrolling to keep all controls reachable on short viewports", () => {
const rootRule = getRule(".dev-server-view");
expect(rootRule).toContain("overflow-y: auto");
expect(rootRule).toContain("overflow-x: hidden");
});
it("keeps config and candidate lists scrollable with bounded height", () => {
const configRule = getRule(".dev-server-config");
expect(configRule).toContain("max-height: min(52vh, calc(var(--space-2xl) * 16))");
expect(configRule).toContain("overflow-y: auto");
const candidatesRule = getRule(".dev-server-candidates");
expect(candidatesRule).toContain("max-height: min(36vh, calc(var(--space-2xl) * 9))");
expect(candidatesRule).toContain("overflow-y: auto");
});
it("renders fullscreen log viewer above fixed chrome layers", () => {
const fullscreenRule = getRule(".devserver-log-viewer--fullscreen");
const zIndexMatch = fullscreenRule.match(/z-index:\s*(\d+)/);
expect(zIndexMatch).toBeTruthy();
const zIndex = Number.parseInt(zIndexMatch?.[1] ?? "0", 10);
expect(zIndex).toBeGreaterThan(50);
});
it("separates warning fallback styling from external-only mode", () => {
const fallbackRule = getRule(".dev-server-preview-fallback", { last: true });
const externalOnlyRule = getRule(".dev-server-preview-external-only", { last: true });
expect(fallbackRule).toContain("var(--color-warning)");
expect(externalOnlyRule).toContain("border: 1px solid var(--border)");
expect(externalOnlyRule).toContain("background: var(--surface)");
expect(externalOnlyRule).not.toContain("--color-warning");
});
it("keeps the preview header responsive on narrow screens", () => {
const badgeRule = getRule(".devserver-preview-url-badge");
expect(badgeRule).toContain("flex: 1 1 auto");
expect(badgeRule).toContain("min-width: 0");
const mobileHeaderRule = getRule(".devserver-preview-header", { last: true });
expect(mobileHeaderRule).toContain("flex-wrap: wrap");
const mobileActionsRule = getRule(".devserver-preview-actions", { last: true });
expect(mobileActionsRule).toContain("width: 100%");
expect(mobileActionsRule).toContain("justify-content: flex-end");
});
});