Files
alrahma_sunday_school_api/tests/Feature/Api/V1/FullSurface/ApiDeepDocumentationAndRouteParityContractTest.php
T
2026-06-08 23:45:55 -04:00

77 lines
2.8 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\FullSurface;
use Illuminate\Routing\Route as LaravelRoute;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;
class ApiDeepDocumentationAndRouteParityContractTest extends FullSurfaceE2EContractCase
{
public function test_every_named_api_route_has_a_stable_route_name_or_explicit_public_exception(): void
{
$unnamed = [];
foreach ($this->apiRoutes() as $route) {
$uri = $route->uri();
if ($route->getName() !== null) {
continue;
}
if ($this->isAllowedUnnamedRoute($uri)) {
continue;
}
$unnamed[] = $this->primaryMethod($route) . ' ' . $uri;
}
$this->assertSame([], $unnamed, "API routes should be nameable for docs, client generation, and redirects. Unnamed routes:\n" . implode("\n", $unnamed));
}
public function test_openapi_or_docs_catalog_endpoint_is_reachable_and_route_table_remains_documentable(): void
{
$docsChecks = [
['GET', '/api/documentation'],
['GET', '/api/documentation/swagger'],
['GET', '/api/documentation/swagger.json'],
['GET', '/api/docs/public'],
];
$failures = [];
foreach ($docsChecks as [$method, $uri]) {
$response = $this->requestAs($this->admin, $method, $uri);
if ($response->getStatusCode() >= 500) {
$failures[] = "$method $uri docs endpoint crashed: " . $response->getContent();
}
}
$this->assertSame([], $failures, "Documentation endpoints must not be decorative rubble:\n" . implode("\n", $failures));
}
public function test_route_use_case_catalog_covers_new_deep_contract_domains(): void
{
$coverageNeedles = [
'import' => ['upload', 'import', 'attachment', 'document'],
'export' => ['download', 'export', 'pdf', 'print'],
'pagination' => ['students', 'users', 'invoices', 'inventory', 'messages'],
'state_transition' => ['close', 'reopen', 'approve', 'archive', 'resolve', 'lock', 'unlock'],
'identity' => ['auth', 'login', 'logout', 'me', 'roles'],
];
foreach ($coverageNeedles as $label => $needles) {
$this->assertNotSame([], $this->apiRoutesContainingAny($needles), "The $label contract bucket should map to at least one route.");
}
}
private function isAllowedUnnamedRoute(string $uri): bool
{
return str_contains($uri, 'api/v1')
|| str_contains($uri, 'login')
|| str_contains($uri, 'register')
|| str_contains($uri, 'proofread')
|| str_contains($uri, 'emails')
|| str_contains($uri, 'compare');
}
}