createAdminClient(); $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], 'json' => $this->validMainPayload('Maintenance Pro', [self::SITE_86]), ]); self::assertSame(201, $response->getStatusCode()); $body = $response->toArray(); // RG-3.11 : companyName normalise en MAJUSCULES. self::assertSame('MAINTENANCE PRO', $body['companyName']); self::assertArrayHasKey('id', $body); // sites embarque (relation directe, site:read) avec name/postalCode. self::assertCount(1, $body['sites']); self::assertSame('86100', $body['sites'][0]['postalCode']); } public function testPostWithoutSiteIsRejected(): void { $client = $this->createAdminClient(); $payload = $this->validMainPayload('Sans Site', [self::SITE_86]); $payload['sites'] = []; $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], 'json' => $payload, ]); // RG-3.03 : au moins un site obligatoire. self::assertSame(422, $response->getStatusCode()); self::assertArrayHasKey('sites', $this->violationsByPath($response->toArray(false))); } public function testPostWithoutCategoryIsRejected(): void { $client = $this->createAdminClient(); $payload = $this->validMainPayload('Sans Categorie', [self::SITE_86]); $payload['categories'] = []; $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], 'json' => $payload, ]); // RG-3.09 : au moins une categorie obligatoire. self::assertSame(422, $response->getStatusCode()); self::assertArrayHasKey('categories', $this->violationsByPath($response->toArray(false))); } public function testPostWithForeignCategoryTypeIsRejected(): void { $client = $this->createAdminClient(); $foreign = $this->foreignCategory(); $payload = $this->validMainPayload('Mauvais Type', [self::SITE_86]); $payload['categories'] = ['/api/categories/'.$foreign->getId()]; $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], 'json' => $payload, ]); // RG-3.09 : categorie hors type PRESTATAIRE -> 422 sur `categories`. self::assertSame(422, $response->getStatusCode()); self::assertArrayHasKey('categories', $this->violationsByPath($response->toArray(false))); } public function testDuplicateCompanyNameReturns409(): void { $this->seedProvider('Doublon Sarl', [self::SITE_86]); $client = $this->createAdminClient(); $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], // Casse differente : l'unicite est insensible a la casse (LOWER). 'json' => $this->validMainPayload('doublon sarl', [self::SITE_86]), ]); // RG-3.10 : doublon de nom (case-insensitive) -> 409. self::assertSame(409, $response->getStatusCode()); } public function testSameNameAfterArchiveIsAllowed(): void { // Index partiel : l'unicite ignore les archives -> reutilisation du nom OK. $this->seedProvider('Recyclage Express', [self::SITE_86], isArchived: true); $client = $this->createAdminClient(); $response = $client->request('POST', '/api/providers', [ 'headers' => ['Content-Type' => self::LD], 'json' => $this->validMainPayload('Recyclage Express', [self::SITE_86]), ]); self::assertSame(201, $response->getStatusCode()); } }