Files
nobat724_front/components/dashboard/userAccount/sidebars/turns/Card.test.jsx
T
hamedandClaude Opus 5 ae958eee73 feat(booking): show services and duration on the user panel appointment
A patient who booked in service mode could not see which services they had
reserved or how long the appointment was. Both now appear on the list card and in
both detail layouts, reading service_items and service_total_minutes from
GET /api/v1/appointments/user.

Every field is behind an explicit guard. Slot-mode appointments carry none of
them, and an unguarded map would crash the card for every slot-mode appointment,
taking the whole panel with it. A reserve entry shows its services but not a
duration, because it has no time.

Covered by Card.test.jsx: slot-mode appointments render unchanged, absent fields
(older backend) do not crash, reserve hides the duration, and a zero duration
produces no row.

Task: clinicpro/docs/new_feture/taskes/task-00b-nobat724-service-mode/

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 15:53:18 +03:30

86 lines
3.9 KiB
React

import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import Card from "./Card";
// آیکن و لودینگ‌ها به این تست ربطی ندارند؛ فقط باید کودکشان را رندر کنند.
vi.mock("@/app/component/loading/Text", () => ({
default: ({ children }) => <>{children}</>,
}));
vi.mock("@/app/component/loading/Circular", () => ({
default: ({ children }) => <>{children}</>,
}));
vi.mock("@/components/icons/ArrowLeftCardD", () => ({ default: () => null }));
vi.mock("next/image", () => ({ default: () => null }));
const base = {
uuid: "ap1",
status: "confirmed",
slot_start: 1785567600,
doctor: { name: "دکتر تست" },
};
function renderCard(data) {
return render(<Card data={{ ...base, ...data }} loading={false} setIsTurnsDetails={() => {}} />);
}
describe("Card نوبت — فیلدهای حالت سرویسی", () => {
// ── ✅ موفق ──────────────────────────────────────────────────────────────
it("نام همهٔ سرویس‌ها و مدت نوبت را نشان می‌دهد", () => {
renderCard({
service_items: [{ uuid: "s1", name: "لیزر صورت" }, { uuid: "s2", name: "لیزر بیکینی" }],
service_total_minutes: 35,
});
expect(screen.getByText("سرویس:")).toBeInTheDocument();
expect(screen.getByText("لیزر صورت، لیزر بیکینی")).toBeInTheDocument();
expect(screen.getByText("مدت نوبت:")).toBeInTheDocument();
expect(screen.getByText("35 دقیقه")).toBeInTheDocument();
});
// ── ❌ خط سرخ: نوبت اسلاتی ────────────────────────────────────────────────
it("نوبت اسلاتی هیچ‌کدام از دو ردیف را نمی‌گیرد و کرش نمی‌کند", () => {
renderCard({ service_items: [], service_total_minutes: null });
expect(screen.queryByText("سرویس:")).not.toBeInTheDocument();
expect(screen.queryByText("مدت نوبت:")).not.toBeInTheDocument();
// ردیف‌های موجود سر جایشان‌اند.
expect(screen.getByText("تاریخ نوبت:")).toBeInTheDocument();
expect(screen.getByText("ساعت نوبت:")).toBeInTheDocument();
});
it("فیلدهای سرویسی کاملاً غایب (بک‌اند قدیمی) هم کرش نمی‌دهد", () => {
renderCard({});
expect(screen.queryByText("سرویس:")).not.toBeInTheDocument();
expect(screen.getByText("تاریخ نوبت:")).toBeInTheDocument();
});
// ── ⚠️ مرزی ──────────────────────────────────────────────────────────────
it("نوبت رزرو سرویس را نشان می‌دهد ولی مدت را نه (زمان ندارد)", () => {
renderCard({
is_reserve: true,
service_items: [{ uuid: "s1", name: "لیزر" }],
service_total_minutes: 45,
});
expect(screen.getByText("لیزر")).toBeInTheDocument();
expect(screen.queryByText("مدت نوبت:")).not.toBeInTheDocument();
});
it("سرویس بدون مدت → فقط ردیف سرویس", () => {
renderCard({ service_items: [{ uuid: "s1", name: "مشاوره" }], service_total_minutes: null });
expect(screen.getByText("مشاوره")).toBeInTheDocument();
expect(screen.queryByText("مدت نوبت:")).not.toBeInTheDocument();
});
it("مدت صفر ردیف نمی‌سازد", () => {
renderCard({ service_items: [{ uuid: "s1", name: "مشاوره" }], service_total_minutes: 0 });
expect(screen.queryByText("مدت نوبت:")).not.toBeInTheDocument();
});
});