117 lines
5.6 KiB
JavaScript
117 lines
5.6 KiB
JavaScript
/**
|
||
* @file smsProblemSummary.test.js
|
||
* @description Что показывать над таблицей: причина недоставки, «всё наладилось»,
|
||
* предупреждение о низком балансе — и когда не показывать ничего.
|
||
*/
|
||
import { describe, it, expect } from "vitest";
|
||
import { summarizeSmsFailures } from "./smsProblemSummary";
|
||
|
||
const row = (over = {}) => ({
|
||
order_group_id: "g1",
|
||
campaign_type: "first_sms",
|
||
status: "send_failed",
|
||
sms_code: "201",
|
||
error_message: "201\n",
|
||
created_at: "2026-09-10T10:06:11Z",
|
||
...over,
|
||
});
|
||
|
||
const daysAgo = (days) => new Date(Date.now() - days * 86400000).toISOString();
|
||
|
||
describe("summarizeSmsFailures — причина недоставки", () => {
|
||
it("объясняет нехватку средств и считает заказы с сообщениями", () => {
|
||
const summary = summarizeSmsFailures([
|
||
row({ order_group_id: "g1", created_at: "2026-09-10T10:06:11Z" }),
|
||
row({ order_group_id: "g2", created_at: "2026-09-13T06:03:03Z" }),
|
||
row({ order_group_id: "g2", created_at: "2026-09-13T06:03:04Z" }),
|
||
], ["g1", "g2"]);
|
||
|
||
expect(summary.kind).toBe("funds");
|
||
expect(summary.reason).toBe("на счёте SMS-сервиса закончились средства");
|
||
expect(summary.groups).toBe(2);
|
||
expect(summary.messages).toBe(3);
|
||
expect(summary.affectedInTable).toBe(2);
|
||
});
|
||
|
||
it("берёт самую частую причину, когда их несколько", () => {
|
||
const summary = summarizeSmsFailures([
|
||
row({ order_group_id: "g1", sms_code: "202", error_message: "202" }),
|
||
row({ order_group_id: "g2" }),
|
||
row({ order_group_id: "g3" }),
|
||
], []);
|
||
|
||
expect(summary.reason).toBe("на счёте SMS-сервиса закончились средства");
|
||
expect(summary.topMessages).toBe(2);
|
||
});
|
||
|
||
it("другая причина — отдельный вид блока", () => {
|
||
const summary = summarizeSmsFailures([row({ sms_code: "202", error_message: "202" })], []);
|
||
expect(summary.kind).toBe("other");
|
||
});
|
||
});
|
||
|
||
describe("summarizeSmsFailures — актуальность по балансу", () => {
|
||
it("счёт пополнен: вместо красного предупреждения — «всё наладилось»", () => {
|
||
const summary = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 12717.45 });
|
||
expect(summary.kind).toBe("resolved");
|
||
expect(summary.balance).toBe(12717.45);
|
||
});
|
||
|
||
it("денег на счёте нет: проблема актуальна", () => {
|
||
const summary = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 42 });
|
||
expect(summary.kind).toBe("funds");
|
||
});
|
||
|
||
it("баланс узнать не удалось — считаем проблему актуальной", () => {
|
||
const summary = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: null });
|
||
expect(summary.kind).toBe("funds");
|
||
});
|
||
|
||
it("старая история не висит месяцами: неделя прошла — не показываем", () => {
|
||
const summary = summarizeSmsFailures([row({ created_at: daysAgo(8) })], [], { balance: 12717.45 });
|
||
expect(summary).toBeNull();
|
||
});
|
||
|
||
it("«всё наладилось» живёт день-два и гаснет само", () => {
|
||
const fresh = summarizeSmsFailures([row({ created_at: daysAgo(0.5) })], [], { balance: 12717.45 });
|
||
expect(fresh.kind).toBe("resolved");
|
||
const stale = summarizeSmsFailures([row({ created_at: daysAgo(3) })], [], { balance: 12717.45 });
|
||
expect(stale).toBeNull();
|
||
});
|
||
|
||
it("отпечаток не зависит от суммы на счёте — закрытый баннер не возвращается", () => {
|
||
const a = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 12717.45 });
|
||
const b = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 11122.69 });
|
||
expect(a.signature).toBe(b.signature);
|
||
});
|
||
|
||
it("ошибок нет, но денег мало — предупреждаем заранее", () => {
|
||
const summary = summarizeSmsFailures([], [], { balance: 55 });
|
||
expect(summary.kind).toBe("low_balance");
|
||
expect(summary.balance).toBe(55);
|
||
expect(summary.reason).toBeNull();
|
||
});
|
||
|
||
it("ошибок нет и денег достаточно — блок не нужен", () => {
|
||
expect(summarizeSmsFailures([], [], { balance: 12717.45 })).toBeNull();
|
||
expect(summarizeSmsFailures(null, [], { balance: null })).toBeNull();
|
||
});
|
||
});
|
||
|
||
describe("отпечаток состояния для закрытия блока", () => {
|
||
it("меняется, когда проблема другая — закрытый блок вернётся с новой ошибкой", () => {
|
||
const first = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 42 });
|
||
const second = summarizeSmsFailures([row({ created_at: daysAgo(2) })], [], { balance: 42 });
|
||
const third = summarizeSmsFailures([row({ created_at: daysAgo(1), sms_code: "202", error_message: "202" })], [], { balance: 42 });
|
||
|
||
expect(first.signature).not.toBe(second.signature);
|
||
expect(first.signature).not.toBe(third.signature);
|
||
});
|
||
|
||
it("одинаковые данные — одинаковый отпечаток (повторно не всплывает)", () => {
|
||
const a = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 42 });
|
||
const b = summarizeSmsFailures([row({ created_at: daysAgo(1) })], [], { balance: 42 });
|
||
expect(a.signature).toBe(b.signature);
|
||
});
|
||
});
|