126 lines
4.1 KiB
TypeScript
126 lines
4.1 KiB
TypeScript
/*
|
|||
|
|
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);
|
||
|
|
});
|
||
|
|
});
|