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, ]); KnowledgeChunk::create([ 'source_path' => 'help/p.md', 'title' => 'Что такое проект', 'tour' => 'create-project', 'topics' => 'создать проект', 'chunk_index' => 0, 'content' => 'Проект — это заявка на поток клиентов.', ]); }); it('стоп-тема (мой баланс) → эскалация без похода в LLM', function () { Http::fake(); $answer = app(BotAnswerService::class)->answer('какой у меня баланс?'); expect($answer->escalate)->toBeTrue() ->and($answer->text)->toContain('специалисту'); Http::assertNothingSent(); }); it('просьба позвать человека → эскалация', function () { Http::fake(); expect(app(BotAnswerService::class)->answer('позовите оператора')->escalate)->toBeTrue(); }); it('вопрос не по базе (пустой поиск) → честное «не знаю» + эскалация', function () { Http::fake(); $answer = app(BotAnswerService::class)->answer('какая погода в москве'); expect($answer->escalate)->toBeTrue(); Http::assertNothingSent(); }); it('обычный вопрос → ответ LLM по контексту, без эскалации', function () { Http::fake([ 'llm.api.cloud.yandex.net/*' => Http::response([ 'result' => ['alternatives' => [['message' => ['role' => 'assistant', 'text' => 'Проект — это заявка на поток клиентов.']]]], ]), ]); $answer = app(BotAnswerService::class)->answer('что такое проект?'); expect($answer->escalate)->toBeFalse() ->and($answer->text)->toContain('Проект') ->and($answer->matchedChunkIds)->not->toBeEmpty(); }); it('tour-ссылка добавляется только при включённом tours_enabled', function () { config()->set('services.jivo_bot.tours_enabled', true); config()->set('app.url', 'https://liderra.ru'); Http::fake([ 'llm.api.cloud.yandex.net/*' => Http::response([ 'result' => ['alternatives' => [['message' => ['role' => 'assistant', 'text' => 'Проект — это…']]]], ]), ]); $withTours = app(BotAnswerService::class)->answer('что такое проект?'); expect($withTours->text)->toContain('https://liderra.ru/?tour=create-project'); config()->set('services.jivo_bot.tours_enabled', false); $without = app(BotAnswerService::class)->answer('что такое проект?'); expect($without->text)->not->toContain('?tour='); }); it('LLM недоступен → эскалация', function () { Http::fake(['llm.api.cloud.yandex.net/*' => Http::response('err', 500)]); expect(app(BotAnswerService::class)->answer('что такое проект?')->escalate)->toBeTrue(); });