Attainly/backend/tests/Feature/Auth/AuthMiddlewareTest.php

119 lines
3.3 KiB
PHP

<?php
namespace Tests\Feature\Auth;
use App\Auth\Clock;
use App\Auth\CreateSessionDto;
use App\Auth\SessionRepository;
use App\Http\Middleware\AuthMiddleware;
use App\Shared\ValueObject\EmailAddress;
use App\User\CreateUserDto;
use App\User\User;
use App\User\UserRepository;
use DateTimeImmutable;
use DateTimeZone;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Tests\Fakes\FakeClock;
use Tests\TestCase;
class AuthMiddlewareTest extends TestCase
{
use RefreshDatabase;
private DateTimeImmutable $now;
protected function setUp(): void
{
parent::setUp();
$this->now = $this->utc('2026-07-31T12:00:00');
$this->app->instance(Clock::class, new FakeClock($this->now));
Route::middleware(AuthMiddleware::class)->get(
'/test/authenticated-user',
function (Request $request): JsonResponse {
$user = $request->attributes->get('user');
if (! $user instanceof User) {
return new JsonResponse(['error' => 'missing user'], 500);
}
return new JsonResponse([
'id' => $user->getId(),
'email' => $user->getEmail()->value(),
]);
},
);
}
public function test_valid_cookie_reaches_the_protected_route(): void
{
$user = $this->createUserAndSession(
token: 'valid-token',
expiresAt: $this->now->modify('+7 days'),
);
$response = $this->withCredentials()
->withUnencryptedCookie(
AuthMiddleware::COOKIE_NAME,
'valid-token',
)->getJson('/test/authenticated-user');
$response->assertOk()->assertExactJson([
'id' => $user->getId(),
'email' => 'user@example.com',
]);
}
public function test_missing_cookie_is_rejected(): void
{
$response = $this->getJson('/test/authenticated-user');
$response
->assertStatus(401)
->assertExactJson(['error' => 'unauthenticated']);
}
public function test_expired_cookie_is_rejected_and_deleted(): void
{
$this->createUserAndSession(
token: 'expired-token',
expiresAt: $this->now->modify('-1 day'),
);
$response = $this->withCredentials()
->withUnencryptedCookie(
AuthMiddleware::COOKIE_NAME,
'expired-token',
)->getJson('/test/authenticated-user');
$response->assertStatus(401);
$this->assertNull(
app(SessionRepository::class)->findByToken('expired-token'),
);
}
private function createUserAndSession(
string $token,
DateTimeImmutable $expiresAt,
): User {
$user = app(UserRepository::class)->create(new CreateUserDto(
email: new EmailAddress('user@example.com'),
));
app(SessionRepository::class)->create(new CreateSessionDto(
token: $token,
user: $user,
createdAt: $this->now,
expiresAt: $expiresAt,
));
return $user;
}
private function utc(string $time): DateTimeImmutable
{
return new DateTimeImmutable($time, new DateTimeZone('UTC'));
}
}