افزودن پالت فرمان (⌘K) و صفحهٔ مصرف سراسری پنل مالک
دو شکاف رسیدگیشده از بازبینی PLAN.md و TODO.md: - پالت فرمان: جستوجو و رفتن سریع بین بخشها با ⌘K/Ctrl+K، پیمایش با کلیدهای جهتدار، Enter برای رفتن، و Escape برای بستن. گروه اختصاصی «کنسول مالک سامانه» فقط برای مالک سامانه نمایش داده میشود. - صفحهٔ /admin/usage: گزارش مصرف سراسری به تفکیک سازمان. اندپوینت `GET /admin/usage` و کلاینت `adminUsage()` از قبل وجود داشتند و توسط صفحات نمای کلی و سازمانها مصرف میشدند؛ این صفحهٔ اختصاصی آن است. همچنین `NAV_ITEMS` به `lib/nav.ts` منتقل شد تا sidebar و پالت فرمان هرگز از هم واگرا نشوند. تست: ۱۰ تست جدید برای پالت فرمان. مجموع تستهای فرانتاند از ۲۵ به ۳۵ رسید. tsc، eslint و ruff تمیز.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { CommandPalette } from "@/components/CommandPalette";
|
||||
|
||||
const push = vi.fn();
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({ push }),
|
||||
usePathname: () => "/dashboard",
|
||||
}));
|
||||
|
||||
/** Opens the palette the way a user does — via the keyboard shortcut. */
|
||||
function openWithShortcut(ctrlKey = true) {
|
||||
fireEvent.keyDown(window, { key: "k", ctrlKey });
|
||||
}
|
||||
|
||||
describe("command palette", () => {
|
||||
beforeEach(() => {
|
||||
push.mockClear();
|
||||
});
|
||||
|
||||
it("starts closed and opens with the keyboard shortcut", () => {
|
||||
render(<CommandPalette />);
|
||||
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
||||
|
||||
openWithShortcut();
|
||||
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens with the macOS cmd key as well as ctrl", () => {
|
||||
render(<CommandPalette />);
|
||||
fireEvent.keyDown(window, { key: "k", metaKey: true });
|
||||
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("lists the sidebar destinations when open", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
expect(screen.getByText(/^بخش/)).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: /داشبورد/ })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("filters the destinations as the user types", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
|
||||
fireEvent.change(screen.getByLabelText("جستوجوی بخشها"), {
|
||||
target: { value: "پروژه" },
|
||||
});
|
||||
|
||||
expect(screen.getByRole("button", { name: /پروژه/ })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /داشبورد/ })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows an empty state when nothing matches", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
|
||||
fireEvent.change(screen.getByLabelText("جستوجوی بخشها"), {
|
||||
target: { value: "zzzz" },
|
||||
});
|
||||
|
||||
expect(screen.getByText("نتیجهای پیدا نشد")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("hides the platform-owner group from a regular user", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
expect(screen.queryByText("کنسول مالک سامانه")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows the platform-owner group to the owner, including global usage", () => {
|
||||
render(<CommandPalette isPlatformOwner />);
|
||||
openWithShortcut();
|
||||
expect(screen.getByText("کنسول مالک سامانه")).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: /مصرف سراسری/ })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("navigates to the highlighted destination on Enter", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
|
||||
fireEvent.keyDown(screen.getByLabelText("جستوجوی بخشها"), {
|
||||
key: "ArrowDown",
|
||||
});
|
||||
fireEvent.keyDown(screen.getByLabelText("جستوجوی بخشها"), { key: "Enter" });
|
||||
|
||||
expect(push).toHaveBeenCalledTimes(1);
|
||||
expect(push).toHaveBeenCalledWith("/manager");
|
||||
});
|
||||
|
||||
it("navigates to the destination clicked with the mouse", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /داشبورد/ }));
|
||||
expect(push).toHaveBeenCalledWith("/dashboard");
|
||||
});
|
||||
|
||||
it("closes with Escape", () => {
|
||||
render(<CommandPalette />);
|
||||
openWithShortcut();
|
||||
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
||||
|
||||
fireEvent.keyDown(screen.getByLabelText("جستوجوی بخشها"), { key: "Escape" });
|
||||
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user