Files
portal/app/tests/Feature/Bot/ChatToursTest.php
T

114 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\KnowledgeChunk;
use App\Services\Bot\BotAnswerService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
uses(RefreshDatabase::class);
/**
* Экскурсии «Показать на портале» 13.07.2026 были ВЫКЛЮЧЕНЫ: ссылки уходили не по теме
* вопроса (совпадало одно случайное слово — бот приписывал экскурсию по уведомлениям
* к реплике «первое сообщение подряд»). Правило переписано, экскурсии включены обратно.
*
* Теперь их держат два условия, и оба обязательны:
* 1. Вопрос по теме статьи (KnowledgeSearch::isOnTopic — тесты в ToursRelevanceTest).
* 2. Клиент пишет ИЗ КАБИНЕТА. Гостю с лендинга ссылка внутрь кабинета бесполезна:
* он там ещё не зарегистрирован, и показывать ему нечего.
*
* Гостю вместо экскурсии в кабинет даём ссылку на ПОШАГОВЫЙ РАЗБОР (кадры со стрелками)
* на странице «Как это работает» (задача 2026-07-13). Раньше связь шла через карту
* BotAnswerService::LANDING_SHOWS (имя экскурсии → якорь, всего 4 темы) — она выброшена:
* разборов стало 20, и их якорь = СЛАГ СТАТЬИ (source_path без ".md"). Список слагов,
* у которых разбор реально существует, — config/guides.php.
*
* Этот сторож не даёт незаметно вернуть ссылки гостям без разбора и не даёт незаметно
* заменить кабинетную экскурсию вошедшего клиента на ссылку на лендинг.
*/
beforeEach(function () {
config()->set('services.bot.tours_enabled', true);
config()->set('app.url', 'https://lk.liderra.ru');
config()->set('services.yandexgpt', [
'api_key' => 'k', 'folder_id' => 'f', 'model' => 'yandexgpt-lite/latest',
'endpoint' => 'https://llm.api.cloud.yandex.net/foundationModels/v1/completion',
'timeout_seconds' => 8,
]);
Http::fake([
'llm.api.cloud.yandex.net/*' => Http::response([
'result' => ['alternatives' => [['message' => ['role' => 'assistant', 'text' => 'Проект создаётся в разделе «Проекты».']]]],
]),
]);
KnowledgeChunk::create([
'source_path' => 'sozdat-proekt.md', 'title' => 'Как создать проект', 'tour' => 'create-project',
'topics' => 'создать проект, новый проект', 'chunk_index' => 0,
'content' => 'Проект создаётся в разделе «Проекты», кнопка «Создать».',
]);
});
it('клиенту из кабинета экскурсия по теме предлагается', function () {
$answer = app(BotAnswerService::class)->answer('как создать проект?', [], fromPortal: true);
expect($answer->text)->toContain('https://lk.liderra.ru/?tour=create-project');
});
it('гостю с лендинга экскурсию не предлагаем — ему нечего показывать в кабинете', function () {
$answer = app(BotAnswerService::class)->answer('как создать проект?', [], fromPortal: false);
expect($answer->text)->not->toContain('?tour=');
});
it('гостю даёт ссылку на разбор по слагу статьи', function () {
config()->set('guides.slugs', ['sozdat-proekt']);
config()->set('services.bot.landing_url', 'https://liderra.ru');
$answer = app(BotAnswerService::class)->answer('как создать проект?', [], fromPortal: false);
expect($answer->text)->toContain('https://liderra.ru/kak-eto-rabotaet#sozdat-proekt');
expect($answer->text)->not->toContain('Показать на портале');
});
it('молчит, если разбора для статьи нет', function () {
config()->set('guides.slugs', ['sozdat-proekt']);
KnowledgeChunk::create([
'source_path' => 'podderzhka.md', 'title' => 'Как связаться с поддержкой', 'tour' => 'support',
'topics' => 'поддержка, связаться, написать в поддержку',
'chunk_index' => 0,
'content' => 'Поддержка отвечает в чате и на support@liderra.ru.',
]);
Http::fake([
'llm.api.cloud.yandex.net/*' => Http::response([
'result' => ['alternatives' => [['message' => ['role' => 'assistant', 'text' => 'Напишите в чат или на support@liderra.ru.']]]],
]),
]);
$answer = app(BotAnswerService::class)->answer('как связаться с поддержкой?', [], fromPortal: false);
expect($answer->text)->not->toContain('kak-eto-rabotaet');
expect($answer->text)->not->toContain('?tour=');
});
it('вошедшему по-прежнему даёт экскурсию в кабинет, а не ссылку на лендинг', function () {
config()->set('guides.slugs', ['sozdat-proekt']);
config()->set('services.bot.landing_url', 'https://liderra.ru');
$answer = app(BotAnswerService::class)->answer('как создать проект?', [], fromPortal: true);
expect($answer->text)->toContain('Показать на портале');
expect($answer->text)->not->toContain('kak-eto-rabotaet');
});
it('на приветствие («привет») ссылок нет никому', function () {
config()->set('guides.slugs', ['sozdat-proekt']);
config()->set('services.bot.landing_url', 'https://liderra.ru');
$guest = app(BotAnswerService::class)->answer('привет', [], fromPortal: false);
$client = app(BotAnswerService::class)->answer('привет', [], fromPortal: true);
expect($guest->text)->not->toContain('kak-eto-rabotaet');
expect($client->text)->not->toContain('Показать на портале');
});