seed(RoleSeeder::class); $this->admin = User::factory()->create([ 'role' => User::ROLE_ADMIN, 'status' => User::STATUS_ACTIVE, ]); } public function test_admin_can_list_users_with_filters(): void { Sanctum::actingAs($this->admin); User::factory()->count(3)->create(['role' => User::ROLE_RESIDENT]); User::factory()->count(2)->create(['role' => User::ROLE_DRIVER]); $response = $this->getJson('/api/v1/admin/users?role=resident'); $response->assertOk(); $items = $response->json('data'); $this->assertGreaterThanOrEqual(3, count($items)); foreach ($items as $u) { $this->assertSame('resident', $u['role']); } } public function test_admin_can_search_users_by_name_or_email(): void { Sanctum::actingAs($this->admin); User::factory()->create(['email' => 'unique-find@example.com']); $response = $this->getJson('/api/v1/admin/users?q=unique-find'); $response->assertOk() ->assertJsonFragment(['email' => 'unique-find@example.com']); } public function test_admin_can_show_user_with_profile(): void { Sanctum::actingAs($this->admin); $user = User::factory()->create(['role' => User::ROLE_RESIDENT]); ResidentProfile::create(['user_id' => $user->id, 'occupation' => 'Teacher']); $response = $this->getJson("/api/v1/admin/users/{$user->uuid}"); $response->assertOk() ->assertJsonPath('data.id', $user->uuid) ->assertJsonPath('data.profile.occupation', 'Teacher'); } public function test_admin_can_update_user(): void { Sanctum::actingAs($this->admin); $user = User::factory()->create(); $response = $this->patchJson("/api/v1/admin/users/{$user->uuid}", [ 'first_name' => 'Updated', 'preferred_language' => 'tl', ]); $response->assertOk() ->assertJsonPath('data.first_name', 'Updated') ->assertJsonPath('data.preferred_language', 'tl'); } public function test_admin_can_suspend_and_activate_user(): void { Sanctum::actingAs($this->admin); $user = User::factory()->create(['status' => User::STATUS_ACTIVE]); $this->postJson("/api/v1/admin/users/{$user->uuid}/suspend") ->assertOk() ->assertJsonPath('data.status', User::STATUS_SUSPENDED); $this->postJson("/api/v1/admin/users/{$user->uuid}/activate") ->assertOk() ->assertJsonPath('data.status', User::STATUS_ACTIVE); } public function test_admin_cannot_suspend_other_admin(): void { Sanctum::actingAs($this->admin); $otherAdmin = User::factory()->create(['role' => User::ROLE_ADMIN]); $response = $this->postJson("/api/v1/admin/users/{$otherAdmin->uuid}/suspend"); $response->assertStatus(422); } public function test_admin_can_soft_delete_user(): void { Sanctum::actingAs($this->admin); $user = User::factory()->create(['role' => User::ROLE_RESIDENT]); $response = $this->deleteJson("/api/v1/admin/users/{$user->uuid}"); $response->assertOk(); $this->assertSoftDeleted('users', ['id' => $user->id]); } public function test_admin_can_approve_driver_profile(): void { Sanctum::actingAs($this->admin); $driver = User::factory()->create([ 'role' => User::ROLE_DRIVER, 'status' => User::STATUS_PENDING, ]); DriverProfile::create(['user_id' => $driver->id, 'license_number' => 'D-1234']); $response = $this->postJson("/api/v1/admin/users/{$driver->uuid}/approve-profile"); $response->assertOk() ->assertJsonPath('data.status', User::STATUS_ACTIVE) ->assertJsonPath('data.profile.verification_status', 'approved'); $this->assertDatabaseHas('driver_profiles', [ 'user_id' => $driver->id, 'verification_status' => 'approved', ]); } public function test_admin_can_reject_driver_profile_with_reason(): void { Sanctum::actingAs($this->admin); $driver = User::factory()->create(['role' => User::ROLE_DRIVER]); DriverProfile::create(['user_id' => $driver->id, 'license_number' => 'D-9999']); $response = $this->postJson("/api/v1/admin/users/{$driver->uuid}/reject-profile", [ 'reason' => 'License photo unreadable', ]); $response->assertOk() ->assertJsonPath('data.profile.verification_status', 'rejected') ->assertJsonPath('data.profile.rejection_reason', 'License photo unreadable'); } public function test_resident_blocked_from_admin_users(): void { $resident = User::factory()->create([ 'role' => User::ROLE_RESIDENT, 'status' => User::STATUS_ACTIVE, ]); Sanctum::actingAs($resident); $this->getJson('/api/v1/admin/users')->assertStatus(403); } public function test_unauthed_blocked_from_admin_users(): void { $this->getJson('/api/v1/admin/users')->assertStatus(401); } }