- 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
68 lines
2.9 KiB
TypeScript
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");
|
|
});
|
|
});
|