122 lines
5.4 KiB
JavaScript
122 lines
5.4 KiB
JavaScript
import { CacheProvider } from "@emotion/react";
|
|
import { render, screen, within } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { MemoryRouter, Route, Routes } from "react-router-dom";
|
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
import { externalEmotionCache } from "../i18n/emotionCache.js";
|
|
import { ExternalI18nProvider } from "../i18n/ExternalI18nProvider.jsx";
|
|
import { EXTERNAL_LOCALE_STORAGE_KEY } from "../i18n/messages.js";
|
|
import { ExternalAdminLayout } from "./ExternalAdminLayout.jsx";
|
|
|
|
const auth = vi.hoisted(() => ({
|
|
logout: vi.fn(),
|
|
session: {
|
|
account: "fami-manager",
|
|
appCode: "fami",
|
|
appName: "Fami",
|
|
logoUrl: "https://media.example.com/apps/fami.png",
|
|
capabilities: ["user:list", "room:list"]
|
|
}
|
|
}));
|
|
const viewport = vi.hoisted(() => ({ mobile: false }));
|
|
|
|
vi.mock("../auth/ExternalAuthProvider.jsx", () => ({ useExternalAuth: () => auth }));
|
|
vi.mock("@mui/material/useMediaQuery", () => ({ default: () => viewport.mobile }));
|
|
|
|
describe("ExternalAdminLayout RTL", () => {
|
|
beforeEach(() => {
|
|
localStorage.setItem(EXTERNAL_LOCALE_STORAGE_KEY, "ar");
|
|
viewport.mobile = false;
|
|
auth.session = {
|
|
account: "fami-manager",
|
|
appCode: "fami",
|
|
appName: "Fami",
|
|
logoUrl: "https://media.example.com/apps/fami.png",
|
|
capabilities: ["user:list", "room:list"]
|
|
};
|
|
});
|
|
|
|
test("shows the H5 tab bar and opens the more sheet in Arabic", async () => {
|
|
const user = userEvent.setup();
|
|
viewport.mobile = true;
|
|
renderLayout();
|
|
|
|
const tabbar = document.querySelector(".external-tabbar");
|
|
expect(tabbar).toBeInTheDocument();
|
|
expect(within(tabbar).getByRole("link", { name: "الرئيسية" })).toBeInTheDocument();
|
|
|
|
await user.click(within(tabbar).getByRole("button", { name: "المزيد" }));
|
|
|
|
const sheet = document.querySelector(".MuiDrawer-paper.external-sheet");
|
|
expect(sheet).toBeInTheDocument();
|
|
expect(sheet.closest(".MuiModal-root")).not.toBeNull();
|
|
expect(within(sheet).getByRole("link", { name: "الرئيسية" })).toBeInTheDocument();
|
|
expect(within(sheet).getByRole("button", { name: "تسجيل الخروج" })).toBeInTheDocument();
|
|
});
|
|
|
|
test("places the desktop navigation drawer on the right for Arabic", () => {
|
|
const view = renderLayout();
|
|
|
|
expect(document.documentElement).toHaveAttribute("dir", "rtl");
|
|
expect(document.documentElement).toHaveAttribute("lang", "ar");
|
|
const permanentDrawer = document.querySelectorAll(".MuiDrawer-paper")[0];
|
|
// Emotion prefixes generated classes with the cache key, so the RTL cache yields external-rtl-*.
|
|
const generatedClass = Array.from(permanentDrawer.classList).find((className) => className.startsWith("external-rtl-") || className.startsWith("css-"));
|
|
const drawerRule = Array.from(document.styleSheets)
|
|
.flatMap((sheet) => Array.from(sheet.cssRules || []))
|
|
.map((rule) => rule.cssText)
|
|
.find((cssText) => cssText.includes(`.${generatedClass}`));
|
|
expect(drawerRule).toContain("right: 0px");
|
|
expect(drawerRule).toContain("border-left:");
|
|
expect(document.querySelector(".external-sidebar-brand img")).toHaveAttribute("src", "https://media.example.com/apps/fami.png");
|
|
expect(screen.getAllByText("Fami").length).toBeGreaterThan(0);
|
|
expect(screen.queryByText("إدارة HYApp الخارجية")).not.toBeInTheDocument();
|
|
expect(document.title).toBe("Fami");
|
|
expect(document.head.querySelector('link[data-external-app-favicon="true"]')).toHaveAttribute("href", "https://media.example.com/apps/fami.png");
|
|
expect(screen.getAllByText("الرئيسية").length).toBeGreaterThan(0);
|
|
expect(screen.getByRole("combobox", { name: "اللغة" })).toHaveTextContent("العربية");
|
|
|
|
view.unmount();
|
|
expect(document.title).toBe("الإدارة الخارجية");
|
|
expect(document.head.querySelector('link[data-external-app-favicon="true"]')).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("uses the App name, logo and title resolved by the authenticated session", () => {
|
|
auth.session = {
|
|
...auth.session,
|
|
account: "lalu-manager",
|
|
appCode: "lalu",
|
|
appName: "Lalu",
|
|
logoUrl: "https://media.example.com/apps/lalu.png"
|
|
};
|
|
const view = renderLayout();
|
|
|
|
expect(screen.getAllByText("Lalu").length).toBeGreaterThan(0);
|
|
expect(document.querySelector(".external-sidebar-brand img")).toHaveAttribute("src", "https://media.example.com/apps/lalu.png");
|
|
expect(document.title).toBe("Lalu");
|
|
expect(document.head.querySelector('link[data-external-app-favicon="true"]')).toHaveAttribute("href", "https://media.example.com/apps/lalu.png");
|
|
|
|
view.unmount();
|
|
expect(document.title).toBe("الإدارة الخارجية");
|
|
expect(document.head.querySelector('link[data-external-app-favicon="true"]')).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
function renderLayout() {
|
|
// The RTL Emotion cache is part of the production setup: physical styles are written
|
|
// for LTR and flipped by the cache, so the test must run the same pipeline.
|
|
return render(
|
|
<CacheProvider value={externalEmotionCache("rtl")}>
|
|
<ExternalI18nProvider>
|
|
<MemoryRouter initialEntries={["/overview"]}>
|
|
<Routes>
|
|
<Route element={<ExternalAdminLayout />}>
|
|
<Route element={<div>overview content</div>} path="/overview" />
|
|
</Route>
|
|
</Routes>
|
|
</MemoryRouter>
|
|
</ExternalI18nProvider>
|
|
</CacheProvider>
|
|
);
|
|
}
|