233 lines
7.6 KiB
PHP
233 lines
7.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\User;
|
|
|
|
use App\User\User;
|
|
use DateTime;
|
|
use InvalidArgumentException;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Tests unitaires pour le modèle User.
|
|
*
|
|
* Vérifie la construction, la validation, les accesseurs
|
|
* et l'hydratation depuis un tableau de base de données.
|
|
*/
|
|
final class UserTest extends TestCase
|
|
{
|
|
|
|
// ── Construction valide ────────────────────────────────────────
|
|
|
|
/**
|
|
* Un utilisateur construit avec des données valides ne doit pas lever d'exception.
|
|
*/
|
|
public function testValidConstruction(): void
|
|
{
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret123', PASSWORD_BCRYPT));
|
|
|
|
$this->assertSame(1, $user->getId());
|
|
$this->assertSame('alice', $user->getUsername());
|
|
$this->assertSame('alice@example.com', $user->getEmail());
|
|
$this->assertSame(User::ROLE_USER, $user->getRole());
|
|
}
|
|
|
|
/**
|
|
* Le rôle par défaut doit être 'user'.
|
|
*/
|
|
public function testDefaultRole(): void
|
|
{
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
|
|
$this->assertSame(User::ROLE_USER, $user->getRole());
|
|
$this->assertFalse($user->isAdmin());
|
|
$this->assertFalse($user->isEditor());
|
|
}
|
|
|
|
/**
|
|
* Un utilisateur avec le rôle 'admin' doit être reconnu comme administrateur.
|
|
*/
|
|
public function testAdminRole(): void
|
|
{
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT), User::ROLE_ADMIN);
|
|
|
|
$this->assertTrue($user->isAdmin());
|
|
$this->assertFalse($user->isEditor());
|
|
}
|
|
|
|
/**
|
|
* Un utilisateur avec le rôle 'editor' doit être reconnu comme éditeur.
|
|
*/
|
|
public function testEditorRole(): void
|
|
{
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT), User::ROLE_EDITOR);
|
|
|
|
$this->assertFalse($user->isAdmin());
|
|
$this->assertTrue($user->isEditor());
|
|
}
|
|
|
|
/**
|
|
* Une date de création explicite doit être conservée.
|
|
*/
|
|
public function testExplicitCreationDate(): void
|
|
{
|
|
$date = new DateTime('2024-01-15 10:00:00');
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT), User::ROLE_USER, $date);
|
|
|
|
$this->assertEquals($date, $user->getCreatedAt());
|
|
}
|
|
|
|
/**
|
|
* Sans date explicite, la date de création doit être définie à maintenant.
|
|
*/
|
|
public function testDefaultCreationDate(): void
|
|
{
|
|
$before = new DateTime();
|
|
$user = new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
$after = new DateTime();
|
|
|
|
$this->assertGreaterThanOrEqual($before, $user->getCreatedAt());
|
|
$this->assertLessThanOrEqual($after, $user->getCreatedAt());
|
|
}
|
|
|
|
|
|
// ── Validation — nom d'utilisateur ─────────────────────────────
|
|
|
|
/**
|
|
* Un nom d'utilisateur de moins de 3 caractères doit lever une exception.
|
|
*/
|
|
public function testUsernameTooShort(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessageMatches('/3 caractères/');
|
|
|
|
new User(1, 'ab', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
}
|
|
|
|
/**
|
|
* Un nom d'utilisateur de plus de 50 caractères doit lever une exception.
|
|
*/
|
|
public function testUsernameTooLong(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessageMatches('/50 caractères/');
|
|
|
|
new User(1, str_repeat('a', 51), 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
}
|
|
|
|
/**
|
|
* Un nom d'utilisateur de exactement 3 caractères doit être accepté.
|
|
*/
|
|
public function testUsernameMinimumLength(): void
|
|
{
|
|
$user = new User(1, 'ali', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
|
|
$this->assertSame('ali', $user->getUsername());
|
|
}
|
|
|
|
/**
|
|
* Un nom d'utilisateur de exactement 50 caractères doit être accepté.
|
|
*/
|
|
public function testUsernameMaximumLength(): void
|
|
{
|
|
$username = str_repeat('a', 50);
|
|
$user = new User(1, $username, 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT));
|
|
|
|
$this->assertSame($username, $user->getUsername());
|
|
}
|
|
|
|
|
|
// ── Validation — email ─────────────────────────────────────────
|
|
|
|
/**
|
|
* Un email invalide doit lever une exception.
|
|
*/
|
|
public function testInvalidEmail(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessageMatches('/email/i');
|
|
|
|
new User(1, 'alice', 'pas-un-email', password_hash('secret', PASSWORD_BCRYPT));
|
|
}
|
|
|
|
/**
|
|
* Un email vide doit lever une exception.
|
|
*/
|
|
public function testEmptyEmail(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
new User(1, 'alice', '', password_hash('secret', PASSWORD_BCRYPT));
|
|
}
|
|
|
|
|
|
// ── Validation — hash du mot de passe ──────────────────────────
|
|
|
|
/**
|
|
* Un hash de mot de passe vide doit lever une exception.
|
|
*/
|
|
public function testEmptyPasswordHash(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessageMatches('/hash/i');
|
|
|
|
new User(1, 'alice', 'alice@example.com', '');
|
|
}
|
|
|
|
|
|
// ── Validation — rôle ──────────────────────────────────────────
|
|
|
|
/**
|
|
* Un rôle invalide doit lever une exception.
|
|
*/
|
|
public function testInvalidRole(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessageMatches('/rôle/i');
|
|
|
|
new User(1, 'alice', 'alice@example.com', password_hash('secret', PASSWORD_BCRYPT), 'superadmin');
|
|
}
|
|
|
|
|
|
// ── Hydratation depuis un tableau ──────────────────────────────
|
|
|
|
/**
|
|
* fromArray() doit hydrater correctement l'utilisateur depuis une ligne de base de données.
|
|
*/
|
|
public function testFromArray(): void
|
|
{
|
|
$hash = password_hash('secret', PASSWORD_BCRYPT);
|
|
|
|
$user = User::fromArray([
|
|
'id' => 42,
|
|
'username' => 'bob',
|
|
'email' => 'bob@example.com',
|
|
'password_hash' => $hash,
|
|
'role' => 'editor',
|
|
'created_at' => '2024-06-01 12:00:00',
|
|
]);
|
|
|
|
$this->assertSame(42, $user->getId());
|
|
$this->assertSame('bob', $user->getUsername());
|
|
$this->assertSame('bob@example.com', $user->getEmail());
|
|
$this->assertSame($hash, $user->getPasswordHash());
|
|
$this->assertSame('editor', $user->getRole());
|
|
$this->assertTrue($user->isEditor());
|
|
}
|
|
|
|
/**
|
|
* fromArray() avec une date absente ne doit pas lever d'exception.
|
|
*/
|
|
public function testFromArrayWithoutDate(): void
|
|
{
|
|
$user = User::fromArray([
|
|
'id' => 1,
|
|
'username' => 'alice',
|
|
'email' => 'alice@example.com',
|
|
'password_hash' => password_hash('secret', PASSWORD_BCRYPT),
|
|
]);
|
|
|
|
$this->assertInstanceOf(DateTime::class, $user->getCreatedAt());
|
|
}
|
|
}
|