first commit
This commit is contained in:
232
tests/User/UserTest.php
Normal file
232
tests/User/UserTest.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user