supersam/src/services/smsProblemSummary.test.js

117 lines
5.6 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.

/**
* @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);
});
});