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

61 lines
2.5 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\FullSurface;
use Illuminate\Support\Facades\Route;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;
class ApiOpenApiDocumentationDriftContractTest extends FullSurfaceE2EContractCase
{
/** @test */
public function api_surface_has_documentation_entry_points_and_route_inventory_remains_machine_readable(): void
{
$documentationRoutes = $this->apiRoutesContainingAny(['docs', 'documentation', 'openapi', 'swagger']);
$this->assertNotEmpty($documentationRoutes, 'The API needs at least one documentation route. Tribal knowledge is not documentation, despite industry folklore.');
foreach ($documentationRoutes as $route) {
$response = $this->probeRoute($route);
$this->assertControlled($response, $this->primaryMethod($route), $route->uri());
}
$apiRoutes = $this->apiRoutes();
$this->assertGreaterThan(25, count($apiRoutes), 'The full-surface suite expects the application API route table to be loaded.');
foreach ($apiRoutes as $route) {
$this->assertNotEmpty($route->uri(), 'Every API route must have a URI. Revolutionary stuff.');
$this->assertNotEmpty($route->methods(), 'Every API route must expose at least one method.');
}
}
/** @test */
public function named_api_routes_use_stable_names_when_names_exist(): void
{
foreach ($this->apiRoutes() as $route) {
$name = $route->getName();
if ($name === null) {
continue;
}
$this->assertStringNotContainsString(' ', $name, "Route name [$name] should not contain spaces.");
$this->assertStringNotContainsString('tmp', strtolower($name), "Route name [$name] looks temporary.");
$this->assertStringNotContainsString('test', strtolower($name), "Route name [$name] looks like test scaffolding leaked into routing.");
}
}
/** @test */
public function documented_routes_do_not_point_to_missing_actions(): void
{
foreach (Route::getRoutes()->getRoutes() as $route) {
if (! str_starts_with($route->uri(), 'api/')) {
continue;
}
$action = $route->getActionName();
$this->assertNotSame('Closure', $action, 'API routes should not depend on anonymous closures because documentation and traceability suffer.');
$this->assertNotEmpty($action, 'API route action must be discoverable.');
}
}
}