Attainly/backend/tests/Unit/Auth/Middleware/AuthMiddlewareTest.php
2026-08-02 20:58:44 +03:00

160 lines
4.5 KiB
PHP

<?php
namespace Tests\Unit\Auth\Middleware;
use App\Auth\CreateSessionDto;
use App\Http\Middleware\AuthMiddleware;
use App\Shared\ValueObject\EmailAddress;
use App\User\User;
use Closure;
use DateTimeImmutable;
use DateTimeZone;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use PHPUnit\Framework\TestCase;
use Tests\Fakes\FakeClock;
use Tests\Fakes\FakeSessionRepository;
class AuthMiddlewareTest extends TestCase
{
private FakeSessionRepository $sessionRepository;
private DateTimeImmutable $now;
private AuthMiddleware $middleware;
protected function setUp(): void
{
$this->now = new DateTimeImmutable(
'2026-07-31T12:00:00',
new DateTimeZone('UTC'),
);
$this->sessionRepository = new FakeSessionRepository;
$this->middleware = new AuthMiddleware(
sessionRepository: $this->sessionRepository,
clock: new FakeClock($this->now),
);
}
public function test_missing_cookie_returns_unauthenticated(): void
{
$capturedRequest = null;
$response = $this->middleware->handle(
$this->requestWithToken(null),
$this->captureNextRequest($capturedRequest),
);
$this->assertSame(401, $response->getStatusCode());
$this->assertSame(
['error' => 'unauthenticated'],
json_decode($response->getContent(), true),
);
$this->assertNull($capturedRequest);
}
public function test_empty_cookie_returns_unauthenticated(): void
{
$capturedRequest = null;
$response = $this->middleware->handle(
$this->requestWithToken(''),
$this->captureNextRequest($capturedRequest),
);
$this->assertSame(401, $response->getStatusCode());
$this->assertNull($capturedRequest);
}
public function test_unknown_token_returns_unauthenticated(): void
{
$capturedRequest = null;
$response = $this->middleware->handle(
$this->requestWithToken('unknown-token'),
$this->captureNextRequest($capturedRequest),
);
$this->assertSame(401, $response->getStatusCode());
$this->assertNull($capturedRequest);
}
public function test_expired_session_is_deleted(): void
{
$this->sessionRepository->create(new CreateSessionDto(
token: 'expired-token',
user: $this->user(),
createdAt: $this->now->modify('-8 days'),
expiresAt: $this->now->modify('-1 day'),
));
$capturedRequest = null;
$response = $this->middleware->handle(
$this->requestWithToken('expired-token'),
$this->captureNextRequest($capturedRequest),
);
$this->assertSame(401, $response->getStatusCode());
$this->assertNull($capturedRequest);
$this->assertNull(
$this->sessionRepository->findByToken('expired-token'),
);
}
public function test_valid_session_attaches_user_and_calls_next(): void
{
$user = $this->user();
$this->sessionRepository->create(new CreateSessionDto(
token: 'valid-token',
user: $user,
createdAt: $this->now,
expiresAt: $this->now->modify('+7 days'),
));
$capturedRequest = null;
$response = $this->middleware->handle(
$this->requestWithToken('valid-token'),
$this->captureNextRequest($capturedRequest),
);
$this->assertSame(200, $response->getStatusCode());
$this->assertNotNull($capturedRequest);
$this->assertSame(
$user,
$capturedRequest->attributes->get('user'),
);
}
private function requestWithToken(?string $token): Request
{
$request = Request::create('/anything', 'GET');
if ($token !== null) {
$request->cookies->set(AuthMiddleware::COOKIE_NAME, $token);
}
return $request;
}
/**
* @param Request|null $capturedRequest
* @return Closure(Request): JsonResponse
*/
private function captureNextRequest(
?Request &$capturedRequest,
): Closure {
return function (Request $request) use (&$capturedRequest) {
$capturedRequest = $request;
return new JsonResponse(['ok' => true]);
};
}
private function user(): User
{
return new User(
id: 7,
email: new EmailAddress('user@example.com'),
passwordHash: 'hashed-password',
);
}
}