208 lines
7.6 KiB
PHP
208 lines
7.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Auth;
|
|
|
|
use App\Auth\AccountController;
|
|
use App\Auth\AuthServiceInterface;
|
|
use App\Shared\Http\FlashServiceInterface;
|
|
use App\Shared\Http\SessionManagerInterface;
|
|
use App\User\Exception\WeakPasswordException;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use Tests\ControllerTestCase;
|
|
|
|
/**
|
|
* Tests unitaires pour AccountController.
|
|
*
|
|
* Couvre showChangePassword() et changePassword() :
|
|
* mots de passe non identiques, mot de passe faible, mot de passe actuel
|
|
* incorrect, erreur inattendue et succès.
|
|
*/
|
|
final class AccountControllerTest extends ControllerTestCase
|
|
{
|
|
/** @var \Slim\Views\Twig&MockObject */
|
|
private \Slim\Views\Twig $view;
|
|
|
|
/** @var AuthServiceInterface&MockObject */
|
|
private AuthServiceInterface $authService;
|
|
|
|
/** @var FlashServiceInterface&MockObject */
|
|
private FlashServiceInterface $flash;
|
|
|
|
/** @var SessionManagerInterface&MockObject */
|
|
private SessionManagerInterface $sessionManager;
|
|
|
|
private AccountController $controller;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->view = $this->makeTwigMock();
|
|
$this->authService = $this->createMock(AuthServiceInterface::class);
|
|
$this->flash = $this->createMock(FlashServiceInterface::class);
|
|
$this->sessionManager = $this->createMock(SessionManagerInterface::class);
|
|
|
|
$this->controller = new AccountController(
|
|
$this->view,
|
|
$this->authService,
|
|
$this->flash,
|
|
$this->sessionManager,
|
|
);
|
|
}
|
|
|
|
// ── showChangePassword ───────────────────────────────────────────
|
|
|
|
/**
|
|
* showChangePassword() doit rendre le formulaire de changement de mot de passe.
|
|
*/
|
|
public function testShowChangePasswordRendersForm(): void
|
|
{
|
|
$this->view->expects($this->once())
|
|
->method('render')
|
|
->with($this->anything(), 'pages/account/password-change.twig', $this->anything())
|
|
->willReturnArgument(0);
|
|
|
|
$res = $this->controller->showChangePassword($this->makeGet('/account/password'), $this->makeResponse());
|
|
|
|
$this->assertStatus($res, 200);
|
|
}
|
|
|
|
// ── changePassword ───────────────────────────────────────────────
|
|
|
|
/**
|
|
* changePassword() doit rediriger avec une erreur si les mots de passe ne correspondent pas.
|
|
*/
|
|
public function testChangePasswordRedirectsWhenPasswordMismatch(): void
|
|
{
|
|
$this->flash->expects($this->once())->method('set')
|
|
->with('password_error', 'Les mots de passe ne correspondent pas');
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'oldpass',
|
|
'new_password' => 'newpass1',
|
|
'new_password_confirm' => 'newpass2',
|
|
]);
|
|
$res = $this->controller->changePassword($req, $this->makeResponse());
|
|
|
|
$this->assertRedirectTo($res, '/account/password');
|
|
}
|
|
|
|
/**
|
|
* changePassword() ne doit pas appeler authService si les mots de passe ne correspondent pas.
|
|
*/
|
|
public function testChangePasswordDoesNotCallServiceOnMismatch(): void
|
|
{
|
|
$this->authService->expects($this->never())->method('changePassword');
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'old',
|
|
'new_password' => 'aaa',
|
|
'new_password_confirm' => 'bbb',
|
|
]);
|
|
$this->controller->changePassword($req, $this->makeResponse());
|
|
}
|
|
|
|
/**
|
|
* changePassword() doit afficher une erreur si le nouveau mot de passe est trop court.
|
|
*/
|
|
public function testChangePasswordRedirectsOnWeakPassword(): void
|
|
{
|
|
$this->sessionManager->method('getUserId')->willReturn(1);
|
|
$this->authService->method('changePassword')->willThrowException(new WeakPasswordException());
|
|
|
|
$this->flash->expects($this->once())->method('set')
|
|
->with('password_error', $this->stringContains('8 caractères'));
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'old',
|
|
'new_password' => 'short',
|
|
'new_password_confirm' => 'short',
|
|
]);
|
|
$res = $this->controller->changePassword($req, $this->makeResponse());
|
|
|
|
$this->assertRedirectTo($res, '/account/password');
|
|
}
|
|
|
|
/**
|
|
* changePassword() doit afficher une erreur si le mot de passe actuel est incorrect.
|
|
*/
|
|
public function testChangePasswordRedirectsOnWrongCurrentPassword(): void
|
|
{
|
|
$this->sessionManager->method('getUserId')->willReturn(1);
|
|
$this->authService->method('changePassword')
|
|
->willThrowException(new \InvalidArgumentException('Mot de passe actuel incorrect'));
|
|
|
|
$this->flash->expects($this->once())->method('set')
|
|
->with('password_error', 'Le mot de passe actuel est incorrect');
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'wrong',
|
|
'new_password' => 'newpassword',
|
|
'new_password_confirm' => 'newpassword',
|
|
]);
|
|
$res = $this->controller->changePassword($req, $this->makeResponse());
|
|
|
|
$this->assertRedirectTo($res, '/account/password');
|
|
}
|
|
|
|
/**
|
|
* changePassword() doit afficher une erreur générique en cas d'exception inattendue.
|
|
*/
|
|
public function testChangePasswordRedirectsOnUnexpectedError(): void
|
|
{
|
|
$this->sessionManager->method('getUserId')->willReturn(1);
|
|
$this->authService->method('changePassword')
|
|
->willThrowException(new \RuntimeException('DB error'));
|
|
|
|
$this->flash->expects($this->once())->method('set')
|
|
->with('password_error', $this->stringContains('inattendue'));
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'old',
|
|
'new_password' => 'newpassword',
|
|
'new_password_confirm' => 'newpassword',
|
|
]);
|
|
$res = $this->controller->changePassword($req, $this->makeResponse());
|
|
|
|
$this->assertRedirectTo($res, '/account/password');
|
|
}
|
|
|
|
/**
|
|
* changePassword() doit afficher un message de succès et rediriger en cas de succès.
|
|
*/
|
|
public function testChangePasswordRedirectsWithSuccessFlash(): void
|
|
{
|
|
$this->sessionManager->method('getUserId')->willReturn(1);
|
|
|
|
$this->flash->expects($this->once())->method('set')
|
|
->with('password_success', $this->stringContains('Mot de passe modifié'));
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'oldpass123',
|
|
'new_password' => 'newpass123',
|
|
'new_password_confirm' => 'newpass123',
|
|
]);
|
|
$res = $this->controller->changePassword($req, $this->makeResponse());
|
|
|
|
$this->assertRedirectTo($res, '/account/password');
|
|
}
|
|
|
|
/**
|
|
* changePassword() doit utiliser 0 comme userId de repli si la session est vide.
|
|
*/
|
|
public function testChangePasswordUsesZeroAsUserIdFallback(): void
|
|
{
|
|
$this->sessionManager->method('getUserId')->willReturn(null);
|
|
|
|
$this->authService->expects($this->once())
|
|
->method('changePassword')
|
|
->with(0, $this->anything(), $this->anything());
|
|
|
|
$req = $this->makePost('/account/password', [
|
|
'current_password' => 'old',
|
|
'new_password' => 'newpassword',
|
|
'new_password_confirm' => 'newpassword',
|
|
]);
|
|
$this->controller->changePassword($req, $this->makeResponse());
|
|
}
|
|
}
|