Spaces:
Runtime error
Runtime error
| // @vitest-environment jsdom | |
| import React, { act } from "react"; | |
| import { createRoot } from "react-dom/client"; | |
| import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from "vitest"; | |
| import type { CompressionRunModel } from "@/app/(dashboard)/dashboard/compression/studio/compressionFlowModel"; | |
| // ββ Polyfill ResizeObserver (required by ReactFlow) βββββββββββββββββββββββ | |
| beforeAll(() => { | |
| globalThis.ResizeObserver = class { | |
| observe() {} | |
| unobserve() {} | |
| disconnect() {} | |
| } as unknown as typeof ResizeObserver; | |
| }); | |
| // ββ Mocks βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Stub @xyflow/react so ReactFlow renders without canvas/DOM measurement APIs | |
| vi.mock("@xyflow/react", async () => { | |
| const actual = (await vi.importActual("@xyflow/react")) as Record<string, unknown>; | |
| return { | |
| ...actual, | |
| Handle: (_props: Record<string, unknown>) => null, | |
| Position: { Left: "left", Right: "right", Top: "top", Bottom: "bottom" }, | |
| }; | |
| }); | |
| // ββ Import after mocks βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const { CompressionCockpit } = | |
| await import("@/app/(dashboard)/dashboard/compression/studio/CompressionCockpit"); | |
| // ββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const containers: HTMLElement[] = []; | |
| function mount(ui: React.ReactElement): HTMLElement { | |
| const container = document.createElement("div"); | |
| document.body.appendChild(container); | |
| containers.push(container); | |
| const root = createRoot(container); | |
| act(() => { | |
| root.render(ui); | |
| }); | |
| return container; | |
| } | |
| function click(el: Element | null): void { | |
| act(() => { | |
| el?.dispatchEvent(new MouseEvent("click", { bubbles: true })); | |
| }); | |
| } | |
| beforeEach(() => { | |
| ( | |
| globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean } | |
| ).IS_REACT_ACT_ENVIRONMENT = true; | |
| }); | |
| afterEach(() => { | |
| while (containers.length > 0) { | |
| containers.pop()?.remove(); | |
| } | |
| document.body.innerHTML = ""; | |
| }); | |
| // ββ Sample run ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const SAMPLE_RUN: CompressionRunModel = { | |
| requestId: "test-req-001", | |
| comboId: "daily-cascade", | |
| mode: "stacked", | |
| originalTokens: 12480, | |
| compressedTokens: 6090, | |
| savingsPercent: 51.2, | |
| timestamp: 1718000000000, | |
| steps: [ | |
| { | |
| engine: "rtk", | |
| originalTokens: 12480, | |
| compressedTokens: 9734, | |
| savingsPercent: 22.0, | |
| techniquesUsed: ["strip-comments", "shell-filter"], | |
| durationMs: 1.8, | |
| }, | |
| { | |
| engine: "headroom", | |
| originalTokens: 9734, | |
| compressedTokens: 8524, | |
| savingsPercent: 12.4, | |
| techniquesUsed: ["smartcrusher"], | |
| durationMs: 0.9, | |
| }, | |
| { | |
| engine: "caveman", | |
| originalTokens: 8524, | |
| compressedTokens: 6896, | |
| savingsPercent: 19.1, | |
| techniquesUsed: ["pt-BR", "filler-drop"], | |
| durationMs: 0.6, | |
| }, | |
| ], | |
| }; | |
| // ββ Tests βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| describe("CompressionCockpit", () => { | |
| it("renders the cockpit wrapper when a run is provided", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.querySelector("[data-testid='compression-cockpit']")).toBeTruthy(); | |
| }); | |
| it("renders the ReactFlow canvas", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.querySelector(".react-flow")).toBeTruthy(); | |
| }); | |
| it("shows the mode in the header", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.textContent).toContain("stacked"); | |
| }); | |
| it("shows the comboId in the header", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.textContent).toContain("daily-cascade"); | |
| }); | |
| it("shows the total savings percentage in the header", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.textContent).toContain("51.2"); | |
| }); | |
| it("shows engine names (from node labels via ReactFlow)", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| // The engine names appear in the header text even if ReactFlow node internals | |
| // don't render in jsdom β we also check the header region. | |
| const text = container.textContent ?? ""; | |
| // At minimum the run metadata renders correctly | |
| expect(text).toContain("test-req-001"); | |
| }); | |
| it("renders the empty state when no run is given", () => { | |
| const container = mount(<CompressionCockpit />); | |
| expect(container.querySelector("[data-testid='compression-cockpit-empty']")).toBeTruthy(); | |
| expect(container.textContent).toContain("No compression run available"); | |
| }); | |
| it("renders replay controls when a run is provided", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| // Replay button present | |
| const text = container.textContent ?? ""; | |
| expect(text).toContain("Replay"); | |
| }); | |
| it("offers a Canvas/Waterfall view toggle", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| expect(container.querySelector("[data-testid='cockpit-view-canvas']")).toBeTruthy(); | |
| expect(container.querySelector("[data-testid='cockpit-view-waterfall']")).toBeTruthy(); | |
| }); | |
| it("switches to the waterfall inspector and back to the canvas", () => { | |
| const container = mount(<CompressionCockpit run={SAMPLE_RUN} />); | |
| // Default view is the ReactFlow canvas, waterfall hidden. | |
| expect(container.querySelector(".react-flow")).toBeTruthy(); | |
| expect(container.querySelector("[data-testid='waterfall-inspector']")).toBeFalsy(); | |
| // Switch to the waterfall (A1) view β the previously-orphan component is now reachable. | |
| click(container.querySelector("[data-testid='cockpit-view-waterfall']")); | |
| expect(container.querySelector("[data-testid='waterfall-inspector']")).toBeTruthy(); | |
| expect(container.querySelector(".react-flow")).toBeFalsy(); | |
| expect( | |
| container.querySelector("[data-testid='waterfall-total-savings']")?.textContent | |
| ).toContain("51.2"); | |
| // Switch back to the canvas. | |
| click(container.querySelector("[data-testid='cockpit-view-canvas']")); | |
| expect(container.querySelector(".react-flow")).toBeTruthy(); | |
| expect(container.querySelector("[data-testid='waterfall-inspector']")).toBeFalsy(); | |
| }); | |
| }); | |