FN-6110: fix Reliability view flex sizing on mobile

Keep the Reliability view filling its flex parent across mobile and desktop states.

- add flex growth and min-width safeguards to the Reliability view, loading, and error containers
- add desktop and mobile regression coverage for loading, populated, and error rendering states

Files changed:
 packages/dashboard/app/components/ReliabilityView.css  |  6 +++
 packages/dashboard/app/components/__tests__/ReliabilityView.test.tsx | 59 ++++++++++++++++++++++
 2 files changed, 65 insertions(+)

Fusion-Task-Id: FN-6110

Fusion-Task-Lineage: 5fe1e5a7-f13a-4316-8c4e-b5c85a51ce86
This commit is contained in:
gsxdsm
2026-06-09 11:44:43 -07:00
parent 934071cc3c
commit d1996a9899
2 changed files with 65 additions and 0 deletions

View File

@@ -1,9 +1,11 @@
.reliability-view {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: var(--space-lg);
height: 100%;
min-height: 0;
min-width: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
@@ -17,20 +19,24 @@
.reliability-loading {
display: flex;
flex: 1 1 auto;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--space-md);
min-width: 0;
padding: var(--space-2xl);
color: var(--text-muted);
}
.reliability-error {
display: flex;
flex: 1 1 auto;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--space-md);
min-width: 0;
padding: var(--space-2xl);
text-align: center;
}

View File

@@ -32,6 +32,27 @@ const baseResponse = {
mergeAttempts: { mean: 1.2, max: 2, histogram: { "1": 1 } },
};
function renderInProjectContent() {
return render(
<div data-testid="project-content" style={{ display: "flex", width: "100%" }}>
<ReliabilityView />
</div>,
);
}
function setViewportWidth(width: number) {
Object.defineProperty(window, "innerWidth", { configurable: true, value: width });
window.dispatchEvent(new Event("resize"));
}
function expectFlexFill(element: HTMLElement) {
const computed = getComputedStyle(element);
expect(computed.flexGrow).toBe("1");
expect(computed.flexShrink).toBe("1");
expect(computed.flexBasis).toBe("auto");
expect(computed.minWidth).toBe("0px");
}
describe("ReliabilityView", () => {
afterEach(() => {
vi.useRealTimers();
@@ -58,6 +79,44 @@ describe("ReliabilityView", () => {
expect(screen.queryByRole("heading", { name: "Reliability" })).not.toBeInTheDocument();
});
it.each([
["desktop", 1024],
["mobile", 375],
])("fills flex parent width in %s loading state", (_label, width) => {
setViewportWidth(width);
vi.spyOn(globalThis, "fetch").mockReturnValue(new Promise<Response>(() => {}));
renderInProjectContent();
expectFlexFill(screen.getByTestId("reliability-loading"));
});
it.each([
["desktop", 1024],
["mobile", 375],
])("fills flex parent width in %s populated state", async (_label, width) => {
setViewportWidth(width);
vi.spyOn(globalThis, "fetch").mockResolvedValue({ ok: true, json: async () => baseResponse } as Response);
const { container } = renderInProjectContent();
await waitFor(() => expect(container.querySelector(".reliability-view")).not.toBeNull());
expectFlexFill(container.querySelector(".reliability-view") as HTMLElement);
});
it.each([
["desktop", 1024],
["mobile", 375],
])("fills flex parent width in %s error state", async (_label, width) => {
setViewportWidth(width);
vi.spyOn(globalThis, "fetch").mockRejectedValue(new Error("Network unavailable"));
renderInProjectContent();
await waitFor(() => expect(screen.getByTestId("reliability-error")).toBeInTheDocument());
expectFlexFill(screen.getByTestId("reliability-error"));
});
it("shows data after successful load even if loading refresh is pending", async () => {
vi.useFakeTimers();
const fetchSpy = vi.spyOn(globalThis, "fetch")