diff --git a/tests/Feature/Api/V1/FullSurface/ApiContentNegotiationAndMediaTypeContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiContentNegotiationAndMediaTypeContractTest.php index d7aca39f..3f984a4e 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiContentNegotiationAndMediaTypeContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiContentNegotiationAndMediaTypeContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiContentNegotiationAndMediaTypeContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function json_accept_header_receives_controlled_api_responses_across_major_domains(): void { $routes = array_slice($this->apiRoutesContainingAny([ @@ -25,7 +26,7 @@ class ApiContentNegotiationAndMediaTypeContractTest extends FullSurfaceE2EContra } } - /** @test */ + #[Test] public function unsupported_accept_headers_do_not_trigger_server_errors(): void { foreach (array_slice($this->apiRoutes(), 0, 60) as $route) { @@ -39,7 +40,7 @@ class ApiContentNegotiationAndMediaTypeContractTest extends FullSurfaceE2EContra } } - /** @test */ + #[Test] public function malformed_content_type_for_mutations_fails_cleanly(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true)), 0, 70); diff --git a/tests/Feature/Api/V1/FullSurface/ApiCrossModuleReferentialWorkflowExpansionTest.php b/tests/Feature/Api/V1/FullSurface/ApiCrossModuleReferentialWorkflowExpansionTest.php index a05e35d3..df5b142b 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiCrossModuleReferentialWorkflowExpansionTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiCrossModuleReferentialWorkflowExpansionTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiCrossModuleReferentialWorkflowExpansionTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function wrong_but_existing_ids_across_modules_do_not_silently_cross_link_records(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true)), 0, 120); diff --git a/tests/Feature/Api/V1/FullSurface/ApiFileMediaMetadataSafetyContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiFileMediaMetadataSafetyContractTest.php index 14fac1fa..aca02d95 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiFileMediaMetadataSafetyContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiFileMediaMetadataSafetyContractTest.php @@ -3,11 +3,12 @@ namespace Tests\Feature\Api\V1\FullSurface; use Illuminate\Http\UploadedFile; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiFileMediaMetadataSafetyContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function upload_routes_reject_misleading_metadata_and_path_names_cleanly(): void { $routes = array_slice($this->apiRoutesContainingAny(['upload', 'import', 'document', 'attachment', 'file', 'photo', 'avatar']), 0, 80); @@ -34,7 +35,7 @@ class ApiFileMediaMetadataSafetyContractTest extends FullSurfaceE2EContractCase } } - /** @test */ + #[Test] public function download_routes_do_not_accept_path_traversal_identifiers(): void { $routes = array_slice($this->apiRoutesContainingAny(['download', 'export', 'file', 'attachment', 'receipt', 'certificate']), 0, 90); diff --git a/tests/Feature/Api/V1/FullSurface/ApiImpersonationDelegationAndActingAsContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiImpersonationDelegationAndActingAsContractTest.php index cda456d4..acb5f5f6 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiImpersonationDelegationAndActingAsContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiImpersonationDelegationAndActingAsContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiImpersonationDelegationAndActingAsContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function impersonation_and_delegation_routes_are_admin_only_and_auditable(): void { $routes = array_slice($this->apiRoutesContainingAny(['impersonate', 'delegate', 'acting-as', 'switch-user', 'assume', 'behalf']), 0, 80); diff --git a/tests/Feature/Api/V1/FullSurface/ApiModelLifecycleInvariantExpansionTest.php b/tests/Feature/Api/V1/FullSurface/ApiModelLifecycleInvariantExpansionTest.php index df36ffe4..542c4241 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiModelLifecycleInvariantExpansionTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiModelLifecycleInvariantExpansionTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiModelLifecycleInvariantExpansionTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function create_update_show_index_lifecycle_routes_remain_controlled_for_core_resources(): void { $resourceFamilies = ['users', 'students', 'classes', 'parents', 'inventory', 'suppliers', 'invoices', 'payments', 'messages']; @@ -25,7 +26,7 @@ class ApiModelLifecycleInvariantExpansionTest extends FullSurfaceE2EContractCase } } - /** @test */ + #[Test] public function identity_fields_are_not_overwritten_by_update_payloads(): void { $routes = array_slice(array_filter($this->apiRoutes(), function ($route): bool { diff --git a/tests/Feature/Api/V1/FullSurface/ApiNestedPayloadAndArrayAbuseContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiNestedPayloadAndArrayAbuseContractTest.php index fefd2335..73d6715b 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiNestedPayloadAndArrayAbuseContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiNestedPayloadAndArrayAbuseContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiNestedPayloadAndArrayAbuseContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function mutation_routes_fail_cleanly_for_deeply_nested_payloads(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true)), 0, 90); @@ -24,7 +25,7 @@ class ApiNestedPayloadAndArrayAbuseContractTest extends FullSurfaceE2EContractCa } } - /** @test */ + #[Test] public function mutation_routes_fail_cleanly_for_large_sparse_arrays(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true)), 0, 90); diff --git a/tests/Feature/Api/V1/FullSurface/ApiNotificationPreferenceAndOptOutContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiNotificationPreferenceAndOptOutContractTest.php index a692390c..522bd62f 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiNotificationPreferenceAndOptOutContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiNotificationPreferenceAndOptOutContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiNotificationPreferenceAndOptOutContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function notification_preference_routes_validate_channels_recipients_and_opt_out_flags(): void { $routes = array_slice($this->apiRoutesContainingAny(['notification', 'notify', 'preferences', 'email', 'whatsapp', 'sms']), 0, 90); @@ -34,7 +35,7 @@ class ApiNotificationPreferenceAndOptOutContractTest extends FullSurfaceE2EContr } } - /** @test */ + #[Test] public function low_privilege_users_cannot_broadcast_notifications_to_everyone(): void { $routes = $this->apiRoutesContainingAny(['broadcast', 'announcement', 'notify', 'notifications']); diff --git a/tests/Feature/Api/V1/FullSurface/ApiOpenApiDocumentationDriftContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiOpenApiDocumentationDriftContractTest.php index f2f89271..3124986c 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiOpenApiDocumentationDriftContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiOpenApiDocumentationDriftContractTest.php @@ -3,11 +3,12 @@ namespace Tests\Feature\Api\V1\FullSurface; use Illuminate\Support\Facades\Route; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiOpenApiDocumentationDriftContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function api_surface_has_documentation_entry_points_and_route_inventory_remains_machine_readable(): void { $documentationRoutes = $this->apiRoutesContainingAny(['docs', 'documentation', 'openapi', 'swagger']); @@ -28,7 +29,7 @@ class ApiOpenApiDocumentationDriftContractTest extends FullSurfaceE2EContractCas } } - /** @test */ + #[Test] public function named_api_routes_use_stable_names_when_names_exist(): void { foreach ($this->apiRoutes() as $route) { @@ -44,7 +45,7 @@ class ApiOpenApiDocumentationDriftContractTest extends FullSurfaceE2EContractCas } } - /** @test */ + #[Test] public function documented_routes_do_not_point_to_missing_actions(): void { foreach (Route::getRoutes()->getRoutes() as $route) { diff --git a/tests/Feature/Api/V1/FullSurface/ApiPolicyAuthorizationDiscoveryContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiPolicyAuthorizationDiscoveryContractTest.php index 20d54283..0bc9b872 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiPolicyAuthorizationDiscoveryContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiPolicyAuthorizationDiscoveryContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiPolicyAuthorizationDiscoveryContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function protected_mutation_routes_are_not_publicly_mutable(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH', 'DELETE'], true)), 0, 140); @@ -24,7 +25,7 @@ class ApiPolicyAuthorizationDiscoveryContractTest extends FullSurfaceE2EContract } } - /** @test */ + #[Test] public function permission_like_routes_reject_wildcards_from_non_admins(): void { $routes = $this->apiRoutesContainingAny(['permission', 'role', 'access', 'acl', 'authorization']); diff --git a/tests/Feature/Api/V1/FullSurface/ApiPublicPrivateCacheSeparationContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiPublicPrivateCacheSeparationContractTest.php index da4420bc..6f1c4fe1 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiPublicPrivateCacheSeparationContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiPublicPrivateCacheSeparationContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiPublicPrivateCacheSeparationContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function authenticated_private_routes_do_not_emit_public_cache_headers(): void { $privateRoutes = array_slice($this->apiRoutesContainingAny([ @@ -29,7 +30,7 @@ class ApiPublicPrivateCacheSeparationContractTest extends FullSurfaceE2EContract } } - /** @test */ + #[Test] public function conditional_cache_headers_do_not_bypass_authorization(): void { $routes = array_slice($this->apiRoutesContainingAny(['users', 'students', 'finance', 'attendance', 'dashboard', 'reports']), 0, 70); diff --git a/tests/Feature/Api/V1/FullSurface/ApiReportConsistencyAndAggregationExpansionTest.php b/tests/Feature/Api/V1/FullSurface/ApiReportConsistencyAndAggregationExpansionTest.php index ad91f925..7a9cd8d7 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiReportConsistencyAndAggregationExpansionTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiReportConsistencyAndAggregationExpansionTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiReportConsistencyAndAggregationExpansionTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function report_routes_handle_date_window_filter_and_group_by_combinations(): void { $routes = array_slice($this->apiRoutesContainingAny(['report', 'dashboard', 'summary', 'analytics', 'statistics']), 0, 100); @@ -32,7 +33,7 @@ class ApiReportConsistencyAndAggregationExpansionTest extends FullSurfaceE2ECont } } - /** @test */ + #[Test] public function parent_and_teacher_report_access_is_scoped_not_global(): void { $routes = $this->apiRoutesContainingAny(['report', 'dashboard', 'summary', 'analytics']); diff --git a/tests/Feature/Api/V1/FullSurface/ApiSoftDeleteRestoreArchiveLifecycleContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiSoftDeleteRestoreArchiveLifecycleContractTest.php index b7be62b9..35e8596b 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiSoftDeleteRestoreArchiveLifecycleContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiSoftDeleteRestoreArchiveLifecycleContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiSoftDeleteRestoreArchiveLifecycleContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function archive_restore_and_unarchive_routes_are_controlled_and_role_protected(): void { $routes = $this->apiRoutesContainingAny(['archive', 'restore', 'unarchive', 'recover']); @@ -23,7 +24,7 @@ class ApiSoftDeleteRestoreArchiveLifecycleContractTest extends FullSurfaceE2ECon } } - /** @test */ + #[Test] public function destructive_soft_delete_style_routes_tolerate_repeated_requests(): void { $routes = array_slice($this->apiRoutesContainingAny(['delete', 'destroy', 'archive', 'cancel', 'void', 'remove']), 0, 80); diff --git a/tests/Feature/Api/V1/FullSurface/ApiSortingFieldSelectionAndIncludeContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiSortingFieldSelectionAndIncludeContractTest.php index 6521a41f..6bc5f6c0 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiSortingFieldSelectionAndIncludeContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiSortingFieldSelectionAndIncludeContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiSortingFieldSelectionAndIncludeContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function list_routes_handle_sort_fields_includes_and_sparse_fieldsets(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => $this->primaryMethod($route) === 'GET'), 0, 120); diff --git a/tests/Feature/Api/V1/FullSurface/ApiTimezoneCalendarRecurrenceDepthContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiTimezoneCalendarRecurrenceDepthContractTest.php index b4b2a39c..6ebd0b13 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiTimezoneCalendarRecurrenceDepthContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiTimezoneCalendarRecurrenceDepthContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiTimezoneCalendarRecurrenceDepthContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function calendar_and_schedule_routes_reject_ambiguous_recurrence_and_timezone_inputs_cleanly(): void { $routes = array_slice($this->apiRoutesContainingAny(['calendar', 'schedule', 'event', 'school-year', 'semester']), 0, 80); diff --git a/tests/Feature/Api/V1/FullSurface/ApiWebhookReplayAndSignatureDepthContractTest.php b/tests/Feature/Api/V1/FullSurface/ApiWebhookReplayAndSignatureDepthContractTest.php index 0b9cc9f9..03d96823 100644 --- a/tests/Feature/Api/V1/FullSurface/ApiWebhookReplayAndSignatureDepthContractTest.php +++ b/tests/Feature/Api/V1/FullSurface/ApiWebhookReplayAndSignatureDepthContractTest.php @@ -2,11 +2,12 @@ namespace Tests\Feature\Api\V1\FullSurface; +use PHPUnit\Framework\Attributes\Test; use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase; class ApiWebhookReplayAndSignatureDepthContractTest extends FullSurfaceE2EContractCase { - /** @test */ + #[Test] public function external_callback_routes_reject_missing_bad_and_replayed_signatures_cleanly(): void { $routes = array_slice($this->apiRoutesContainingAny(['webhook', 'callback', 'paypal', 'stripe', 'provider', 'payment-notification']), 0, 80);