cfd26e38ef
Заменяет JivoBotController+JivoBotClient на ChatController (POST /api/chat/message) и ProcessJivoMessageJob на ProcessChatMessageJob. Реплику клиента теперь пишет контроллер и возвращает её номер (message_id); джоба получает этот номер и берёт историю строго до него, не отправляя ответ во внешний Jivo — он ложится в bot_dialogs, откуда его заберёт своё окошко (Задача 3). Мозг бота не менялся. Спека: docs/superpowers/specs/2026-07-13-own-chat-widget-design.md §5
47 lines
1.5 KiB
PHP
47 lines
1.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Jobs\Bot\ProcessChatMessageJob;
|
|
use App\Models\BotDialog;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Queue;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('принимает сообщение клиента, пишет его в журнал и ставит ответ в очередь', function () {
|
|
Queue::fake();
|
|
$chat = str_repeat('a', 32);
|
|
|
|
$response = $this->postJson('/api/chat/message', [
|
|
'chat_id' => $chat,
|
|
'text' => 'сколько стоит заявка?',
|
|
]);
|
|
|
|
$response->assertOk();
|
|
$id = $response->json('message_id');
|
|
expect($id)->toBeInt();
|
|
|
|
$row = BotDialog::query()->find($id);
|
|
expect($row->chat_id)->toBe($chat)
|
|
->and($row->direction)->toBe('in')
|
|
->and($row->message)->toBe('сколько стоит заявка?')
|
|
->and($row->source)->toBe('landing'); // гость → лендинг
|
|
|
|
Queue::assertPushed(ProcessChatMessageJob::class);
|
|
});
|
|
|
|
it('не принимает слишком длинное сообщение', function () {
|
|
$this->postJson('/api/chat/message', [
|
|
'chat_id' => str_repeat('b', 32),
|
|
'text' => str_repeat('я', 1001),
|
|
])->assertStatus(422);
|
|
});
|
|
|
|
it('не принимает кривой номер разговора', function () {
|
|
$this->postJson('/api/chat/message', [
|
|
'chat_id' => 'не-номер',
|
|
'text' => 'привет',
|
|
])->assertStatus(422);
|
|
});
|