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.'); } } }