import { fireEvent, render, screen } from "@testing-library/react";
import { beforeAll, describe, expect, it, vi } from "vitest";
import VisibilitySelector from "@/components/MemoEditor/Toolbar/VisibilitySelector";
import { Visibility } from "@/types/proto/api/v1/memo_service_pb";
vi.mock("@/utils/i18n", () => ({ useTranslate: () => (key: string) => key }));
// Base UI menus reach for layout/pointer APIs jsdom doesn't implement.
beforeAll(() => {
Element.prototype.scrollIntoView = vi.fn();
Element.prototype.hasPointerCapture = vi.fn(() => false);
Element.prototype.setPointerCapture = vi.fn();
Element.prototype.releasePointerCapture = vi.fn();
});
const openMenu = async (value: Visibility, onChange = vi.fn(), space?: string) => {
render();
fireEvent.click(screen.getByRole("button"));
await screen.findByRole("menu");
return onChange;
};
describe("VisibilitySelector", () => {
it("omits the Space audience when the edited memo has no Space placement", async () => {
await openMenu(Visibility.PRIVATE);
expect(screen.getAllByRole("menuitem").map((item) => item.textContent)).toEqual([
"memo.visibility.privatememo.visibility.private-description",
"memo.visibility.protectedmemo.visibility.protected-description",
"memo.visibility.publicmemo.visibility.public-description",
]);
});
it("offers the Space audience with its own description when the edited memo belongs to a Space", async () => {
await openMenu(Visibility.PRIVATE, vi.fn(), "spaces/product");
const spaceItem = screen.getByRole("menuitem", { name: /memo\.visibility\.space/ });
expect(spaceItem).toHaveTextContent("memo.visibility.space-description");
});
it("names the current Space audience even when placement is unavailable", () => {
render();
expect(screen.getByRole("button")).toHaveTextContent("memo.visibility.space");
});
it("keeps the current Space audience selectable when placement is unavailable", async () => {
await openMenu(Visibility.SPACE);
expect(screen.getByRole("menuitem", { name: /memo\.visibility\.space/ })).toBeInTheDocument();
});
it("reports the picked audience", async () => {
const onChange = await openMenu(Visibility.PRIVATE);
fireEvent.click(screen.getByRole("menuitem", { name: /memo\.visibility\.public/ }));
expect(onChange).toHaveBeenCalledWith(Visibility.PUBLIC);
});
});