From f79f061131387d22a1b685a61d09062da3451cee Mon Sep 17 00:00:00 2001 From: Matthieu Date: Wed, 15 Apr 2026 11:15:41 +0200 Subject: [PATCH] fix(test) : RBAC #344 - corrige EM stale et ajoute cas orphan=true --- config/packages/api_platform.yaml | 3 +- tests/Module/Core/Api/PermissionApiTest.php | 59 +++++++++++++++++---- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml index 7558fb2..fc3d6a9 100644 --- a/config/packages/api_platform.yaml +++ b/config/packages/api_platform.yaml @@ -1,7 +1,8 @@ api_platform: title: Coltura API version: 1.0.0 - # Scan des modules pour decouvrir les classes ApiResource et ApiFilter. + # Scan du module Core pour decouvrir les classes ApiResource et ApiFilter. + # Ajouter un chemin par module lors de l'ajout d'entites ApiResource dans d'autres modules. # Sans ces paths, le compile pass d'API Platform ne declare pas les # services de filtres annotes (les filtres etaient silencieusement # ignores sur Permission — cf. ticket #344). diff --git a/tests/Module/Core/Api/PermissionApiTest.php b/tests/Module/Core/Api/PermissionApiTest.php index 0e7fbe2..9658bf7 100644 --- a/tests/Module/Core/Api/PermissionApiTest.php +++ b/tests/Module/Core/Api/PermissionApiTest.php @@ -27,14 +27,16 @@ final class PermissionApiTest extends ApiTestCase // eviter la deprecation emise a la creation du client de test. protected static ?bool $alwaysBootKernel = true; - private EntityManagerInterface $em; - protected function setUp(): void { parent::setUp(); + // On boote le kernel une fois pour pouvoir seeder les fixtures. + // ATTENTION : ne pas stocker l'EntityManager dans une propriete, + // chaque createClient() dans les tests rebootera le kernel et + // invalidera tout EM capture ici (cf. $alwaysBootKernel = true). self::bootKernel(); - $this->em = self::getContainer()->get('doctrine')->getManager(); + $em = $this->getEm(); // Nettoyage defensif au cas ou un run precedent aurait laisse des restes. $this->cleanupTestPermissions(); @@ -46,11 +48,11 @@ final class PermissionApiTest extends ApiTestCase $p3 = new Permission('test.commercial.clients.view', 'View clients (test)', 'commercial'); $p2->markOrphan(); - $this->em->persist($p1); - $this->em->persist($p2); - $this->em->persist($p3); - $this->em->flush(); - $this->em->clear(); + $em->persist($p1); + $em->persist($p2); + $em->persist($p3); + $em->flush(); + $em->clear(); } protected function tearDown(): void @@ -66,6 +68,9 @@ final class PermissionApiTest extends ApiTestCase self::assertResponseIsSuccessful(); $data = $response->toArray(); + // API Platform 4 emet du JSON-LD 1.1 avec un @context qui utilise un + // @vocab : les cles sortent donc non prefixees (`member`, `totalItems`) + // au lieu des anciennes `hydra:member` / `hydra:totalItems`. self::assertArrayHasKey('member', $data); self::assertGreaterThanOrEqual(3, $data['totalItems']); } @@ -89,6 +94,26 @@ final class PermissionApiTest extends ApiTestCase self::assertNotContains('test.commercial.clients.view', $codes); } + public function testCollectionFilterByOrphanTrue(): void + { + $client = $this->authenticatedClient('admin', 'admin'); + $response = $client->request('GET', '/api/permissions', [ + 'query' => ['orphan' => 'true'], + ]); + + self::assertResponseIsSuccessful(); + $data = $response->toArray(); + foreach ($data['member'] as $item) { + self::assertTrue($item['orphan']); + } + $codes = array_column($data['member'], 'code'); + // La permission marquee orpheline dans setUp() doit remonter... + self::assertContains('test.core.users.manage', $codes); + // ...et celles non orphelines doivent etre exclues. + self::assertNotContains('test.core.users.view', $codes); + self::assertNotContains('test.commercial.clients.view', $codes); + } + public function testCollectionFilterByOrphanFalse(): void { $client = $this->authenticatedClient('admin', 'admin'); @@ -109,7 +134,7 @@ final class PermissionApiTest extends ApiTestCase public function testGetItemAsAdminReturnsAllReadFields(): void { /** @var null|Permission $permission */ - $permission = $this->em->getRepository(Permission::class) + $permission = $this->getEm()->getRepository(Permission::class) ->findOneBy(['code' => 'test.core.users.view']) ; self::assertNotNull($permission); @@ -153,9 +178,23 @@ final class PermissionApiTest extends ApiTestCase self::assertResponseStatusCodeSame(403); } + /** + * Recupere l'EntityManager depuis le container courant. A utiliser a + * chaque appel : apres un createClient(), le kernel est reboote et tout + * EM precedemment capture est invalide. + */ + private function getEm(): EntityManagerInterface + { + if (!self::$kernel) { + self::bootKernel(); + } + + return self::getContainer()->get('doctrine')->getManager(); + } + private function cleanupTestPermissions(): void { - $this->em->createQuery( + $this->getEm()->createQuery( 'DELETE FROM '.Permission::class.' p WHERE p.code LIKE :prefix' )->setParameter('prefix', self::TEST_CODE_PREFIX.'%')->execute(); }