seed(RoleSeeder::class); $this->admin = User::factory()->create(['role' => User::ROLE_ADMIN, 'status' => 'active']); } public function test_bulk_approve_only_approves_eligible_households(): void { Sanctum::actingAs($this->admin); $a = Household::factory()->create(['verification_status' => 'pending', 'proof_of_residency_path' => 'a.jpg']); $b = Household::factory()->create(['verification_status' => 'pending', 'proof_of_residency_path' => null]); $c = Household::factory()->create(['verification_status' => 'approved', 'proof_of_residency_path' => 'c.jpg']); $response = $this->postJson('/api/v1/admin/households/bulk-approve', [ 'household_ids' => [$a->uuid, $b->uuid, $c->uuid], ]); $response->assertOk() ->assertJsonPath('data.approved', 1) ->assertJsonPath('data.rejected', 2); $this->assertSame('approved', $a->fresh()->verification_status); $this->assertSame('pending', $b->fresh()->verification_status); } public function test_bulk_suspend_users_skips_admins(): void { Sanctum::actingAs($this->admin); $resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']); $otherAdmin = User::factory()->create(['role' => User::ROLE_ADMIN, 'status' => 'active']); $response = $this->postJson('/api/v1/admin/bulk/users/suspend', [ 'user_ids' => [$resident->uuid, $otherAdmin->uuid], ]); $response->assertOk()->assertJsonPath('data.suspended', 1); $this->assertSame('suspended', $resident->fresh()->status); $this->assertSame('active', $otherAdmin->fresh()->status); } public function test_bulk_void_qr_codes_with_reason(): void { Sanctum::actingAs($this->admin); $batch = app(BatchGenerator::class)->generate(3, QrCodeBatch::PURPOSE_FREE); $serials = $batch->codes->pluck('serial')->all(); $response = $this->postJson('/api/v1/admin/bulk/qr-codes/void', [ 'serials' => $serials, 'reason' => 'Misprint batch', ]); $response->assertOk()->assertJsonPath('data.voided', 3); $this->assertSame(3, QrCode::where('status', 'voided')->count()); } }