createAppointmentActors(); $response = $this->actingAs($admin)->postJson(route('chat.appoint.appoint'), [ 'username' => $target->username, 'position_id' => $position->id, 'remark' => '聊天室快速任命', 'room_id' => $room->id, ]); $response->assertOk()->assertJson([ 'status' => 'success', 'message' => "已成功将【{$target->username}】任命为【{$position->name}】。", ]); $privateMessage = $this->findPrivateSystemMessage($room->id, $target->username, '已任命你为'); $this->assertNotNull($privateMessage); $this->assertSame('✨ 职务任命通知', $privateMessage['toast_notification']['title'] ?? null); $this->assertSame('✨', $privateMessage['toast_notification']['icon'] ?? null); $this->assertSame('#a855f7', $privateMessage['toast_notification']['color'] ?? null); Queue::assertPushed(SaveMessageJob::class, 1); } /** * 测试撤销职务后会给目标用户写入带 toast 的私聊提示。 */ public function test_revoke_pushes_private_toast_notification_to_target(): void { Queue::fake(); [$admin, $target, $room, $position] = $this->createAppointmentActors(); UserPosition::create([ 'user_id' => $target->id, 'position_id' => $position->id, 'appointed_by_user_id' => $admin->id, 'appointed_at' => now()->subDay(), 'remark' => '已有职务', 'is_active' => true, ]); $target->update(['user_level' => $position->level]); $response = $this->actingAs($admin)->postJson(route('chat.appoint.revoke'), [ 'username' => $target->username, 'remark' => '聊天室快速撤销', 'room_id' => $room->id, ]); $response->assertOk()->assertJson([ 'status' => 'success', ]); $privateMessage = $this->findPrivateSystemMessage($room->id, $target->username, '已撤销你的'); $this->assertNotNull($privateMessage); $this->assertSame('📋 职务变动通知', $privateMessage['toast_notification']['title'] ?? null); $this->assertSame('📋', $privateMessage['toast_notification']['icon'] ?? null); $this->assertSame('#6b7280', $privateMessage['toast_notification']['color'] ?? null); Queue::assertPushed(SaveMessageJob::class, 1); } /** * 创建任命测试共用的操作者、目标用户、房间与职务。 * * @return array{0: User, 1: User, 2: Room, 3: Position} */ private function createAppointmentActors(): array { $admin = User::factory()->create([ 'id' => 1, 'user_level' => 100, ]); $target = User::factory()->create([ 'user_level' => 1, ]); $room = Room::create([ 'room_name' => '职务操作房', ]); $department = Department::create([ 'name' => '办公厅', 'rank' => 90, ]); $position = Position::create([ 'department_id' => $department->id, 'name' => '巡查员', 'icon' => '✨', 'rank' => 50, 'level' => 20, ]); return [$admin, $target, $room, $position]; } /** * 从房间消息缓存中定位目标用户收到的系统私聊提示。 * * @return array|null */ private function findPrivateSystemMessage(int $roomId, string $targetUsername, string $needle): ?array { $messages = Redis::lrange("room:{$roomId}:messages", 0, -1); return collect($messages) ->map(fn (string $item) => json_decode($item, true)) ->first(fn (array $item) => ($item['from_user'] ?? null) === '系统' && ($item['to_user'] ?? null) === $targetUsername && str_contains((string) ($item['content'] ?? ''), $needle)); } }