getId()); self::assertSame('core.users.view', $permission->getCode()); self::assertSame('Voir les utilisateurs', $permission->getLabel()); self::assertSame('core', $permission->getModule()); self::assertFalse($permission->isOrphan()); } public function testMarkOrphanSetsFlag(): void { $permission = new Permission('core.users.view', 'Voir les utilisateurs', 'core'); $permission->markOrphan(); self::assertTrue($permission->isOrphan()); } public function testReviveResetsOrphanAndUpdatesMetadata(): void { $permission = new Permission('core.users.view', 'Old label', 'core'); $permission->markOrphan(); $permission->revive('New label', 'commercial'); self::assertFalse($permission->isOrphan()); self::assertSame('New label', $permission->getLabel()); self::assertSame('commercial', $permission->getModule()); } public function testUpdateMetadataDoesNotTouchOrphan(): void { $permission = new Permission('core.users.view', 'Old', 'core'); $permission->markOrphan(); $permission->updateMetadata('Lbl', 'core'); self::assertTrue($permission->isOrphan()); self::assertSame('Lbl', $permission->getLabel()); } public function testConstructorRejectsEmptyCode(): void { $this->expectException(InvalidArgumentException::class); new Permission('', 'Libelle', 'core'); } public function testConstructorRejectsCodeWithoutDot(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('invalid_format'); new Permission('invalid_format', 'Libelle', 'core'); } public function testConstructorRejectsEmptyLabel(): void { $this->expectException(InvalidArgumentException::class); new Permission('core.users.view', '', 'core'); } public function testConstructorRejectsEmptyModule(): void { $this->expectException(InvalidArgumentException::class); new Permission('core.users.view', 'Libelle', ''); } }