test(transport) : rigueur RG sous-ressources (propertyPath, 404 parent, 401, certif)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Failing after 54s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m33s

Repond aux retours de review (rigueur d'assertion transversale) :
- mutualise assertViolationOnPath dans AbstractCarrierApiTestCase (au lieu d'un
  duplicata local a CarrierWriteApiTest) ;
- asserte le propertyPath des 422 des sous-ressources (adresses city/street/postalCode,
  contacts firstName/phones/email, prix clientDeliveryAddress/supplierSupplyAddress/price)
  -> evite les faux-verts du mapping inline (ERP-101) ;
- 404 parent (POST sur /carriers/999999/{addresses,contacts,prices}) ;
- 401 anonyme + filtre ?certificationType= sur la collection (trous releves sur le
  contrat de lecture).
This commit is contained in:
Matthieu
2026-06-16 14:57:45 +02:00
parent 18c88156e5
commit c1fcd9a7c8
6 changed files with 170 additions and 29 deletions
@@ -17,6 +17,7 @@ use App\Module\Transport\Domain\Entity\CarrierPrice;
use App\Module\Transport\Domain\Entity\QualimatCarrier;
use App\Tests\Module\Core\Api\AbstractApiTestCase;
use DateTimeImmutable;
use Symfony\Contracts\HttpClient\ResponseInterface;
/**
* Base des tests fonctionnels du repertoire transporteurs (M4). Apporte les
@@ -47,9 +48,11 @@ abstract class AbstractCarrierApiTestCase extends AbstractApiTestCase
// client/supplier), liberant les Client/Supplier de test pour leur purge.
$em->createQuery('DELETE FROM '.Carrier::class)->execute();
$em->createQuery('DELETE FROM '.ClientEntity::class.' c WHERE c.companyName LIKE :p')
->setParameter('p', self::TEST_REF_PREFIX.'%')->execute();
->setParameter('p', self::TEST_REF_PREFIX.'%')->execute()
;
$em->createQuery('DELETE FROM '.Supplier::class.' s WHERE s.companyName LIKE :p')
->setParameter('p', self::TEST_REF_PREFIX.'%')->execute();
->setParameter('p', self::TEST_REF_PREFIX.'%')->execute()
;
// qualimat_carrier : insere en DBAL brut (entite lecture seule) -> purge DBAL.
$em->getConnection()->executeStatement(
'DELETE FROM qualimat_carrier WHERE siret LIKE :p',
@@ -64,6 +67,27 @@ abstract class AbstractCarrierApiTestCase extends AbstractApiTestCase
return $this->authenticatedClient('admin', 'admin');
}
/**
* Garde-fou ERP-101 : verifie qu'une reponse 422 porte une violation sur le
* `propertyPath` attendu (et pas seulement le bon code HTTP). Sans cette
* assertion, une 422 venue d'une AUTRE cause (autre champ manquant, IRI 404)
* ferait passer le test au vert sans prouver le mapping inline par champ.
*
* Mutualise dans la base (au lieu d'un duplicata par fichier) pour que toute
* la stack d'ecriture (formulaire principal + sous-ressources) l'utilise.
*/
protected static function assertViolationOnPath(object $response, string $path): void
{
/** @var ResponseInterface $response */
$paths = array_column($response->toArray(false)['violations'] ?? [], 'propertyPath');
self::assertContains(
$path,
$paths,
sprintf('Aucune violation sur "%s" (paths: %s).', $path, implode(', ', $paths)),
);
}
/**
* Payload minimal valide du formulaire principal (transporteur non-QUALIMAT,
* non affrete) : nom + certification GMP_PLUS. Sert de base aux tests
@@ -247,7 +271,7 @@ abstract class AbstractCarrierApiTestCase extends AbstractApiTestCase
'status' => 'Valide',
'validity_date' => '2027-12-31',
'is_active' => 'true',
'last_synced_at' => (new DateTimeImmutable())->format('Y-m-d H:i:s'),
'last_synced_at' => new DateTimeImmutable()->format('Y-m-d H:i:s'),
]);
$qualimat = $em->getRepository(QualimatCarrier::class)->findOneBy(['siret' => $siret]);