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()); } }