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'), password: 'correct-password', )); 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')); } }