test(commercial) : SupplierExportControllerTest sur base fournisseurs (catégories FOURNISSEUR, dédup F3) (ERP-113) (#73)
Auto Tag Develop / tag (push) Successful in 7s
Auto Tag Develop / tag (push) Successful in 7s
Suivi du finding F3 de la review ERP-92. **Test uniquement** — aucune modif de code applicatif (le controller d'export ERP-91 est correct).
### Problème (F3)
`SupplierExportControllerTest` étendait `AbstractCommercialApiTestCase` et redéfinissait un `seedSupplier()` privé appelant `createCategory()` du parent → catégorie de **type CLIENT**, ce qui viole RG-2.10 dans les données de test (latent : l'export ne filtre pas par type de catégorie, mais le contrat de test était faux).
### Changements
- Bascule de base : `extends AbstractSupplierApiTestCase` (helpers `seedSupplier`/`addContact`/`supplierCategory` sur type **FOURNISSEUR**).
- Suppression du `seedSupplier()` privé (type CLIENT) et du `tearDown()` redondant — dédup F3.
- `testExportUsesPrincipalContactColumns` : utilise `addContact()` de la base ; le téléphone secondaire (non porté par ce helper) est posé via le setter sur le contact retourné.
- `testExportPopulatesCategoryAndSiteColumns` : l'assertion de la colonne « Catégories » dérive le libellé de `supplierCategory('NEGOCIANT')->getName()` au lieu de hardcoder le préfixe de nom de test (la base nomme `test_cli_cat_fr_negociant`).
- Imports `Supplier` / `SupplierContact` / `DateTimeImmutable` retirés (inutilisés).
### Vérifications
- `SupplierExportControllerTest` : 9 tests, 48 assertions — vert sous APP_DEBUG=0.
- Suite complète `make test` : 574 tests, 2448 assertions — OK sous APP_DEBUG=0.
- `make php-cs-fixer-allow-risky` : 0 correction.
> MR stackée sur `feature/ERP-112-fixtures-fournisseurs`.
---------
Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #73
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
This commit was merged in pull request #73.
This commit is contained in:
@@ -4,11 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Commercial\Api;
|
||||
|
||||
use App\Module\Commercial\Domain\Entity\Supplier;
|
||||
use App\Module\Commercial\Domain\Entity\SupplierAddress;
|
||||
use App\Module\Commercial\Domain\Entity\SupplierContact;
|
||||
use App\Module\Sites\Domain\Entity\Site;
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
/**
|
||||
@@ -23,24 +20,11 @@ use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class SupplierExportControllerTest extends AbstractCommercialApiTestCase
|
||||
final class SupplierExportControllerTest extends AbstractSupplierApiTestCase
|
||||
{
|
||||
private const string XLSX_MIME = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
private const string EXPORT_URL = '/api/suppliers/export.xlsx';
|
||||
|
||||
/**
|
||||
* Les fournisseurs doivent etre purges AVANT les categories de test (le parent
|
||||
* supprime les categories `test_cli_cat_*`) : la jointure supplier_category est
|
||||
* en ON DELETE CASCADE cote supplier mais RESTRICT cote category. Le DELETE DQL
|
||||
* sur Supplier declenche le cascade BDD sur supplier_category / _contact /
|
||||
* _address (et leurs sous-jointures), liberant les categories pour le parent.
|
||||
*/
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->getEm()->createQuery('DELETE FROM '.Supplier::class)->execute();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testExportReturnsXlsxResponseWithAttachmentFilename(): void
|
||||
{
|
||||
$client = $this->createAdminClient();
|
||||
@@ -110,9 +94,13 @@ final class SupplierExportControllerTest extends AbstractCommercialApiTestCase
|
||||
$supplier = $this->seedSupplier('Contact Co');
|
||||
|
||||
// position 1 (secondaire) insere en premier...
|
||||
$this->addContact($supplier, 'Secondaire', 'Bob', 1, '0600000001', '0600000002', 'bob@contact.co');
|
||||
$this->addContact($supplier, 'Bob', 'Secondaire', '0600000001', 'bob@contact.co', 1);
|
||||
// ...position 0 (principal) insere ensuite : c'est lui qui doit gagner.
|
||||
$this->addContact($supplier, 'Principal', 'Alice', 0, '0612345678', '0698765432', 'alice@contact.co');
|
||||
$principal = $this->addContact($supplier, 'Alice', 'Principal', '0612345678', 'alice@contact.co', 0);
|
||||
// Le telephone secondaire n'est pas porte par le helper de base : on le pose
|
||||
// directement sur le contact principal pour alimenter la colonne dediee.
|
||||
$principal->setPhoneSecondary('0698765432');
|
||||
$this->getEm()->flush();
|
||||
|
||||
$row = $this->rowFor($client->request('GET', self::EXPORT_URL)->getContent(), 'CONTACT CO');
|
||||
|
||||
@@ -149,8 +137,10 @@ final class SupplierExportControllerTest extends AbstractCommercialApiTestCase
|
||||
|
||||
$flat = $this->flatten($this->gridFromResponse($client->request('GET', self::EXPORT_URL)->getContent()));
|
||||
|
||||
// Colonne « Catégories » : libelle de la categorie du fournisseur (getName()).
|
||||
self::assertStringContainsString('test_cli_cat_negociant', $flat);
|
||||
// Colonne « Catégories » : libelle de la categorie FOURNISSEUR du fournisseur
|
||||
// (getName()). On le derive du helper de base (idempotent) plutot que de
|
||||
// hardcoder le prefixe de nom de test.
|
||||
self::assertStringContainsString((string) $this->supplierCategory('NEGOCIANT')->getName(), $flat);
|
||||
// Colonne « Sites » : site agrege depuis l'adresse (RG-2.06).
|
||||
self::assertStringContainsString((string) $site->getName(), $flat);
|
||||
}
|
||||
@@ -206,50 +196,6 @@ final class SupplierExportControllerTest extends AbstractCommercialApiTestCase
|
||||
self::assertResponseStatusCodeSame(401);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seede directement un Supplier en base (sans passer par l'API), pour les
|
||||
* tests de liste / archivage. Stocke le nom en MAJUSCULES pour refleter l'etat
|
||||
* normalise (RG-2.12) qu'aurait produit le SupplierProcessor via l'API.
|
||||
*/
|
||||
private function seedSupplier(string $companyName, bool $isArchived = false, string $categoryCode = 'SECTEUR'): Supplier
|
||||
{
|
||||
$em = $this->getEm();
|
||||
$supplier = new Supplier();
|
||||
$supplier->setCompanyName(mb_strtoupper($companyName, 'UTF-8'));
|
||||
$supplier->addCategory($this->createCategory($categoryCode));
|
||||
$supplier->setIsArchived($isArchived);
|
||||
if ($isArchived) {
|
||||
$supplier->setArchivedAt(new DateTimeImmutable());
|
||||
}
|
||||
$em->persist($supplier);
|
||||
$em->flush();
|
||||
|
||||
return $supplier;
|
||||
}
|
||||
|
||||
private function addContact(
|
||||
Supplier $supplier,
|
||||
string $lastName,
|
||||
string $firstName,
|
||||
int $position,
|
||||
?string $phonePrimary = null,
|
||||
?string $phoneSecondary = null,
|
||||
?string $email = null,
|
||||
): void {
|
||||
$contact = new SupplierContact();
|
||||
$contact->setSupplier($supplier);
|
||||
$contact->setLastName($lastName);
|
||||
$contact->setFirstName($firstName);
|
||||
$contact->setPosition($position);
|
||||
$contact->setPhonePrimary($phonePrimary);
|
||||
$contact->setPhoneSecondary($phoneSecondary);
|
||||
$contact->setEmail($email);
|
||||
|
||||
$supplier->addContact($contact);
|
||||
$this->getEm()->persist($contact);
|
||||
$this->getEm()->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Relit le binaire XLSX d'une reponse et renvoie la grille de cellules.
|
||||
*
|
||||
@@ -284,7 +230,7 @@ final class SupplierExportControllerTest extends AbstractCommercialApiTestCase
|
||||
/**
|
||||
* Renvoie la ligne de donnees dont la 1re colonne (nom) vaut $companyName.
|
||||
*
|
||||
* @return array<int, mixed>|null
|
||||
* @return null|array<int, mixed>
|
||||
*/
|
||||
private function rowFor(string $binary, string $companyName): ?array
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user