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

55 lines
2.1 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\FullSurface;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;
class ApiPublicPrivateCacheSeparationContractTest extends FullSurfaceE2EContractCase
{
/** @test */
public function authenticated_private_routes_do_not_emit_public_cache_headers(): void
{
$privateRoutes = array_slice($this->apiRoutesContainingAny([
'users', 'students', 'parents', 'teacher', 'attendance', 'finance', 'inventory', 'messages', 'dashboard', 'reports',
]), 0, 100);
foreach ($privateRoutes as $route) {
$method = $this->primaryMethod($route);
if ($method !== 'GET') {
continue;
}
$uri = $route->uri();
$response = $this->requestAs($this->actorFor($uri), $method, $uri);
$cacheControl = strtolower((string) $response->headers->get('Cache-Control'));
$this->assertControlled($response, $method, $uri);
$this->assertFalse(str_contains($cacheControl, 'public') && str_contains($cacheControl, 'max-age'), "$method $uri should not mark private API data as publicly cacheable.");
}
}
/** @test */
public function conditional_cache_headers_do_not_bypass_authorization(): void
{
$routes = array_slice($this->apiRoutesContainingAny(['users', 'students', 'finance', 'attendance', 'dashboard', 'reports']), 0, 70);
foreach ($routes as $route) {
$method = $this->primaryMethod($route);
if ($method !== 'GET') {
continue;
}
$uri = $route->uri();
$response = $this->withHeaders([
'If-None-Match' => '"attacker-cache-tag"',
'If-Modified-Since' => 'Wed, 21 Oct 2099 07:28:00 GMT',
])->json('GET', $this->materializePath($uri));
$this->assertStatusIn($response, [200, 204, 302, 304, 401, 403, 404, 405, 409, 419, 422], "conditional unauthenticated GET $uri");
$this->assertNotSame(500, $response->getStatusCode(), "conditional unauthenticated GET $uri should not crash.");
}
}
}