Files
Inventory/tests/AbstractApiTestCase.php
2026-03-13 13:44:52 +01:00

449 lines
13 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Symfony\Bundle\Test\Client;
use App\Entity\Composant;
use App\Entity\ComposantPieceSlot;
use App\Entity\ComposantProductSlot;
use App\Entity\ComposantSubcomponentSlot;
use App\Entity\Constructeur;
use App\Entity\CustomField;
use App\Entity\CustomFieldValue;
use App\Entity\Machine;
use App\Entity\MachineComponentLink;
use App\Entity\MachinePieceLink;
use App\Entity\MachineProductLink;
use App\Entity\ModelType;
use App\Entity\Piece;
use App\Entity\PieceProductSlot;
use App\Entity\Product;
use App\Entity\Profile;
use App\Entity\Site;
use App\Enum\ModelCategory;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
abstract class AbstractApiTestCase extends ApiTestCase
{
private const DEFAULT_PASSWORD = 'test1234';
protected function tearDown(): void
{
$this->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,
?ModelType $typeComposant = null,
?ModelType $typePiece = null,
?ModelType $typeProduct = null,
int $orderIndex = 0,
): CustomField {
$cf = new CustomField();
$cf->setName($name);
$cf->setType($type);
$cf->setOrderIndex($orderIndex);
if (null !== $machine) {
$cf->setMachine($machine);
}
if (null !== $typeComposant) {
$cf->setTypeComposant($typeComposant);
}
if (null !== $typePiece) {
$cf->setTypePiece($typePiece);
}
if (null !== $typeProduct) {
$cf->setTypeProduct($typeProduct);
}
$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, int $quantity = 1): MachinePieceLink
{
$link = new MachinePieceLink();
$link->setMachine($machine);
$link->setPiece($piece);
$link->setQuantity($quantity);
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;
}
protected function createComposantPieceSlot(
Composant $composant,
?ModelType $typePiece = null,
?Piece $selectedPiece = null,
int $quantity = 1,
int $position = 0,
): ComposantPieceSlot {
$slot = new ComposantPieceSlot();
$slot->setComposant($composant);
$slot->setQuantity($quantity);
$slot->setPosition($position);
if (null !== $typePiece) {
$slot->setTypePiece($typePiece);
}
if (null !== $selectedPiece) {
$slot->setSelectedPiece($selectedPiece);
}
$em = $this->getEntityManager();
$em->persist($slot);
$em->flush();
return $slot;
}
protected function createComposantSubcomponentSlot(
Composant $composant,
?string $alias = null,
?string $familyCode = null,
?ModelType $typeComposant = null,
?Composant $selectedComposant = null,
int $position = 0,
): ComposantSubcomponentSlot {
$slot = new ComposantSubcomponentSlot();
$slot->setComposant($composant);
$slot->setAlias($alias);
$slot->setFamilyCode($familyCode);
$slot->setPosition($position);
if (null !== $typeComposant) {
$slot->setTypeComposant($typeComposant);
}
if (null !== $selectedComposant) {
$slot->setSelectedComposant($selectedComposant);
}
$em = $this->getEntityManager();
$em->persist($slot);
$em->flush();
return $slot;
}
protected function createComposantProductSlot(
Composant $composant,
?ModelType $typeProduct = null,
?Product $selectedProduct = null,
?string $familyCode = null,
int $position = 0,
): ComposantProductSlot {
$slot = new ComposantProductSlot();
$slot->setComposant($composant);
$slot->setFamilyCode($familyCode);
$slot->setPosition($position);
if (null !== $typeProduct) {
$slot->setTypeProduct($typeProduct);
}
if (null !== $selectedProduct) {
$slot->setSelectedProduct($selectedProduct);
}
$em = $this->getEntityManager();
$em->persist($slot);
$em->flush();
return $slot;
}
protected function createPieceProductSlot(
Piece $piece,
?ModelType $typeProduct = null,
?Product $selectedProduct = null,
?string $familyCode = null,
int $position = 0,
): PieceProductSlot {
$slot = new PieceProductSlot();
$slot->setPiece($piece);
$slot->setFamilyCode($familyCode);
$slot->setPosition($position);
if (null !== $typeProduct) {
$slot->setTypeProduct($typeProduct);
}
if (null !== $selectedProduct) {
$slot->setSelectedProduct($selectedProduct);
}
$em = $this->getEntityManager();
$em->persist($slot);
$em->flush();
return $slot;
}
// ── 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);
}
}