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); }); it('отдаёт ответ бота, появившийся после сообщения клиента', function () { $chat = str_repeat('c', 32); $in = BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => 'привет', 'created_at' => now()]); $out = BotDialog::create(['chat_id' => $chat, 'direction' => 'out', 'message' => 'Здравствуйте!', 'created_at' => now()]); $response = $this->getJson("/api/chat/{$chat}/messages?after={$in->id}"); $response->assertOk(); expect($response->json('messages'))->toHaveCount(1) ->and($response->json('messages.0.direction'))->toBe('out') ->and($response->json('messages.0.text'))->toBe('Здравствуйте!') ->and($response->json('messages.0.id'))->toBe((int) $out->id); }); it('отдаёт всю переписку разговора, когда окошко открыли заново', function () { $chat = str_repeat('d', 32); BotDialog::create(['chat_id' => $chat, 'direction' => 'in', 'message' => 'вопрос', 'created_at' => now()]); BotDialog::create(['chat_id' => $chat, 'direction' => 'out', 'message' => 'ответ', 'created_at' => now()]); $response = $this->getJson("/api/chat/{$chat}/messages?after=0"); expect($response->json('messages'))->toHaveCount(2); }); it('не отдаёт чужой разговор', function () { $mine = str_repeat('e', 32); BotDialog::create(['chat_id' => str_repeat('f', 32), 'direction' => 'out', 'message' => 'чужое', 'created_at' => now()]); expect($this->getJson("/api/chat/{$mine}/messages?after=0")->json('messages'))->toBe([]); }); it('вежливо отказывает, когда клиент строчит слишком быстро', function () { Queue::fake(); $chat = str_repeat('7', 32); $this->postJson('/api/chat/message', ['chat_id' => $chat, 'text' => 'раз'])->assertOk(); $second = $this->postJson('/api/chat/message', ['chat_id' => $chat, 'text' => 'два']); $second->assertStatus(429); expect($second->json('message'))->toContain('подождите'); // Деньги не тратим: второй вопрос в очередь не попал. Queue::assertPushed(ProcessChatMessageJob::class, 1); });