createComposant('Pompe A'); $this->createComposant('Pompe B'); $client = $this->createViewerClient(); $client->request('GET', '/api/composants'); $this->assertResponseIsSuccessful(); $this->assertJsonContainsHydraCollection(); $this->assertJsonContains(['totalItems' => 2]); } public function testGetItem(): void { $c = $this->createComposant('Pompe A'); $client = $this->createViewerClient(); $client->request('GET', self::iri('composants', $c->getId())); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['name' => 'Pompe A']); } public function testPost(): void { $client = $this->createGestionnaireClient(); $client->request('POST', '/api/composants', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'name' => 'Nouveau composant', 'reference' => 'REF-COMP-001', ], ]); $this->assertResponseStatusCodeSame(201); $this->assertJsonContains(['name' => 'Nouveau composant']); } public function testPostWithType(): void { $mt = $this->createModelType('Pompe', 'POMPE-001', ModelCategory::COMPONENT); $client = $this->createGestionnaireClient(); $client->request('POST', '/api/composants', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'name' => 'Composant typé', 'typeComposant' => self::iri('model_types', $mt->getId()), ], ]); $this->assertResponseStatusCodeSame(201); } public function testPut(): void { $c = $this->createComposant('Pompe A'); $client = $this->createGestionnaireClient(); $client->request('PUT', self::iri('composants', $c->getId()), [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => ['name' => 'Pompe A Renommée'], ]); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['name' => 'Pompe A Renommée']); } public function testPatch(): void { $c = $this->createComposant('Pompe A'); $client = $this->createGestionnaireClient(); $client->request('PATCH', self::iri('composants', $c->getId()), [ 'headers' => ['Content-Type' => 'application/merge-patch+json'], 'json' => ['prix' => '250.00'], ]); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['prix' => '250.00']); } public function testDelete(): void { $c = $this->createComposant('ToDelete'); $client = $this->createGestionnaireClient(); $client->request('DELETE', self::iri('composants', $c->getId())); $this->assertResponseStatusCodeSame(204); } public function testUnauthenticatedAccess(): void { $client = $this->createUnauthenticatedClient(); $client->request('GET', '/api/composants'); $this->assertResponseStatusCodeSame(401); } public function testViewerCannotWrite(): void { $client = $this->createViewerClient(); $client->request('POST', '/api/composants', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => ['name' => 'Blocked'], ]); $this->assertResponseStatusCodeSame(403); } public function testSearchFilter(): void { $this->createComposant('Pompe hydraulique'); $this->createComposant('Vanne de contrôle'); $client = $this->createViewerClient(); $client->request('GET', '/api/composants?name=pompe'); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['totalItems' => 1]); } public function testComposantPieceSlotsPersistedAndReadable(): void { $pieceType = $this->createModelType('Joint', 'JOINT-CSLOT', ModelCategory::PIECE); $piece = $this->createPiece('Joint slot', 'REF-CSLOT', $pieceType); $composant = $this->createComposant('Composant slots pièces'); $this->createComposantPieceSlot($composant, $pieceType, $piece, 3, 0); $em = $this->getEntityManager(); $em->clear(); $refetched = $em->find(Composant::class, $composant->getId()); $this->assertNotNull($refetched); $this->assertCount(1, $refetched->getPieceSlots()); $slot = $refetched->getPieceSlots()->first(); $this->assertSame($pieceType->getId(), $slot->getTypePiece()->getId()); $this->assertSame($piece->getId(), $slot->getSelectedPiece()->getId()); $this->assertSame(3, $slot->getQuantity()); $this->assertSame(0, $slot->getPosition()); } public function testComposantSubcomponentSlotsPersistedAndReadable(): void { $subType = $this->createModelType('Sous-pompe', 'SP-001', ModelCategory::COMPONENT); $subComposant = $this->createComposant('Sous-composant'); $composant = $this->createComposant('Composant parent'); $this->createComposantSubcomponentSlot($composant, 'Sous-pompe A', 'SP-FAM', $subType, $subComposant, 0); $em = $this->getEntityManager(); $em->clear(); $refetched = $em->find(Composant::class, $composant->getId()); $this->assertNotNull($refetched); $this->assertCount(1, $refetched->getSubcomponentSlots()); $slot = $refetched->getSubcomponentSlots()->first(); $this->assertSame('Sous-pompe A', $slot->getAlias()); $this->assertSame('SP-FAM', $slot->getFamilyCode()); $this->assertSame($subType->getId(), $slot->getTypeComposant()->getId()); $this->assertSame($subComposant->getId(), $slot->getSelectedComposant()->getId()); } public function testComposantProductSlotsPersistedAndReadable(): void { $productType = $this->createModelType('Huile', 'HUILE-CSLOT', ModelCategory::PRODUCT); $product = $this->createProduct('Huile slot', 'REF-HSLOT', $productType); $composant = $this->createComposant('Composant slots produits'); $this->createComposantProductSlot($composant, $productType, $product, 'LUB', 0); $em = $this->getEntityManager(); $em->clear(); $refetched = $em->find(Composant::class, $composant->getId()); $this->assertNotNull($refetched); $this->assertCount(1, $refetched->getProductSlots()); $slot = $refetched->getProductSlots()->first(); $this->assertSame($productType->getId(), $slot->getTypeProduct()->getId()); $this->assertSame($product->getId(), $slot->getSelectedProduct()->getId()); $this->assertSame('LUB', $slot->getFamilyCode()); } public function testComposantDeleteCascadesSlots(): void { $composant = $this->createComposant('Composant cascade'); $this->createComposantPieceSlot($composant); $this->createComposantProductSlot($composant); $this->createComposantSubcomponentSlot($composant, 'Sub', 'FAM'); $client = $this->createGestionnaireClient(); $client->request('DELETE', self::iri('composants', $composant->getId())); $this->assertResponseStatusCodeSame(204); } }