449 lines
13 KiB
PHP
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);
|
|
}
|
|
}
|