/* 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( , ); }; 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); }); });