create(['username' => 'tester', 'email_verified_at' => now()]); } public function test_get_chat_success_maps_messages_and_last_id() { Http::fake([ $this->base() . '/chat*' => Http::response([ 'messages' => [ [ 'id' => 1, 'user_id' => 12, 'username' => 'dolo', 'avatar' => 'http://a/1.png', 'message' => 'hi', 'reply_to_id' => null, 'reactions' => ['🔥' => 2, '😂' => 1], 'created_at' => now()->toIso8601String(), ], [ 'id' => 2, 'user_id' => 13, 'username' => 'sara', 'avatar' => null, 'message' => 'yo', 'reply_to_id' => 1, 'reactions' => [], 'created_at' => now()->toIso8601String(), ], ], ], 200), ]); $res = $this->actingAs($this->actingUser(), 'web') ->get('/api/chat?limit=2'); $res->assertStatus(200) ->assertJsonStructure([ 'data' => [ ['id', 'user_id', 'message', 'reply_to_id', 'created_at', 'user' => ['id', 'username', 'avatar_url'], 'reactions_agg'], ], 'last_id', ]); $json = $res->json(); $this->assertEquals(2, $json['last_id']); $this->assertCount(2, $json['data']); $this->assertEquals('dolo', $json['data'][0]['user']['username']); } public function test_get_chat_client_error_is_mapped() { Http::fake([ $this->base() . '/chat*' => Http::response(['message' => 'Invalid request'], 422), ]); $res = $this->actingAs($this->actingUser(), 'web') ->get('/api/chat?limit=0'); $res->assertStatus(422) ->assertJson([ 'error' => 'client_error', 'message' => 'Invalid request', ]); } public function test_get_chat_server_error_maps_to_503() { Http::fake([ $this->base() . '/chat*' => Http::response(['message' => 'Upstream failed'], 500), ]); $res = $this->actingAs($this->actingUser(), 'web') ->get('/api/chat?limit=50'); $res->assertStatus(503) ->assertJson([ 'error' => 'service_unavailable', ]); } public function test_get_chat_timeout_maps_to_502() { Http::fake(function () { throw new \Illuminate\Http\Client\ConnectionException('timeout'); }); $res = $this->actingAs($this->actingUser(), 'web') ->get('/api/chat?limit=50'); $res->assertStatus(502) ->assertJson([ 'error' => 'bad_gateway', ]); } public function test_post_chat_success_returns_minimal_message() { Http::fake([ $this->base() . '/chat' => Http::response(['success' => true, 'message_id' => 123], 200), ]); $res = $this->actingAs($this->actingUser(), 'web') ->postJson('/api/chat', [ 'message' => 'Hello world', ]); $res->assertStatus(201) ->assertJsonStructure(['data' => ['id', 'user_id', 'message', 'created_at', 'user' => ['id', 'username', 'avatar_url'], 'reactions_agg']]); $this->assertEquals(123, data_get($res->json(), 'data.id')); $this->assertEquals('Hello world', data_get($res->json(), 'data.message')); } public function test_post_chat_client_error_is_mapped() { Http::fake([ $this->base() . '/chat' => Http::response(['message' => 'Too long'], 422), ]); $res = $this->actingAs($this->actingUser(), 'web') ->postJson('/api/chat', [ 'message' => str_repeat('x', 400), ]); $res->assertStatus(422) ->assertJson([ 'error' => 'client_error', 'message' => 'Too long', ]); } public function test_react_success_returns_200() { Http::fake([ $this->base() . '/chat/55/react' => Http::response(['ok' => true], 200), ]); $res = $this->actingAs($this->actingUser(), 'web') ->postJson('/api/chat/55/react', [ 'emoji' => '🔥' ]); $res->assertStatus(200) ->assertJson([ 'data' => null, ]); } }