Attainly/backend/tests/Unit/Http/Controllers/AuthControllerTest.php
2026-08-03 19:41:51 +03:00

161 lines
5.2 KiB
PHP

<?php
namespace Tests\Unit\Http\Controllers;
use App\Auth\UseCases\AuthenticateUser\AuthenticateUser;
use App\Auth\UseCases\CreateSession\CreateSession;
use App\Auth\UseCases\Logout\Logout;
use App\Http\Controllers\AuthController;
use App\Http\Middleware\AuthMiddleware;
use App\Shared\ValueObject\EmailAddress;
use App\User\CreateUserDto;
use DateTimeImmutable;
use DateTimeZone;
use Illuminate\Http\Request;
use PHPUnit\Framework\TestCase;
use Tests\Fakes\FakeClock;
use Tests\Fakes\FakePasswordHasher;
use Tests\Fakes\FakeSessionRepository;
use Tests\Fakes\FakeTokenGenerator;
use Tests\Fakes\FakeUserRepository;
class AuthControllerTest extends TestCase
{
private FakeUserRepository $userRepository;
private FakePasswordHasher $passwordHasher;
private FakeSessionRepository $sessionRepository;
private AuthController $controller;
protected function setUp(): void
{
$this->userRepository = new FakeUserRepository;
$this->passwordHasher = new FakePasswordHasher;
$this->sessionRepository = new FakeSessionRepository;
$authenticateUser = new AuthenticateUser(
$this->userRepository,
$this->passwordHasher,
);
$createSession = new CreateSession(
$this->sessionRepository,
new FakeTokenGenerator(['session-token']),
new FakeClock(new DateTimeImmutable(
'2026-07-31T12:00:00',
new DateTimeZone('UTC'),
)),
);
$logout = new Logout($this->sessionRepository);
$this->controller = new AuthController(
$authenticateUser,
$createSession,
$logout,
);
}
public function test_login_returns_user_and_cookie(): void
{
$this->createUser('correct-password');
$response = $this->controller->login(new Request([
'email' => 'user@example.com',
'password' => 'correct-password',
]));
$this->assertSame(200, $response->getStatusCode());
$this->assertSame(
'user@example.com',
json_decode($response->getContent(), true)['user']['email'],
);
$cookie = $response->headers->getCookies()[0];
$this->assertSame(AuthMiddleware::COOKIE_NAME, $cookie->getName());
$this->assertSame('session-token', $cookie->getValue());
$this->assertTrue($cookie->isHttpOnly());
$this->assertSame('lax', $cookie->getSameSite());
$this->assertNotNull(
$this->sessionRepository->findByToken('session-token'),
);
}
public function test_login_returns_bad_request_for_missing_email(): void
{
$response = $this->controller->login(new Request([
'password' => 'correct-password',
]));
$this->assertSame(400, $response->getStatusCode());
$this->assertSame(
['error' => 'email is required'],
json_decode($response->getContent(), true),
);
}
public function test_login_returns_bad_request_for_missing_password(): void
{
$response = $this->controller->login(new Request([
'email' => 'user@example.com',
]));
$this->assertSame(400, $response->getStatusCode());
$this->assertSame(
['error' => 'password is required'],
json_decode($response->getContent(), true),
);
}
public function test_login_returns_unauthorized_for_invalid_credentials(): void
{
$this->createUser('correct-password');
$response = $this->controller->login(new Request([
'email' => 'user@example.com',
'password' => 'wrong-password',
]));
$this->assertSame(401, $response->getStatusCode());
$this->assertSame(
['error' => 'invalid credentials'],
json_decode($response->getContent(), true),
);
}
public function test_logout_deletes_session_and_clears_cookie(): void
{
$this->createUser('correct-password');
$this->controller->login(new Request([
'email' => 'user@example.com',
'password' => 'correct-password',
]));
$request = new Request;
$request->cookies->set(
AuthMiddleware::COOKIE_NAME,
'session-token',
);
$response = $this->controller->logout($request);
$this->assertSame(204, $response->getStatusCode());
$this->assertNull(
$this->sessionRepository->findByToken('session-token'),
);
$cookies = $response->headers->getCookies();
$this->assertCount(1, $cookies);
$this->assertSame(
AuthMiddleware::COOKIE_NAME,
$cookies[0]->getName(),
);
$this->assertSame('', $cookies[0]->getValue());
$this->assertSame(1, $cookies[0]->getExpiresTime());
$this->assertTrue($cookies[0]->isHttpOnly());
$this->assertSame('lax', $cookies[0]->getSameSite());
}
private function createUser(string $password): void
{
$this->userRepository->create(new CreateUserDto(
email: new EmailAddress('user@example.com'),
passwordHash: $this->passwordHasher->hash($password),
));
}
}