fix(bot): сторож ловит жёсткий отказ в замене в любой форме (живой баг 13.07)
This commit is contained in:
@@ -184,3 +184,181 @@ it('без карточки: число ИЗ статьи (обычная, не
|
||||
|
||||
expect($out)->toContain('300');
|
||||
});
|
||||
|
||||
/**
|
||||
* 🔴 ЖИВОЙ БАГ 13.07.2026: правило владельца — ЗАМЕНЫ ЗАЯВКИ НЕТ (недозвон не брак), но
|
||||
* бот не должен РУБИТЬ ДВЕРЬЮ («не полагается», «не вернём»). Старое правило BANNED
|
||||
* (строка ~74) знало только форму ЕДИНСТВЕННОГО числа «не полагается» — «не полагаются»
|
||||
* (множественное) прошло мимо на живом прогоне. Урок проекта: правила по СПИСКУ
|
||||
* ФОРМУЛИРОВОК проигрывают гонку — нужно правило ПО СМЫСЛУ (как promisesReplacement и
|
||||
* соседи), а не очередная строка в BANNED.
|
||||
*/
|
||||
it('🔴 ЖИВОЙ БАГ: «Замены за недозвоны не полагаются» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Замены за недозвоны не полагаются — это нормальная часть работы.',
|
||||
'Недозвон — обычная часть работы с контактами.'
|
||||
);
|
||||
|
||||
expect($out)->not->toContain('не полагаются');
|
||||
});
|
||||
|
||||
it('старая форма «Замена не полагается» — тоже рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean('Замена не полагается.', 'Недозвон — обычная часть работы.');
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Возврат денег за недозвон не предусмотрен» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Возврат денег за недозвон не предусмотрен.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Компенсации за такие заявки мы не делаем» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Компенсации за такие заявки мы не делаем.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Деньги за недозвоны не возвращаются» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Деньги за недозвоны не возвращаются.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Заменить заявку нельзя, возврата нет» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Заменить заявку нельзя, возврата нет.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Мы не меняем и не возвращаем деньги за такие номера» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Мы не меняем и не возвращаем деньги за такие номера.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Такие заявки не подлежат замене» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Такие заявки не подлежат замене.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
it('«Возмещение по недозвонам не положено» — рубка дверью, вырезается', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Возмещение по недозвонам не положено.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toBe('');
|
||||
});
|
||||
|
||||
/**
|
||||
* Честные фразы — сгладить тему, но НЕ рубить дверью. Их резать НЕЛЬЗЯ: без них ответ
|
||||
* потеряет весь смысл и клиент уйдёт с пустым ответом (эскалация «оставьте телефон»).
|
||||
*/
|
||||
it('честное: путь на support@ для спорного случая — НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Спорный случай опишите на support@liderra.ru — специалист разберёт его индивидуально.',
|
||||
'Поддержка работает круглосуточно.'
|
||||
);
|
||||
|
||||
expect($out)->toContain('support@liderra.ru')
|
||||
->and($out)->toContain('специалист разберёт его индивидуально');
|
||||
});
|
||||
|
||||
it('честное: «недозвон — обычная часть работы, попробуйте СМС и повтор» — НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Недозвон — обычная часть работы: попробуйте СМС и повторный звонок позже.',
|
||||
'Недозвон — обычная часть работы.'
|
||||
);
|
||||
|
||||
expect($out)->toContain('попробуйте СМС и повторный звонок позже');
|
||||
});
|
||||
|
||||
it('честное: «из ста номеров обычно отвечают 8–12 человек» — НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Из ста номеров обычно отвечают 8–12 человек.',
|
||||
'Из ста номеров обычно отвечают 8–12 человек.'
|
||||
);
|
||||
|
||||
expect($out)->toContain('Из ста номеров обычно отвечают');
|
||||
});
|
||||
|
||||
it('честное: «если заявка явно не по теме, напишите нам — разберёмся» — НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean(
|
||||
'Если заявка явно не по теме, напишите нам — разберёмся.',
|
||||
'Заявка не по теме — напишите нам.'
|
||||
);
|
||||
|
||||
expect($out)->toContain('напишите нам — разберёмся');
|
||||
});
|
||||
|
||||
/**
|
||||
* Ложные срабатывания: слово «нет» — самое частое слово в русском, встречается в
|
||||
* контекстах, никак не связанных с заменой/возвратом/деньгами. Правило НЕ должно их резать.
|
||||
*/
|
||||
it('ложное срабатывание: «заявок сегодня нет» — про заявки, не про замену/деньги, НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
$out = $guard->clean('Заявок сегодня нет — это нормально, бывают дни потише.', 'Заявок сегодня нет.');
|
||||
|
||||
expect($out)->toContain('Заявок сегодня нет');
|
||||
});
|
||||
|
||||
it('ложное срабатывание: «денег на балансе нет» (не отказ в замене/возврате) — НЕ режется', function () {
|
||||
$guard = new App\Services\Bot\AnswerGuard;
|
||||
|
||||
// Слово «деньг\w*» — триггер моего правила, «нет» — тоже, но смысл предложения не про
|
||||
// отказ в замене/возврате, а про то, что баланс пуст. Правило не должно это резать.
|
||||
$out = $guard->clean(
|
||||
'Денег на балансе нет — пополните счёт, чтобы получать новые заявки.',
|
||||
'Пополнить баланс можно картой или по счёту.'
|
||||
);
|
||||
|
||||
expect($out)->toContain('Денег на балансе нет');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user