diff --git a/src/grid/CallLayout.test.tsx b/src/grid/CallLayout.test.tsx index 3338b5802..4c0a9c1e2 100644 --- a/src/grid/CallLayout.test.tsx +++ b/src/grid/CallLayout.test.tsx @@ -5,28 +5,25 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { act, render, screen } from "@testing-library/react"; -import { BehaviorSubject } from "rxjs"; -import { describe, expect, it, vi } from "vitest"; +import { render } from "@testing-library/react"; +import { expect, test, vi } from "vitest"; -import { arrangeTiles, type Bounds } from "./CallLayout"; +import { type CallLayout } from "./CallLayout"; import { makeGridLayout } from "./GridLayout"; import { makeSpotlightLandscapeLayout } from "./SpotlightLandscapeLayout"; import { makeSpotlightPortraitLayout } from "./SpotlightPortraitLayout"; import { type LayoutProps } from "./Grid"; import { constant } from "../state/Behavior"; -import { - type Alignment, - type GridLayout, - type SpotlightLandscapeLayout, - type SpotlightPortraitLayout, -} from "../state/layout-types"; +import { type Alignment } from "../state/layout-types"; import { type UserMediaViewModel } from "../state/media/UserMediaViewModel"; import { GridTileViewModel, SpotlightTileViewModel, type TileViewModel, } from "../state/TileViewModel"; +import { makeOneOnOneMobileLayout } from "./OneOnOneMobileLayout"; +import { makeSpotlightExpandedLayout } from "./SpotlightExpandedLayout"; +import { makeOneOnOneDesktopLayout } from "./OneOnOneDesktopLayout"; // Grid supplies these hooks to the layouts it renders; on their own the // layouts have no grid to report to @@ -36,66 +33,8 @@ vi.mock("./Grid", async (importOriginal) => ({ useVisibleTiles: (): void => {}, })); -describe("grid layout", () => { - it("sizes the tiles from the minimum bounds", () => { - const minBounds$ = new BehaviorSubject({ width: 800, height: 600 }); - const { scrolling: Scrolling } = makeGridLayout({ minBounds$ }); - render(); - const layer = screen.getByTestId("slot-0").parentElement!; - expect(layer.style.width).toBe("800px"); - expect(layer.style.getPropertyValue("--width")).toBe( - `${Math.floor(arrangeTiles(800, 600, 3).tileWidth)}px`, - ); +const minBounds$ = constant({ width: 800, height: 800 }); - act(() => minBounds$.next({ width: 400, height: 300 })); - expect(layer.style.width).toBe("400px"); - expect(layer.style.getPropertyValue("--width")).toBe( - `${Math.floor(arrangeTiles(400, 300, 3).tileWidth)}px`, - ); - }); -}); - -describe("spotlight landscape layout", () => { - it("puts the spotlight in the fixed layer and the grid in the scrolling one", () => { - const { fixed: Fixed, scrolling: Scrolling } = makeSpotlightLandscapeLayout( - { minBounds$: bounds }, - ); - const model = landscapeModel(); - const { unmount } = render(); - expect(screen.getByTestId("slot-spotlight")).toBeInTheDocument(); - unmount(); - - render(); - expect(slotIds()).toEqual(model.grid.map((tile) => tile.id)); - }); -}); - -describe("spotlight portrait layout", () => { - it("sizes the grid tiles from the minimum width", () => { - const minBounds$ = new BehaviorSubject({ width: 300, height: 700 }); - const { scrolling: Scrolling } = makeSpotlightPortraitLayout({ - minBounds$, - }); - const model = portraitModel(); - render(); - expect(slotIds()).toEqual(model.grid.map((tile) => tile.id)); - const layer = screen.getByTestId(`slot-${model.grid[0].id}`).parentElement! - .parentElement!; - expect(layer.style.getPropertyValue("--grid-tile-width")).toBe( - `${Math.floor(arrangeTiles(300, 300, 3).tileWidth)}px`, - ); - - act(() => minBounds$.next({ width: 500, height: 700 })); - expect(layer.style.getPropertyValue("--grid-tile-width")).toBe( - `${Math.floor(arrangeTiles(500, 500, 3).tileWidth)}px`, - ); - }); -}); - -const bounds = constant({ width: 800, height: 600 }); - -// The layouts only pass tile view models through to their slots -const media = {} as UserMediaViewModel; const spotlight = { vm: new SpotlightTileViewModel( constant([]), @@ -105,51 +44,94 @@ const spotlight = { alignment$: constant({ inline: "end", block: "end" }), onDrag: () => {}, }; -const tiles = (): GridTileViewModel[] => - Array.from({ length: 3 }, () => new GridTileViewModel(constant(media))); +const grid = Array.from( + { length: 3 }, + () => new GridTileViewModel(constant({} as UserMediaViewModel)), +); +const pip = { + alignment$: constant({ inline: "end", block: "end" }), + onDrag: () => {}, + vm: { id: "pip" } as GridTileViewModel, + size$: constant("sm" as const), +}; -function gridModel(): GridLayout { - return { - type: "grid", - spotlight, - grid: tiles(), - setVisibleTiles: () => {}, - }; -} - -function landscapeModel(): SpotlightLandscapeLayout { - return { - type: "spotlight-landscape", - spotlight, - grid: tiles(), - setVisibleTiles: () => {}, - }; -} - -function portraitModel(): SpotlightPortraitLayout { - return { - type: "spotlight-portrait", - spotlight, - grid: tiles(), - setVisibleTiles: () => {}, - }; -} - -// Slots show the id of the tile they hold const Slot: LayoutProps["Slot"] = ({ id, model, onDrag, + children, ...props }) => (
- {model instanceof GridTileViewModel ? model.id : "spotlight"} + {children}
); -function slotIds(): string[] { - return screen - .getAllByTestId(/^slot-/) - .map((slot) => slot.textContent ?? "") - .filter((id) => id !== "spotlight"); +function snapshotLayout(layout: CallLayout, model: Model): void { + const { + foreground, + scrolling: Scrolling, + fixed: Fixed, + } = layout({ minBounds$ }); + const scrollingLayer = ; + const fixedLayer = ; + const { container } = render( + foreground === "fixed" ? ( + <> + {scrollingLayer} + {fixedLayer} + + ) : ( + <> + {fixedLayer} + {scrollingLayer} + + ), + ); + expect(container).toMatchSnapshot(); } + +test("grid layout", () => + snapshotLayout(makeGridLayout, { + type: "grid", + spotlight, + grid, + setVisibleTiles: () => {}, + })); + +test("spotlight landscape layout", () => + snapshotLayout(makeSpotlightLandscapeLayout, { + type: "spotlight-landscape", + spotlight, + grid, + setVisibleTiles: () => {}, + })); + +test("spotlight portrait layout", () => + snapshotLayout(makeSpotlightPortraitLayout, { + type: "spotlight-portrait", + spotlight, + grid, + setVisibleTiles: () => {}, + })); + +test("spotlight expanded layout", () => + snapshotLayout(makeSpotlightExpandedLayout, { + type: "spotlight-expanded", + spotlight: spotlight.vm, + pip, + })); + +test("one-on-one desktop layout", () => + snapshotLayout(makeOneOnOneDesktopLayout, { + type: "one-on-one-desktop", + spotlight: { id: "spotlight" } as GridTileViewModel, + pip, + })); + +test("one-on-one mobile layout", () => + snapshotLayout(makeOneOnOneMobileLayout, { + type: "one-on-one-mobile", + spotlight: spotlight.vm, + pip, + })); diff --git a/src/grid/__snapshots__/CallLayout.test.tsx.snap b/src/grid/__snapshots__/CallLayout.test.tsx.snap new file mode 100644 index 000000000..4e22011e0 --- /dev/null +++ b/src/grid/__snapshots__/CallLayout.test.tsx.snap @@ -0,0 +1,186 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`grid layout 1`] = ` +
+
+
+
+
+
+
+
+
+
+`; + +exports[`one-on-one desktop layout 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`one-on-one mobile layout 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`spotlight expanded layout 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`spotlight landscape layout 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`spotlight portrait layout 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;