getJson('/api/v1/support/tenants'); $response->assertStatus(401); } public function test_support_resources_allow_super_admin_tokens(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); Tenant::factory()->create(); Sanctum::actingAs($user, ['support-admin', 'support:read']); $response = $this->getJson('/api/v1/support/tenants'); $response->assertOk() ->assertJsonStructure(['data', 'meta']); } public function test_support_token_endpoint_issues_bearer_token_and_allows_api_access(): void { $user = User::factory()->create([ 'role' => 'super_admin', 'password' => Hash::make('secret-password'), ]); Tenant::factory()->create(); $response = $this->postJson('/api/v1/support/auth/token', [ 'login' => $user->email, 'password' => 'secret-password', ]); $response->assertOk() ->assertJsonStructure(['token', 'token_type', 'abilities', 'user']); $token = $response->json('token'); $this->assertIsString($token); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/support/tenants') ->assertOk() ->assertJsonStructure(['data', 'meta']); } public function test_support_requests_require_support_admin_ability(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $token = $user->createToken('support-api', ['support:read'])->plainTextToken; $response = $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/support/tenants'); $response->assertStatus(403) ->assertJsonPath('error.code', 'support_forbidden'); } public function test_support_write_requires_write_ability(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $tenant = Tenant::factory()->create(); $token = $user->createToken('support-api', ['support-admin', 'support:read'])->plainTextToken; $response = $this->withHeader('Authorization', 'Bearer '.$token) ->patchJson('/api/v1/support/tenants/'.$tenant->id, [ 'data' => [ 'slug' => 'not-allowed', ], ]); $response->assertStatus(403) ->assertJsonPath('error.code', 'forbidden'); } public function test_support_read_only_resource_rejects_deletes(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $eventType = EventType::factory()->create(); $token = $user->createToken('support-api', ['support-admin', 'support:write'])->plainTextToken; $response = $this->withHeader('Authorization', 'Bearer '.$token) ->deleteJson('/api/v1/support/event-types/'.$eventType->id); $response->assertStatus(403) ->assertJsonPath('error.code', 'support_mutation_not_allowed'); } public function test_expired_support_token_is_rejected(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $token = $user->createToken('support-api', ['support-admin', 'support:read'], now()->subMinute())->plainTextToken; $response = $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/support/tenants'); $response->assertStatus(401); } public function test_support_resource_update_rejects_invalid_fields(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $tenant = Tenant::factory()->create(); Sanctum::actingAs($user, ['support-admin', 'support:write']); $response = $this->patchJson('/api/v1/support/tenants/'.$tenant->id, [ 'data' => [ 'name' => 'Unauthorized', ], ]); $response->assertStatus(422) ->assertJsonPath('error.code', 'support_invalid_fields'); } public function test_support_data_export_create_sets_user_and_dispatches_job(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $tenant = Tenant::factory()->create(); Bus::fake(); Sanctum::actingAs($user, ['support-admin', 'support:ops']); $response = $this->postJson('/api/v1/support/data-exports', [ 'data' => [ 'scope' => 'tenant', 'tenant_id' => $tenant->id, 'include_media' => true, ], ]); $response->assertCreated() ->assertJsonPath('data.status', 'pending') ->assertJsonPath('data.user_id', $user->id) ->assertJsonPath('data.event_id', null); Bus::assertDispatched(\App\Jobs\GenerateDataExport::class); } public function test_support_photo_reject_requires_moderation_notes(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $photo = Photo::factory()->create(); Sanctum::actingAs($user, ['support-admin', 'support:write']); $response = $this->patchJson('/api/v1/support/photos/'.$photo->id, [ 'data' => [ 'status' => 'rejected', ], ]); $response->assertStatus(422) ->assertJsonValidationErrors(['moderation_notes']); } public function test_support_blog_post_create_requires_title_and_content(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $category = BlogCategory::create([ 'slug' => 'news', 'name' => ['de' => 'News', 'en' => 'News'], 'is_visible' => true, ]); Sanctum::actingAs($user, ['support-admin', 'support:content']); $response = $this->postJson('/api/v1/support/blog-posts', [ 'data' => [ 'blog_category_id' => $category->id, 'slug' => 'missing-title', 'is_published' => false, ], ]); $response->assertStatus(422) ->assertJsonValidationErrors(['title', 'content']); } public function test_support_update_logs_audit_entry(): void { $user = User::factory()->create([ 'role' => 'super_admin', ]); $tenant = Tenant::factory()->create(); Sanctum::actingAs($user, ['support-admin', 'support:write']); $response = $this->patchJson('/api/v1/support/tenants/'.$tenant->id, [ 'data' => [ 'slug' => 'support-updated', ], ]); $response->assertOk(); $this->assertTrue(SuperAdminActionLog::query()->where('action', 'tenants.updated')->exists()); } }