Files
portal/app/tests/Feature/ClientTg/PrichinaDlyaKlientaTest.php
T
Дмитрий 13ce301ab3 feat телеграм: разбор застрявших кампаний и человеческий язык отказов
Кампания, брошенная роботом на полпути, попадала в needs_review или
draft_ready — статусы, из которых не вело ни одного перехода. Замороженные
деньги клиента запирались навсегда, снять их мог только программист правкой
боевой базы. В бою 06.08.2026 так заперло 268,80 ₽ по кампании №14.

Теперь в админке есть карточка «Застрявшие кампании»: владелец видит номер
кампании в кабинете МТС, запертую сумму и уже уплаченную МТС сумму — и решает
сам. Кнопка «списать по факту» показывается ТОЛЬКО когда МТС уже уплачено;
иначе списывать было бы нечего, кроме сметы — ровно та беда, ради которой
заморозку и заводили.

Заодно: клиенту больше не показывают внутренние адреса и команды запуска —
причина отказа переводится на человеческий язык. Портал перестал принимать
пустой отчёт робота как успешный.

Проверено: модуль 354 теста, экраны 13 тестов, статанализ 0 ошибок.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 14:56:50 +03:00

69 lines
3.8 KiB
PHP
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.
<?php
declare(strict_types=1);
use App\Services\ClientTg\PrichinaDlyaKlienta;
/**
* Приёмка 06.08.2026, боевой прогон: в карточке кампании у ПЛАТЯЩЕГО клиента стояло
* дословно «Вход в кабинет МТС потерян — нужен вход руками (npm run login)», а после
* второго прогона — «После «Продолжить» не перешли на /\/budget$/ (шаг «Объявление»);
* текущий URL: https://marketolog.mts.ru/...».
*
* Клиент не программист: команда разработчика и внутренний адрес в его карточке —
* не объяснение, а мусор. Полный текст остаётся в журнале (Log::warning уже пишет
* 'reason'), клиенту показываем человеческую фразу.
*
* 🔴 Отказ МОДЕРАЦИИ МТС через этот перевод НЕ проходит: там текст их модератора,
* и клиенту он нужен дословно — иначе он не поймёт, что править.
*/
it('пустую причину не выдумывает', function () {
expect(PrichinaDlyaKlienta::perevesti(null))->toBeNull();
expect(PrichinaDlyaKlienta::perevesti(''))->toBeNull();
expect(PrichinaDlyaKlienta::perevesti(' '))->toBeNull();
});
it('прячет команду разработчика за человеческой фразой', function () {
$text = PrichinaDlyaKlienta::perevesti('Вход в кабинет МТС потерян — нужен вход руками (npm run login)');
expect($text)->not->toContain('npm')
->and($text)->not->toContain('run login')
->and($text)->toContain('кабинет');
});
it('прячет внутренний адрес и регулярку', function () {
$vnutri = 'После «Продолжить» не перешли на /\/budget$/ (шаг «Объявление»); текущий URL: https://marketolog.mts.ru/cabinet/campaign/telegram-a2p/2237812/message';
$text = PrichinaDlyaKlienta::perevesti($vnutri);
expect($text)->not->toContain('http')
->and($text)->not->toContain('budget')
->and($text)->not->toContain('URL')
->and($text)->not->toBe($vnutri);
});
it('временную беду называет временной, а не поломкой', function () {
$text = PrichinaDlyaKlienta::perevesti('МТС не пускает этот адрес — отказ 3 раз подряд; если повторится, роботу нужен другой адрес выхода');
expect($text)->toContain('временно');
});
it('про потолок траты говорит клиенту как есть — это ему полезно', function () {
$vnutri = 'Бюджет 1500₽ превышает потолок 1000₽ — боевой запуск запрещён';
expect(PrichinaDlyaKlienta::perevesti($vnutri))->toBe($vnutri);
});
it('в любом переводе нет латиницы — клиент читает по-русски', function () {
$prichiny = [
'Вход в кабинет МТС потерян — нужен вход руками (npm run login)',
'submitWithPayment: кнопка оплаты неактивна',
'Кабинет МТС не открылся — пустая страница после 3 попыток',
'Статус кампании 2237821 не определён в списке',
'что-то совсем новое и незнакомое',
];
foreach ($prichiny as $p) {
expect(PrichinaDlyaKlienta::perevesti($p))->not->toMatch('/[A-Za-z]/');
}
});