'Bearer '.JWTAuth::fromUser($user)]; } public function test_append_messages_sequential_seq_and_last_seq(): void { $service = app(ChatService::class); $session = $service->createSession('Test Session'); $messages = collect(range(1, 20))->map(function ($i) use ($service, $session) { return $service->appendMessage([ 'session_id' => $session->session_id, 'role' => 'USER', 'type' => 'user.prompt', 'content' => 'msg '.$i, ]); }); $seqs = $messages->pluck('seq')->all(); $this->assertEquals(range(1, 20), $seqs); $session->refresh(); $this->assertEquals(20, $session->last_seq); } public function test_dedupe_returns_existing_message(): void { $service = app(ChatService::class); $session = $service->createSession('Test Session'); $first = $service->appendMessage([ 'session_id' => $session->session_id, 'role' => 'USER', 'type' => 'user.prompt', 'content' => 'hello', 'dedupe_key' => 'k1', ]); $second = $service->appendMessage([ 'session_id' => $session->session_id, 'role' => 'USER', 'type' => 'user.prompt', 'content' => 'hello again', 'dedupe_key' => 'k1', ]); $this->assertEquals($first->message_id, $second->message_id); $this->assertEquals($first->seq, $second->seq); $this->assertCount(1, $session->messages()->get()); } public function test_closed_session_blocks_append_except_whitelisted(): void { $service = app(ChatService::class); $session = $service->createSession('Test Session'); $session->update(['status' => ChatSessionStatus::CLOSED]); $this->expectExceptionMessage('Session is closed'); $service->appendMessage([ 'session_id' => $session->session_id, 'role' => 'USER', 'type' => 'user.prompt', 'content' => 'blocked', ]); } public function test_http_append_and_list_messages(): void { $user = User::factory()->create(); $headers = $this->authHeader($user); $createSession = $this->withHeaders($headers)->postJson('/api/sessions', [ 'session_name' => 'API Session', ])->assertCreated(); $sessionId = $createSession->json('session_id'); $append = $this->withHeaders($headers)->postJson("/api/sessions/{$sessionId}/messages", [ 'role' => 'USER', 'type' => 'user.prompt', 'content' => 'hello api', ])->assertCreated(); $this->assertEquals(1, $append->json('data.seq')); $list = $this->withHeaders($headers)->getJson("/api/sessions/{$sessionId}/messages?after_seq=0&limit=10") ->assertOk(); $this->assertEquals(1, $list->json('data.0.seq')); $this->assertEquals('hello api', $list->json('data.0.content')); } }