add api tests
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Routing\Route as LaravelRoute;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Tests\Concerns\CreatesApiTestUsers;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ApiAuthenticationAndAuthorizationTest extends TestCase
|
||||
{
|
||||
use CreatesApiTestUsers;
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_auth_me_requires_authentication(): void
|
||||
{
|
||||
$this->getJson('/api/v1/auth/me')->assertUnauthorized();
|
||||
}
|
||||
|
||||
public function test_auth_me_returns_the_current_authenticated_user(): void
|
||||
{
|
||||
$user = $this->createApiUserWithRole('teacher', [
|
||||
'firstname' => 'Teacher',
|
||||
'lastname' => 'Tester',
|
||||
'email' => 'teacher.me@example.test',
|
||||
]);
|
||||
|
||||
$this->actingAs($user, 'api')
|
||||
->getJson('/api/v1/auth/me')
|
||||
->assertOk()
|
||||
->assertJsonPath('status', true)
|
||||
->assertJsonPath('data.email', 'teacher.me@example.test');
|
||||
}
|
||||
|
||||
public function test_admin_only_routes_reject_non_admin_users(): void
|
||||
{
|
||||
$parent = $this->createApiUserWithRole('parent');
|
||||
$this->actingAs($parent, 'api');
|
||||
|
||||
foreach ($this->adminOnlyEndpoints() as [$method, $uri]) {
|
||||
$response = $this->json($method, $uri);
|
||||
|
||||
$this->assertContains(
|
||||
$response->getStatusCode(),
|
||||
[401, 403],
|
||||
"$method $uri should reject a non-admin user; got {$response->getStatusCode()}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_protected_api_routes_reject_anonymous_requests_before_business_logic(): void
|
||||
{
|
||||
$failures = [];
|
||||
|
||||
foreach ($this->sampleProtectedRoutes() as $route) {
|
||||
$method = $this->primaryMethod($route);
|
||||
$uri = '/' . $this->uriWithPlaceholders($route->uri());
|
||||
|
||||
$response = $this->json($method, $uri);
|
||||
$status = $response->getStatusCode();
|
||||
|
||||
if (! in_array($status, [401, 403, 404, 405, 419, 422], true)) {
|
||||
$failures[] = "$method $uri returned $status";
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame([], $failures, "Anonymous requests reached unexpected responses:\n" . implode("\n", $failures));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{0: string, 1: string}>
|
||||
*/
|
||||
private function adminOnlyEndpoints(): array
|
||||
{
|
||||
return [
|
||||
['GET', '/api/v1/users'],
|
||||
['POST', '/api/v1/users'],
|
||||
['GET', '/api/v1/administrator/dashboard/metrics'],
|
||||
['GET', '/api/v1/administrator/staff'],
|
||||
['GET', '/api/v1/school-years'],
|
||||
['GET', '/api/v1/administrator/role-permission/roles'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<LaravelRoute>
|
||||
*/
|
||||
private function sampleProtectedRoutes(): array
|
||||
{
|
||||
return collect(Route::getRoutes()->getRoutes())
|
||||
->filter(fn (LaravelRoute $route): bool => str_starts_with($route->uri(), 'api/'))
|
||||
->filter(function (LaravelRoute $route): bool {
|
||||
return collect($route->gatherMiddleware())->contains(function (string $middleware): bool {
|
||||
return str_contains($middleware, 'auth:api') || str_contains($middleware, 'jwt.auth');
|
||||
});
|
||||
})
|
||||
->reject(function (LaravelRoute $route): bool {
|
||||
$uri = $route->uri();
|
||||
|
||||
return str_contains($uri, 'files/')
|
||||
|| str_contains($uri, 'receipts/')
|
||||
|| str_contains($uri, 'reimbursements/')
|
||||
|| str_contains($uri, 'attachments/');
|
||||
})
|
||||
->take(80)
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function primaryMethod(LaravelRoute $route): string
|
||||
{
|
||||
foreach ($route->methods() as $method) {
|
||||
if (! in_array($method, ['HEAD', 'OPTIONS'], true)) {
|
||||
return $method;
|
||||
}
|
||||
}
|
||||
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
private function uriWithPlaceholders(string $uri): string
|
||||
{
|
||||
return preg_replace('/\{[^}]+\}/', '1', $uri) ?? $uri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user