Files
element-call/src/lotus/LotusScreensharePrompt.test.tsx
T

126 lines
4.1 KiB
TypeScript
Raw Normal View History

/*
Copyright 2026 Lotus Guild
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { afterEach, describe, expect, it, vi } from "vitest";
import { act, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { TooltipProvider } from "@vector-im/compound-web";
import { BehaviorSubject } from "rxjs";
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
import { LotusScreensharePrompt } from "./LotusScreensharePrompt";
import {
lotusFrameScreenshareEnabled,
lotusFrameScreenshareVisible$,
lotusScreensharePrompt$,
shouldPromptScreenshare,
} from "./lotusControls";
// lotusFlag memoizes the URL params on first read, so set them once here.
window.history.pushState(
{},
"",
"/?lotusHostControls=1&lotusFrameScreenshare=1",
);
const mockVm = (
toggle: (() => void) | null,
sharing = new BehaviorSubject(false),
): CallViewModel =>
({
sharingScreen$: sharing,
toggleScreenSharing: toggle,
}) as unknown as CallViewModel;
const renderPrompt = (vm: CallViewModel): void => {
render(
<TooltipProvider>
<LotusScreensharePrompt vm={vm} />
</TooltipProvider>,
);
};
const prompt = (): HTMLElement | null =>
screen.queryByTestId("lotus_screenshare_prompt");
afterEach(() => {
act(() => {
lotusScreensharePrompt$.next(false);
lotusFrameScreenshareVisible$.next(true);
});
});
describe("LotusScreensharePrompt", () => {
it("is enabled by lotusHostControls + lotusFrameScreenshare", () => {
expect(lotusFrameScreenshareEnabled()).toBe(true);
});
it("stays hidden until the host asks", () => {
renderPrompt(mockVm(vi.fn()));
expect(prompt()).toBeNull();
act(() => lotusScreensharePrompt$.next(true));
expect(prompt()).toBeInTheDocument();
expect(
screen.getByRole("alertdialog", { name: "Share your screen?" }),
).toBeInTheDocument();
});
it("focuses Share, and Share starts the share and closes", async () => {
const toggle = vi.fn();
renderPrompt(mockVm(toggle));
act(() => lotusScreensharePrompt$.next(true));
const share = screen.getByTestId("lotus_screenshare_prompt_share");
expect(share).toHaveFocus();
await userEvent.click(share);
expect(toggle).toHaveBeenCalledTimes(1);
expect(prompt()).toBeNull();
});
it("Cancel and Escape close without sharing", async () => {
const toggle = vi.fn();
renderPrompt(mockVm(toggle));
act(() => lotusScreensharePrompt$.next(true));
await userEvent.click(screen.getByRole("button", { name: "Cancel" }));
expect(prompt()).toBeNull();
act(() => lotusScreensharePrompt$.next(true));
await userEvent.keyboard("{Escape}");
expect(prompt()).toBeNull();
expect(toggle).not.toHaveBeenCalled();
});
it("closes when a share starts some other way", () => {
const sharing = new BehaviorSubject(false);
renderPrompt(mockVm(vi.fn(), sharing));
act(() => lotusScreensharePrompt$.next(true));
act(() => sharing.next(true));
expect(prompt()).toBeNull();
});
it("closes when the room's policy stops allowing screensharing", () => {
renderPrompt(mockVm(vi.fn()));
act(() => lotusScreensharePrompt$.next(true));
act(() => lotusFrameScreenshareVisible$.next(false));
expect(prompt()).toBeNull();
});
it("renders nothing when screensharing is unavailable", () => {
renderPrompt(mockVm(null));
act(() => lotusScreensharePrompt$.next(true));
expect(prompt()).toBeNull();
});
});
describe("shouldPromptScreenshare", () => {
const ok = { enabled: true, allowed: true, canShare: true, sharing: false };
it("prompts only in prompt mode, when allowed, able and not sharing", () => {
expect(shouldPromptScreenshare(ok)).toBe(true);
expect(shouldPromptScreenshare({ ...ok, enabled: false })).toBe(false);
expect(shouldPromptScreenshare({ ...ok, allowed: false })).toBe(false);
expect(shouldPromptScreenshare({ ...ok, canShare: false })).toBe(false);
expect(shouldPromptScreenshare({ ...ok, sharing: true })).toBe(false);
});
});