getEntityManager()->clear(); parent::tearDown(); } protected function getEntityManager(): EntityManagerInterface { return static::getContainer()->get('doctrine')->getManager(); } protected function getPasswordHasher(): UserPasswordHasherInterface { return static::getContainer()->get(UserPasswordHasherInterface::class); } // ── Auth helpers ──────────────────────────────────────────────── protected function createAuthenticatedClient(string $role): Client { $profile = $this->createProfile(roles: [$role], password: self::DEFAULT_PASSWORD); $client = static::createClient(); $client->request('POST', '/api/session/profile', [ 'json' => [ 'profileId' => $profile->getId(), 'password' => self::DEFAULT_PASSWORD, ], ]); return $client; } protected function createViewerClient(): Client { return $this->createAuthenticatedClient('ROLE_VIEWER'); } protected function createGestionnaireClient(): Client { return $this->createAuthenticatedClient('ROLE_GESTIONNAIRE'); } protected function createAdminClient(): Client { return $this->createAuthenticatedClient('ROLE_ADMIN'); } protected function createUnauthenticatedClient(): Client { return static::createClient(); } // ── Factory helpers ───────────────────────────────────────────── protected function createProfile( string $firstName = 'Test', string $lastName = 'User', ?string $email = null, array $roles = ['ROLE_USER'], ?string $password = null, bool $isActive = true, ): Profile { $profile = new Profile(); $profile->setFirstName($firstName); $profile->setLastName($lastName); $profile->setEmail($email ?? uniqid('test-', true).'@test.local'); $profile->setRoles($roles); $profile->setIsActive($isActive); if (null !== $password) { $hashed = $this->getPasswordHasher()->hashPassword($profile, $password); $profile->setPassword($hashed); } $em = $this->getEntityManager(); $em->persist($profile); $em->flush(); return $profile; } protected function createSite(string $name = 'Site Test', array $extra = []): Site { $site = new Site(); $site->setName($name); if (isset($extra['contactName'])) { $site->setContactName($extra['contactName']); } if (isset($extra['contactCity'])) { $site->setContactCity($extra['contactCity']); } $em = $this->getEntityManager(); $em->persist($site); $em->flush(); return $site; } protected function createConstructeur(string $name = 'Constructeur Test', ?string $email = null, ?string $phone = null): Constructeur { $c = new Constructeur(); $c->setName($name); $c->setEmail($email); $c->setPhone($phone); $em = $this->getEntityManager(); $em->persist($c); $em->flush(); return $c; } protected function createModelType( string $name = 'ModelType Test', string $code = 'MT-001', ModelCategory $category = ModelCategory::COMPONENT, ): ModelType { $mt = new ModelType(); $mt->setName($name); $mt->setCode($code); $mt->setCategory($category); $em = $this->getEntityManager(); $em->persist($mt); $em->flush(); return $mt; } protected function createMachine(string $name = 'Machine Test', ?Site $site = null, ?string $reference = null): Machine { $site ??= $this->createSite(); $machine = new Machine(); $machine->setName($name); $machine->setSite($site); if (null !== $reference) { $machine->setReference($reference); } $em = $this->getEntityManager(); $em->persist($machine); $em->flush(); return $machine; } protected function createComposant(string $name = 'Composant Test', ?ModelType $type = null): Composant { $c = new Composant(); $c->setName($name); if (null !== $type) { $c->setTypeComposant($type); } $em = $this->getEntityManager(); $em->persist($c); $em->flush(); return $c; } protected function createPiece(string $name = 'Piece Test', ?string $reference = null, ?ModelType $type = null): Piece { $p = new Piece(); $p->setName($name); if (null !== $reference) { $p->setReference($reference); } if (null !== $type) { $p->setTypePiece($type); } $em = $this->getEntityManager(); $em->persist($p); $em->flush(); return $p; } protected function createProduct(string $name = 'Product Test', ?string $reference = null, ?ModelType $type = null): Product { $p = new Product(); $p->setName($name); if (null !== $reference) { $p->setReference($reference); } if (null !== $type) { $p->setTypeProduct($type); } $em = $this->getEntityManager(); $em->persist($p); $em->flush(); return $p; } protected function createCustomField( string $name = 'Custom Field', string $type = 'text', ?Machine $machine = null, ): CustomField { $cf = new CustomField(); $cf->setName($name); $cf->setType($type); if (null !== $machine) { $cf->setMachine($machine); } $em = $this->getEntityManager(); $em->persist($cf); $em->flush(); return $cf; } protected function createCustomFieldValue( CustomField $customField, string $value = 'test value', ?Machine $machine = null, ?Composant $composant = null, ): CustomFieldValue { $cfv = new CustomFieldValue(); $cfv->setValue($value); $cfv->setCustomField($customField); if (null !== $machine) { $cfv->setMachine($machine); } if (null !== $composant) { $cfv->setComposant($composant); } $em = $this->getEntityManager(); $em->persist($cfv); $em->flush(); return $cfv; } protected function createMachineComponentLink(Machine $machine, Composant $composant): MachineComponentLink { $link = new MachineComponentLink(); $link->setMachine($machine); $link->setComposant($composant); $em = $this->getEntityManager(); $em->persist($link); $em->flush(); return $link; } protected function createMachinePieceLink(Machine $machine, Piece $piece, ?MachineComponentLink $parentLink = null): MachinePieceLink { $link = new MachinePieceLink(); $link->setMachine($machine); $link->setPiece($piece); if (null !== $parentLink) { $link->setParentLink($parentLink); } $em = $this->getEntityManager(); $em->persist($link); $em->flush(); return $link; } protected function createMachineProductLink(Machine $machine, Product $product): MachineProductLink { $link = new MachineProductLink(); $link->setMachine($machine); $link->setProduct($product); $em = $this->getEntityManager(); $em->persist($link); $em->flush(); return $link; } // ── Assertion helpers ─────────────────────────────────────────── protected function assertJsonContainsHydraCollection(): void { $this->assertJsonContains(['@type' => 'Collection']); } protected static function iri(string $resource, string $id): string { return sprintf('/api/%s/%s', $resource, $id); } }