Files
clinicpro/assets/admin/pages/MySecretariesPageClinic.test.tsx
T

153 lines
6.7 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from "vitest";
import { screen, fireEvent, waitFor, within } from "@testing-library/react";
import { renderWithProviders } from "../test/utils";
vi.mock("sonner", () => ({ toast: { success: vi.fn(), error: vi.fn(), warning: vi.fn() } }));
vi.mock("../lib/api", () => ({
api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() },
ApiError: class extends Error {},
}));
vi.mock("../stores/authStore", () => ({
useAuthStore: () => ({ doctorUuid: null, dbUuid: "clinic-1", primaryRole: "clinic" }),
}));
vi.mock("../hooks/useSubscription", () => ({
useSubscription: () => ({ maxSecretaries: 5 }),
}));
import { api } from "../lib/api";
import MySecretariesPage from "./MySecretariesPage";
const get = api.get as ReturnType<typeof vi.fn>;
const patch = api.patch as ReturnType<typeof vi.fn>;
const put = api.put as ReturnType<typeof vi.fn>;
/** یک منشیِ مشترک بین دو پزشک = دو ردیف لینک با secretary_uuid یکسان */
const sharedSecretaryRows = [
{
uuid: "link-a",
secretary_uuid: "sec-1",
user_name: "ساسان عطایی",
mobile_number: "09120671732",
doctor_name: "دکتر الف",
doctor_uuid: "doc-a",
is_active: true,
national_code: "1212121212",
address: null,
permissions: {},
created_at: "1750000000",
},
{
uuid: "link-b",
secretary_uuid: "sec-1",
user_name: "ساسان عطایی",
mobile_number: "09120671732",
doctor_name: "دکتر ب",
doctor_uuid: "doc-b",
is_active: true,
national_code: "1212121212",
address: null,
permissions: {},
created_at: "1750000000",
},
];
beforeEach(() => {
get.mockReset();
patch.mockReset();
put.mockReset();
patch.mockResolvedValue({ success: true, data: {} });
put.mockResolvedValue({ success: true, data: {} });
get.mockImplementation((url: string) => {
if (url.includes("/clinic/doctor-list/"))
return Promise.resolve({ success: true, data: { data: [
{ uuid: "doc-a", name: "دکتر الف" },
{ uuid: "doc-b", name: "دکتر ب" },
] } });
if (url.includes("/secretaries/clinic/")) return Promise.resolve({ success: true, data: [] });
return Promise.resolve({ success: true, data: [] });
});
});
describe("MySecretariesPage — clinic multi-doctor", () => {
it("shows the doctor multi-select inside the add modal", async () => {
renderWithProviders(<MySecretariesPage />, { route: "/admin/my-secretaries" });
// پیکر روی صفحه نیست تا وقتی مودال باز شود
expect(screen.queryByText("پزشکانِ این منشی")).not.toBeInTheDocument();
fireEvent.click(await screen.findByText("اضافه کردن منشی"));
expect(await screen.findByText("پزشکانِ این منشی")).toBeInTheDocument();
expect(screen.getByText("دکتر الف")).toBeInTheDocument();
expect(screen.getByText("دکتر ب")).toBeInTheDocument();
expect(screen.getByText("انتخاب همه")).toBeInTheDocument();
});
it("selecting all picks every clinic doctor", async () => {
renderWithProviders(<MySecretariesPage />, { route: "/admin/my-secretaries" });
fireEvent.click(await screen.findByText("اضافه کردن منشی"));
await screen.findByText("پزشکانِ این منشی");
fireEvent.click(screen.getByText("انتخاب همه"));
expect(screen.getByText(/[۲2] انتخاب‌شده/)).toBeInTheDocument();
expect(screen.getByText("لغو همه")).toBeInTheDocument();
});
});
describe("MySecretariesPage — one row per secretary", () => {
beforeEach(() => {
get.mockImplementation((url: string) => {
if (url.includes("/clinic/doctor-list/"))
return Promise.resolve({ success: true, data: { data: [
{ uuid: "doc-a", name: "دکتر الف" },
{ uuid: "doc-b", name: "دکتر ب" },
] } });
if (url.includes("/secretaries/clinic/"))
return Promise.resolve({ success: true, data: sharedSecretaryRows });
return Promise.resolve({ success: true, data: [] });
});
});
it("renders a secretary shared by two doctors as a single row", async () => {
renderWithProviders(<MySecretariesPage />, { route: "/admin/my-secretaries" });
const table = within(await screen.findByRole("table"));
expect(table.getAllByText("ساسان عطایی")).toHaveLength(1);
expect(table.getByText("دکتر الف، دکتر ب")).toBeInTheDocument();
});
it("cancelling collaboration deactivates every link row", async () => {
renderWithProviders(<MySecretariesPage />, { route: "/admin/my-secretaries" });
const table = within(await screen.findByRole("table"));
// اولین «لغو همکاری» عنوان ستون است؛ دکمه‌ی ردیف مورد نظر است
fireEvent.click(table.getByRole("button", { name: "لغو همکاری" }));
// متن تأیید باید تعداد پزشکان را نشان دهد
expect(await screen.findByText(/برای همه‌ی .* پزشک/)).toBeInTheDocument();
fireEvent.click(screen.getAllByText("لغو همکاری").pop()!);
await waitFor(() => expect(patch).toHaveBeenCalledTimes(2));
expect(patch).toHaveBeenCalledWith("/api/v1/secretary/link-a", { active: false });
expect(patch).toHaveBeenCalledWith("/api/v1/secretary/link-b", { active: false });
});
it("editing patches every link row and syncs the doctor set", async () => {
renderWithProviders(<MySecretariesPage />, { route: "/admin/my-secretaries" });
fireEvent.click((await screen.findAllByTitle("ویرایش"))[0]);
// مجموعه‌ی پزشکانِ فعلی باید از قبل انتخاب شده باشد
expect(await screen.findByText("پزشکانِ این منشی")).toBeInTheDocument();
expect(screen.getByText(/[۲2] انتخاب‌شده/)).toBeInTheDocument();
// حذف یکی از پزشکان (آخرین مورد = ردیف لیست، نه چیپ انتخاب‌شده)
fireEvent.click(screen.getAllByText("دکتر ب").pop()!);
fireEvent.click(screen.getByText("ذخیره"));
await waitFor(() => expect(put).toHaveBeenCalledTimes(1));
expect(patch).toHaveBeenCalledTimes(2);
expect(put).toHaveBeenCalledWith("/api/v1/secretaries/clinic/clinic-1/doctors", {
secretary_uuid: "sec-1",
doctor_uuids: ["doc-a"],
});
});
});