supersam/src/components/admin/analytics/OrderPathFunnelBlock.test.jsx

117 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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");
});
});