232 lines
7.2 KiB
JavaScript
232 lines
7.2 KiB
JavaScript
import React from "react";
|
||
import { MemoryRouter } from "react-router-dom";
|
||
import { renderToStaticMarkup } from "react-dom/server";
|
||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||
import { DashboardPage } from "./DashboardPage";
|
||
|
||
const { useAuthMock, useOrdersMock } = vi.hoisted(() => ({
|
||
useAuthMock: vi.fn(),
|
||
useOrdersMock: vi.fn(),
|
||
}));
|
||
|
||
vi.mock("../context/AuthContext", () => ({
|
||
useAuth: useAuthMock,
|
||
}));
|
||
|
||
vi.mock("../hooks/useOrders", () => ({
|
||
useOrders: useOrdersMock,
|
||
}));
|
||
|
||
vi.mock("../layouts/AppShell", () => ({
|
||
AppShell: ({ children, navItems, onOpenGuide, isGuideOpen }) => (
|
||
<div>
|
||
<nav>{navItems.map((item) => <span key={item.key}>{item.label}</span>)}</nav>
|
||
<button type="button" onClick={onOpenGuide} aria-label="Справка">
|
||
{isGuideOpen ? "Назад" : "?"}
|
||
</button>
|
||
{children}
|
||
</div>
|
||
),
|
||
}));
|
||
|
||
const baseOrder = {
|
||
id: "order-1",
|
||
orderNumber: "CD-240031",
|
||
status: "Ожидает согласования доставки",
|
||
updatedAt: "2026-04-15T09:00:00Z",
|
||
createdAt: "2026-04-14T09:00:00Z",
|
||
scheduledDelivery: "2026-04-16T12:00:00Z",
|
||
customer: {
|
||
name: "Мария Волкова",
|
||
phone: "+7 978 000-12-31",
|
||
address: "Симферополь, ул. Ленина, 10",
|
||
messenger: "СМС",
|
||
items: ["Кухонный гарнитур | 1 комплект"],
|
||
},
|
||
items: ["Кухонный гарнитур | 1 комплект"],
|
||
comments: ["Нужен звонок за час"],
|
||
orderNotes: [{ id: "note-1", text: "Подъезд узкий" }],
|
||
history: [],
|
||
chatMessages: [],
|
||
deliverySlots: [],
|
||
};
|
||
|
||
const baseDeliverySet = {
|
||
key: "set-1",
|
||
name: "Набор Марии Волковой",
|
||
status: "ready_to_launch",
|
||
readyAt: "2026-04-15T08:00:00Z",
|
||
readyReason: "all_accepted",
|
||
sourceCustomerCity: "Симферополь",
|
||
orderCount: 1,
|
||
linkedBillTexts: "УН-00031",
|
||
orders: [baseOrder],
|
||
};
|
||
|
||
const mockOrdersState = {
|
||
orders: [baseOrder],
|
||
allOrders: [baseOrder],
|
||
selectedOrder: baseOrder,
|
||
selectedOrderId: baseOrder.id,
|
||
setSelectedOrderId: vi.fn(),
|
||
filters: {
|
||
query: "",
|
||
status: "all",
|
||
stage: "all",
|
||
ownerRole: "all",
|
||
agingState: "all",
|
||
managerId: "all",
|
||
logisticianId: "all",
|
||
messenger: "all",
|
||
},
|
||
setFilters: vi.fn(),
|
||
notifications: [],
|
||
pushNotification: vi.fn(),
|
||
updateStatus: vi.fn(),
|
||
addChatMessage: vi.fn(),
|
||
addInternalMessage: vi.fn(),
|
||
addOrderNote: vi.fn(),
|
||
assignDriver: vi.fn(),
|
||
reassignDelivery: vi.fn(),
|
||
autoAssignLogisticians: vi.fn(),
|
||
saveDriverRouteOrder: vi.fn(),
|
||
metrics: {
|
||
total: 1,
|
||
readyToShip: 1,
|
||
awaitingDeliveryCoordination: 1,
|
||
exceptions: 0,
|
||
inLogistics: 1,
|
||
},
|
||
agingAlerts: [],
|
||
agingSummary: { warning: 0, critical: 0 },
|
||
deliverySetBuckets: {
|
||
approaching: [],
|
||
ready_to_launch: [baseDeliverySet],
|
||
awaiting_client: [],
|
||
manual_work: [],
|
||
agreed: [],
|
||
completed: [],
|
||
},
|
||
users: [
|
||
{ id: "u-manager", name: "Анна", role: "manager" },
|
||
{ id: "u-logistics", name: "Ольга", role: "logistician" },
|
||
{ id: "u-driver", name: "Иван", role: "driver" },
|
||
],
|
||
isSupabaseBacked: true,
|
||
isLoading: false,
|
||
loadError: "",
|
||
};
|
||
|
||
describe("DashboardPage", () => {
|
||
beforeEach(() => {
|
||
vi.useFakeTimers();
|
||
vi.setSystemTime(new Date("2026-04-15T09:00:00Z"));
|
||
useOrdersMock.mockReturnValue(mockOrdersState);
|
||
});
|
||
|
||
it("keeps the manager dashboard on the delivery registry only", () => {
|
||
useAuthMock.mockReturnValue({
|
||
user: { id: "u-manager", name: "Анна", role: "manager" },
|
||
signOut: vi.fn(),
|
||
});
|
||
|
||
const markup = renderToStaticMarkup(
|
||
<MemoryRouter>
|
||
<DashboardPage />
|
||
</MemoryRouter>,
|
||
);
|
||
|
||
expect(markup).toContain("Реестр заказов");
|
||
expect(markup).toContain("Поиск по номеру, клиенту и телефону.");
|
||
expect(markup).toContain("aria-label=\"Справка\"");
|
||
expect(markup).not.toContain("<span>Справка</span>");
|
||
expect(markup).not.toContain("доставочный контур");
|
||
expect(markup).not.toContain("Поиск по заказу, клиенту и телефону");
|
||
expect(markup).not.toContain("Интерфейс показывает");
|
||
expect(markup).not.toContain("Производство");
|
||
expect(markup).not.toContain("Администрирование");
|
||
expect(markup).not.toContain("Справочники");
|
||
expect(markup).not.toContain("Календарь");
|
||
expect(markup).not.toContain("Канбан");
|
||
expect(markup).not.toContain("История");
|
||
expect(markup).not.toContain("Архив");
|
||
});
|
||
|
||
afterEach(() => {
|
||
vi.useRealTimers();
|
||
});
|
||
|
||
it("keeps the logistician dashboard free of bot control and extra workspace", () => {
|
||
useAuthMock.mockReturnValue({
|
||
user: { id: "u-logistics", name: "Ольга", role: "logistician" },
|
||
signOut: vi.fn(),
|
||
});
|
||
|
||
const markup = renderToStaticMarkup(
|
||
<MemoryRouter>
|
||
<DashboardPage />
|
||
</MemoryRouter>,
|
||
);
|
||
|
||
expect(markup).toContain("Наборы доставки");
|
||
expect(markup).toContain("Готово к запуску");
|
||
expect(markup).not.toContain("Управление ботами");
|
||
expect(markup).not.toContain("рабочая панель");
|
||
expect(markup).not.toContain("Сегодня");
|
||
expect(markup).not.toContain("Производство");
|
||
expect(markup).not.toContain("Администрирование");
|
||
expect(markup).not.toContain("Справочники");
|
||
});
|
||
|
||
it("keeps the driver dashboard on the deliveries list only", () => {
|
||
useOrdersMock.mockReturnValue({
|
||
...mockOrdersState,
|
||
orders: [
|
||
{
|
||
...baseOrder,
|
||
id: "driver-order-1",
|
||
status: "Назначен водитель",
|
||
scheduledDelivery: "2026-04-15T12:00:00Z",
|
||
deliverySlots: [{ id: "slot-1", date: "2026-04-15", time: "До обеда" }],
|
||
},
|
||
],
|
||
allOrders: [
|
||
{
|
||
...baseOrder,
|
||
id: "driver-order-1",
|
||
status: "Назначен водитель",
|
||
scheduledDelivery: "2026-04-15T12:00:00Z",
|
||
deliverySlots: [{ id: "slot-1", date: "2026-04-15", time: "До обеда" }],
|
||
},
|
||
],
|
||
selectedOrder: {
|
||
...baseOrder,
|
||
id: "driver-order-1",
|
||
status: "Назначен водитель",
|
||
scheduledDelivery: "2026-04-15T12:00:00Z",
|
||
deliverySlots: [{ id: "slot-1", date: "2026-04-15", time: "До обеда" }],
|
||
},
|
||
selectedOrderId: "driver-order-1",
|
||
});
|
||
useAuthMock.mockReturnValue({
|
||
user: { id: "u-driver", name: "Иван", role: "driver" },
|
||
signOut: vi.fn(),
|
||
});
|
||
|
||
const markup = renderToStaticMarkup(
|
||
<MemoryRouter>
|
||
<DashboardPage />
|
||
</MemoryRouter>,
|
||
);
|
||
|
||
expect(markup).toContain("Мои доставки");
|
||
expect(markup).toContain("CD-240031");
|
||
expect(markup).toContain("Мария Волкова");
|
||
expect(markup).not.toContain("Канбан");
|
||
expect(markup).not.toContain("Календарь");
|
||
expect(markup).not.toContain("История");
|
||
expect(markup).not.toContain("Архив");
|
||
expect(markup).not.toContain("Производство");
|
||
});
|
||
});
|