getEm(); // Nettoyage defensif au cas ou un run precedent aurait laisse des restes. $this->cleanupTestData(); // Permissions de test reutilisables (notamment pour le PATCH). $p1 = new Permission('test.core.roles.view', 'View roles (test)', 'core'); $p2 = new Permission('test.core.roles.manage', 'Manage roles (test)', 'core'); $em->persist($p1); $em->persist($p2); // Role custom existant : utilise pour les GET / PATCH / DELETE. $editor = new Role('test_editor', 'Editeur (test)', false, 'Role de test editeur'); $em->persist($editor); // Deuxieme role custom : pour enrichir les collections. $viewer = new Role('test_viewer', 'Visualisateur (test)', false); $em->persist($viewer); $em->flush(); $em->clear(); } protected function tearDown(): void { $this->cleanupTestData(); parent::tearDown(); } public function testPostCreatesCustomRoleAsAdmin(): void { $client = $this->authenticatedClient('admin', 'admin'); $response = $client->request('POST', '/api/roles', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'code' => 'test_new_editor', 'label' => 'Nouvel editeur', 'description' => 'Role de test', ], ]); self::assertResponseStatusCodeSame(201); $data = $response->toArray(); self::assertSame('test_new_editor', $data['code']); self::assertSame('Nouvel editeur', $data['label']); self::assertFalse($data['isSystem']); // Verification cote base : le role existe et isSystem = false. $persisted = $this->getEm()->getRepository(Role::class)->findOneBy(['code' => 'test_new_editor']); self::assertNotNull($persisted); self::assertFalse($persisted->isSystem()); } public function testPostWithDuplicateCodeReturns422(): void { $client = $this->authenticatedClient('admin', 'admin'); $client->request('POST', '/api/roles', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ // `admin` est un role systeme charge par les fixtures. 'code' => SystemRoles::ADMIN_CODE, 'label' => 'Tentative de doublon', ], ]); self::assertResponseStatusCodeSame(422); } public function testPostWithInvalidCodeReturns422(): void { $client = $this->authenticatedClient('admin', 'admin'); $client->request('POST', '/api/roles', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ // Majuscules interdites par la regex snake_case. 'code' => 'BadCode', 'label' => 'Code invalide', ], ]); self::assertResponseStatusCodeSame(422); } public function testPostWithIsSystemTrueIgnoresItAndPersistsFalse(): void { $client = $this->authenticatedClient('admin', 'admin'); $response = $client->request('POST', '/api/roles', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'code' => 'test_sneaky', 'label' => 'Tentative systeme', 'isSystem' => true, ], ]); self::assertResponseStatusCodeSame(201); $data = $response->toArray(); self::assertFalse($data['isSystem']); $persisted = $this->getEm()->getRepository(Role::class)->findOneBy(['code' => 'test_sneaky']); self::assertNotNull($persisted); self::assertFalse($persisted->isSystem()); } public function testGetCollectionAsAdminReturnsRoles(): void { $client = $this->authenticatedClient('admin', 'admin'); $response = $client->request('GET', '/api/roles?pagination=false'); self::assertResponseIsSuccessful(); $data = $response->toArray(); self::assertArrayHasKey('member', $data); // Au moins admin systeme + user systeme + test_editor + test_viewer. self::assertGreaterThanOrEqual(4, $data['totalItems']); $codes = array_column($data['member'], 'code'); self::assertContains('test_editor', $codes); } /** * Verrouille le chemin paginE PAR DEFAUT (ERP-72) : le test ci-dessus passe * `?pagination=false` (usage