117 lines
5.0 KiB
JavaScript
117 lines
5.0 KiB
JavaScript
import React from "react";
|
||
import { renderToStaticMarkup } from "react-dom/server";
|
||
import { describe, expect, it } from "vitest";
|
||
import { OrderPathFunnelBlock } from "./OrderPathFunnelBlock";
|
||
|
||
// Фикстура — блок order_path из admin_comms_funnel (реальные цифры за 30 дней на 29.09.2026).
|
||
const funnel = {
|
||
order_path: {
|
||
stages: [
|
||
{ key: "created", label: "Групп в работе", value: 396, pct: 100 },
|
||
{ key: "sms", label: "Первое SMS", value: 340, pct: 85.9 },
|
||
{ key: "dated", label: "Дата согласована", value: 161, pct: 40.7 },
|
||
{ key: "done", label: "Выдано по цепочке", value: 134, pct: 33.8 },
|
||
],
|
||
bypass: { delivered: 199, paid_storage: 3, cancelled: 0, no_confirmation: 42 },
|
||
split: { pickup: 235, delivery: 161 },
|
||
channels: [
|
||
{ channel: "manual", count: 135 },
|
||
{ channel: "sms", count: 20 },
|
||
{ channel: "call", count: 7 },
|
||
],
|
||
sources: [
|
||
{ source: "manual", count: 135 },
|
||
{ source: "autocall", count: 6 },
|
||
{ source: "none", count: 20 },
|
||
],
|
||
},
|
||
};
|
||
|
||
const empty = { order_path: { stages: [], bypass: {}, split: {}, sources: [] } };
|
||
|
||
describe("OrderPathFunnelBlock", () => {
|
||
const html = renderToStaticMarkup(<OrderPathFunnelBlock funnel={funnel} mobile={false} periodLabel="30 дней" />);
|
||
|
||
it("подписывает этапы со значениями и процентами", () => {
|
||
for (const label of ["Групп в работе", "Первое SMS", "Дата согласована", "Выдано по цепочке"]) {
|
||
expect(html).toContain(label);
|
||
}
|
||
expect(html).toContain("396 · 100%");
|
||
expect(html).toContain("340 · 85.9%");
|
||
expect(html).toContain("134 · 33.8%");
|
||
});
|
||
|
||
it("считает конверсию между ступенями", () => {
|
||
expect(html).toContain("Групп в работе → Первое SMS");
|
||
expect(html).toContain("85.9%");
|
||
expect(html).toContain("Первое SMS → Дата согласована");
|
||
expect(html).toContain("47.4%"); // 161/340
|
||
expect(html).toContain("Дата согласована → Выдано по цепочке");
|
||
});
|
||
|
||
it("честно показывает то, что прошло мимо цепочки", () => {
|
||
expect(html).toContain("Мимо цепочки (без даты)");
|
||
expect(html).toContain("выдано 199");
|
||
expect(html).toContain("платное хранение 3");
|
||
expect(html).toContain("воронка выше их не считает");
|
||
expect(html).toContain("без согласования 42");
|
||
});
|
||
|
||
it("показывает источники даты и разбивку по типу заказа", () => {
|
||
expect(html).toContain("Менеджер");
|
||
expect(html).toContain("Робот-звонок");
|
||
expect(html).toContain("В обход (без даты)");
|
||
expect(html).toContain("Самовывоз");
|
||
expect(html).toContain("235");
|
||
expect(html).toContain("Доставка");
|
||
});
|
||
|
||
it("подписывает клиентские источники даты, а не показывает ключи БД", () => {
|
||
const withClientSources = renderToStaticMarkup(
|
||
<OrderPathFunnelBlock
|
||
funnel={{
|
||
...funnel,
|
||
order_path: {
|
||
...funnel.order_path,
|
||
sources: [
|
||
{ source: "sms", count: 20 },
|
||
{ source: "client", count: 9 },
|
||
{ source: "push", count: 4 },
|
||
{ source: "messenger", count: 2 },
|
||
],
|
||
},
|
||
}}
|
||
mobile={false}
|
||
periodLabel="7 дней"
|
||
/>,
|
||
);
|
||
expect(withClientSources).toContain("SMS-ссылка");
|
||
expect(withClientSources).toContain("Ссылка (прямой заход)");
|
||
expect(withClientSources).toContain("Push");
|
||
expect(withClientSources).toContain("Мессенджер");
|
||
expect(withClientSources).not.toContain(">client<");
|
||
expect(withClientSources).not.toContain(">messenger<");
|
||
});
|
||
|
||
it("на пустом периоде пишет заглушку", () => {
|
||
const e = renderToStaticMarkup(<OrderPathFunnelBlock funnel={empty} mobile periodLabel="Сегодня" />);
|
||
expect(e).toContain("За период заказов нет");
|
||
expect(e).toContain("Путь заказа");
|
||
});
|
||
|
||
it("показывает заглушку загрузки, пока данных нет", () => {
|
||
const l = renderToStaticMarkup(<OrderPathFunnelBlock funnel={null} isLoading mobile={false} />);
|
||
expect(l).toContain("Путь заказа");
|
||
expect(l).toContain("Загружаю…");
|
||
});
|
||
|
||
it("показывает, каким каналом согласовали дату", () => {
|
||
expect(html).toContain("Как согласовали дату");
|
||
expect(html).toContain("Логист");
|
||
expect(html).toContain("SMS-ссылка");
|
||
expect(html).toContain("Звонок робота");
|
||
expect(html).toContain("135");
|
||
expect(html).toContain("20");
|
||
});
|
||
});
|