createPiece('Joint A'); $this->createPiece('Joint B'); $client = $this->createViewerClient(); $client->request('GET', '/api/pieces'); $this->assertResponseIsSuccessful(); $this->assertJsonContainsHydraCollection(); $this->assertJsonContains(['totalItems' => 2]); } public function testGetItem(): void { $p = $this->createPiece('Joint A', 'REF-J001'); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $p->getId())); $this->assertResponseIsSuccessful(); $this->assertJsonContains([ 'name' => 'Joint A', 'reference' => 'REF-J001', ]); } public function testPost(): void { $client = $this->createGestionnaireClient(); $client->request('POST', '/api/pieces', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'name' => 'Nouvelle pièce', 'reference' => 'REF-NEW', ], ]); $this->assertResponseStatusCodeSame(201); $this->assertJsonContains(['name' => 'Nouvelle pièce']); } public function testPostWithType(): void { $mt = $this->createModelType('Joint', 'JOINT-001', ModelCategory::PIECE); $client = $this->createGestionnaireClient(); $client->request('POST', '/api/pieces', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'name' => 'Pièce typée', 'typePiece' => self::iri('model_types', $mt->getId()), ], ]); $this->assertResponseStatusCodeSame(201); } public function testPut(): void { $p = $this->createPiece('Joint A'); $client = $this->createGestionnaireClient(); $client->request('PUT', self::iri('pieces', $p->getId()), [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => ['name' => 'Joint A Renommé'], ]); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['name' => 'Joint A Renommé']); } public function testPatch(): void { $p = $this->createPiece('Joint A'); $client = $this->createGestionnaireClient(); $client->request('PATCH', self::iri('pieces', $p->getId()), [ 'headers' => ['Content-Type' => 'application/merge-patch+json'], 'json' => ['prix' => '15.50'], ]); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['prix' => '15.50']); } public function testDelete(): void { $p = $this->createPiece('ToDelete'); $client = $this->createGestionnaireClient(); $client->request('DELETE', self::iri('pieces', $p->getId())); $this->assertResponseStatusCodeSame(204); } public function testUnauthenticatedAccess(): void { $client = $this->createUnauthenticatedClient(); $client->request('GET', '/api/pieces'); $this->assertResponseStatusCodeSame(401); } public function testViewerCannotWrite(): void { $client = $this->createViewerClient(); $client->request('POST', '/api/pieces', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => ['name' => 'Blocked'], ]); $this->assertResponseStatusCodeSame(403); } public function testUniqueReferenceConstraint(): void { $this->createPiece('Joint A', 'REF-UNIQUE'); $client = $this->createGestionnaireClient(); $client->request('POST', '/api/pieces', [ 'headers' => ['Content-Type' => 'application/ld+json'], 'json' => [ 'name' => 'Joint B', 'reference' => 'REF-UNIQUE', ], ]); $this->assertResponseStatusCodeSame(422); } public function testGetItemReturnsProductIds(): void { $product1 = $this->createProduct('Huile A', 'HUILE-A'); $product2 = $this->createProduct('Graisse B', 'GRAISSE-B'); $piece = $this->createPiece('Joint avec produits', 'REF-JP'); $piece->addProduct($product1); $piece->addProduct($product2); $em = $this->getEntityManager(); $em->persist($piece); $em->flush(); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $data = $client->getResponse()->toArray(); $this->assertArrayHasKey('productIds', $data); $this->assertCount(2, $data['productIds']); $this->assertContains($product1->getId(), $data['productIds']); $this->assertContains($product2->getId(), $data['productIds']); } public function testPieceProductRelationSurvivesRefetch(): void { $product = $this->createProduct('Huile', 'HUILE-REL'); $piece = $this->createPiece('Joint relation', 'REF-REL'); $piece->addProduct($product); $em = $this->getEntityManager(); $em->persist($piece); $em->flush(); $em->clear(); // Re-fetch the piece to verify relation persisted $refetched = $em->find(Piece::class, $piece->getId()); $this->assertNotNull($refetched); $this->assertCount(1, $refetched->getProducts()); $this->assertSame($product->getId(), $refetched->getProducts()->first()->getId()); $this->assertSame([$product->getId()], $refetched->getProductIds()); } }