import React from "react"; import "@testing-library/jest-dom"; import { fireEvent, render, screen, waitFor, within } from "@testing-library/react"; import { CssVarsProvider } from "@mui/material/styles"; import { api } from "./api"; import { ConfirmProvider } from "./confirm"; import { I18nProvider } from "./i18n/I18nProvider"; import { PromptProvider } from "./prompt"; import { getTheme } from "./theme"; import { ToastProvider } from "./toast"; import AdminUsersPage from "./views/AdminUsersPage"; jest.mock("./api", () => ({ api: { get: jest.fn(), put: jest.fn(), post: jest.fn(), delete: jest.fn() }, getApiErrorMessage: (_error: unknown, fallback: string) => fallback, })); const mockedApi = api as jest.Mocked; function renderPage(users: unknown[]) { mockedApi.get.mockResolvedValue({ data: users } as any); mockedApi.put.mockResolvedValue({ data: null } as any); mockedApi.delete.mockResolvedValue({ data: null } as any); render( , ); } beforeEach(() => { jest.clearAllMocks(); Object.defineProperty(window, "matchMedia", { configurable: true, value: jest.fn().mockImplementation(() => ({ matches: true, addEventListener: jest.fn(), removeEventListener: jest.fn(), addListener: jest.fn(), removeListener: jest.fn(), })), }); }); test("requires explicit confirmation before removing your own admin role", async () => { renderPage([{ id: "me", email: "me@example.com", userName: "me", roles: ["Admin"], emailConfirmed: true, isCurrentUser: true, canRemoveAdmin: true }]); fireEvent.click(await screen.findByRole("button", { name: "Remove admin" })); expect(await screen.findByText(/you will immediately lose access/i)).toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "Cancel" })); expect(mockedApi.put).not.toHaveBeenCalled(); await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); fireEvent.click(screen.getByRole("button", { name: "Remove admin" })); fireEvent.click(within(await screen.findByRole("dialog")).getByRole("button", { name: "Remove admin" })); await waitFor(() => expect(mockedApi.put).toHaveBeenCalledWith("/users/me/roles", { roles: [] })); }); test("warns before demoting another administrator", async () => { renderPage([{ id: "other", email: "other@example.com", userName: "other", roles: ["Admin"], emailConfirmed: true, isCurrentUser: false, canRemoveAdmin: true }]); fireEvent.click(await screen.findByRole("button", { name: "Remove admin" })); expect(await screen.findByText(/they will immediately lose access/i)).toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "Cancel" })); expect(mockedApi.put).not.toHaveBeenCalled(); }); test("disables demotion and deletion for the final administrator", async () => { renderPage([{ id: "me", email: "me@example.com", userName: "me", roles: ["Admin"], emailConfirmed: true, isCurrentUser: true, canRemoveAdmin: false }]); expect(await screen.findByRole("button", { name: "Remove admin" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Delete" })).toBeDisabled(); }); test("sends the exact account email after confirming deletion", async () => { renderPage([{ id: "other", email: "other@example.com", userName: "other", roles: [], emailConfirmed: true, isCurrentUser: false, canRemoveAdmin: true }]); fireEvent.click(await screen.findByRole("button", { name: "Delete" })); fireEvent.click(within(await screen.findByRole("dialog")).getByRole("button", { name: "Delete" })); await waitFor(() => expect(mockedApi.delete).toHaveBeenCalledWith("/users/other", { headers: { "X-Confirm-Account-Deletion": "other@example.com" }, })); });