77 lines
2.8 KiB
PHP
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');
|
|
}
|
|
}
|