Files
crm_ecosplay/tests/Controller/FactureVerifyControllerTest.php
Serreau Jovann 79c55ba0f9 test: ajout 163 tests unitaires (668->831) avec couverture 73%
Entites (76 tests) :
- PrestataireTest : constructeur, setters, getFullAddress, getTotalPaidHt
- FacturePrestataireTest : constructeur, getPeriodLabel 12 mois, Vich upload
- AdvertPaymentTest : constructeur, types constants, method
- AdvertEventTest : constructeur, getTypeLabel, 5 types + fallback
- FactureLineTest : constructeur, setters, optionnels nullable
- ActionLogTest : constructeur, 10 action constants, severity
- PaymentReminderTest : 8 steps, getStepLabel, getSeverity
- DocusealEventTest : constructeur, nullable fields

Commands (16 tests) :
- ReminderFacturesPrestataireCommandTest : 6 scenarios (aucun presta,
  tous OK, factures manquantes, SIRET vide, mois different)
- PaymentReminderCommandTest : 10 scenarios (skip recent, J+15 emails,
  suspension, termination, exception handling)

Services PDF (24 tests) :
- ComptaPdfTest : empty/FEC/multi-page, totaux Debit/Credit
- RapportFinancierPdfTest : recettes/depenses, bilan equilibre/deficit/excedent
- FacturePdfTest : lignes, TVA, customer address, paid badge, multi-page

Controllers (47 tests) :
- ComptabiliteControllerTest : 18 tests (index, 7 exports CSV, 2 JSON,
  4 PDF, 2 rapport financier)
- PrestatairesControllerTest : 19 tests (CRUD, factures, SIRET proxy)
- FactureControllerTest : 6 tests (search, send)
- FactureVerifyControllerTest : 4 tests (HMAC valid/invalid/not found)

Couverture : 51%->60% classes, 58%->73% methodes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:57:42 +02:00

139 lines
5.0 KiB
PHP

<?php
namespace App\Tests\Controller;
use App\Controller\FactureVerifyController;
use App\Entity\Customer;
use App\Entity\Facture;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
class FactureVerifyControllerTest extends TestCase
{
private function buildController(?Environment $twig = null): FactureVerifyController
{
$twig ??= $this->createStub(Environment::class);
$twig->method('render')->willReturn('<html></html>');
$container = $this->createStub(ContainerInterface::class);
$container->method('has')->willReturnMap([
['twig', true],
['parameter_bag', true],
]);
$container->method('get')->willReturnMap([
['twig', $twig],
['parameter_bag', $this->createStub(ParameterBagInterface::class)],
]);
$controller = new FactureVerifyController();
$controller->setContainer($container);
return $controller;
}
private function buildEmWithFacture(?Facture $facture): EntityManagerInterface
{
$factureRepo = $this->createStub(EntityRepository::class);
$factureRepo->method('find')->willReturn($facture);
$em = $this->createStub(EntityManagerInterface::class);
$em->method('getRepository')->willReturn($factureRepo);
return $em;
}
// ---------------------------------------------------------------
// Valid HMAC — facture found with correct hmac
// ---------------------------------------------------------------
public function testIndexReturnsVerifyPageWhenHmacMatches(): void
{
$customer = $this->createStub(Customer::class);
$facture = $this->createStub(Facture::class);
$facture->method('getHmac')->willReturn('abc123');
$facture->method('getCustomer')->willReturn($customer);
$em = $this->buildEmWithFacture($facture);
$controller = $this->buildController();
$response = $controller->index(1, 'abc123', $em);
$this->assertInstanceOf(Response::class, $response);
$this->assertSame(200, $response->getStatusCode());
}
// ---------------------------------------------------------------
// Invalid HMAC — facture found but wrong hmac
// ---------------------------------------------------------------
public function testIndexReturnsInvalidPageWhenHmacMismatch(): void
{
$facture = $this->createStub(Facture::class);
$facture->method('getHmac')->willReturn('correct_hmac');
$em = $this->buildEmWithFacture($facture);
$twig = $this->createStub(Environment::class);
$twig->method('render')->willReturn('<html>Invalid</html>');
$controller = $this->buildController($twig);
$response = $controller->index(1, 'wrong_hmac', $em);
$this->assertInstanceOf(Response::class, $response);
$this->assertSame(200, $response->getStatusCode());
}
// ---------------------------------------------------------------
// Facture not found
// ---------------------------------------------------------------
public function testIndexReturnsInvalidPageWhenFactureNotFound(): void
{
$em = $this->buildEmWithFacture(null);
$controller = $this->buildController();
$response = $controller->index(999, 'any_hmac', $em);
$this->assertInstanceOf(Response::class, $response);
$this->assertSame(200, $response->getStatusCode());
}
// ---------------------------------------------------------------
// HMAC timing-safe comparison (hash_equals)
// ---------------------------------------------------------------
public function testIndexUsesHashEqualsForComparison(): void
{
// Craft two hmac values that differ only in length to ensure no
// trivial == comparison is used (hash_equals handles timing safety)
$storedHmac = hash_hmac('sha256', 'data', 'secret');
$differentHmac = hash_hmac('sha256', 'other', 'secret');
$facture = $this->createStub(Facture::class);
$facture->method('getHmac')->willReturn($storedHmac);
$em = $this->buildEmWithFacture($facture);
$controller = $this->buildController();
// Wrong hmac -> invalid page (still 200 but renders invalid template)
$response = $controller->index(1, $differentHmac, $em);
$this->assertSame(200, $response->getStatusCode());
// Correct hmac -> verify page
$facture2 = $this->createStub(Facture::class);
$facture2->method('getHmac')->willReturn($storedHmac);
$facture2->method('getCustomer')->willReturn(null);
$em2 = $this->buildEmWithFacture($facture2);
$response2 = $controller->index(1, $storedHmac, $em2);
$this->assertSame(200, $response2->getStatusCode());
}
}