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>
231 lines
7.6 KiB
PHP
231 lines
7.6 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Service\Pdf;
|
|
|
|
use App\Entity\Facture;
|
|
use App\Entity\FactureLine;
|
|
use App\Entity\OrderNumber;
|
|
use App\Service\Pdf\FacturePdf;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\HttpKernel\KernelInterface;
|
|
|
|
class FacturePdfTest extends TestCase
|
|
{
|
|
private const HMAC_SECRET = 'test-hmac-secret';
|
|
|
|
private KernelInterface $kernel;
|
|
private string $projectDir;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->projectDir = sys_get_temp_dir().'/facture-pdf-test-'.bin2hex(random_bytes(4));
|
|
mkdir($this->projectDir.'/public', 0775, true);
|
|
|
|
$this->kernel = $this->createStub(KernelInterface::class);
|
|
$this->kernel->method('getProjectDir')->willReturn($this->projectDir);
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->removeDir($this->projectDir);
|
|
}
|
|
|
|
private function removeDir(string $dir): void
|
|
{
|
|
if (!is_dir($dir)) {
|
|
return;
|
|
}
|
|
foreach (scandir($dir) as $item) {
|
|
if ('.' === $item || '..' === $item) {
|
|
continue;
|
|
}
|
|
$path = $dir.'/'.$item;
|
|
is_dir($path) ? $this->removeDir($path) : unlink($path);
|
|
}
|
|
rmdir($dir);
|
|
}
|
|
|
|
private function makeFacture(string $numOrder = '04/2026-00001'): Facture
|
|
{
|
|
$orderNumber = new OrderNumber($numOrder);
|
|
|
|
return new Facture($orderNumber, self::HMAC_SECRET);
|
|
}
|
|
|
|
private function makeCustomer(bool $withRaisonSociale = false, bool $withAddress2 = false): \App\Entity\Customer
|
|
{
|
|
$customer = $this->createStub(\App\Entity\Customer::class);
|
|
$customer->method('getFullName')->willReturn('Jean Dupont');
|
|
$customer->method('getRaisonSociale')->willReturn($withRaisonSociale ? 'ACME SARL' : null);
|
|
$customer->method('getEmail')->willReturn('jean.dupont@example.com');
|
|
$customer->method('getAddress')->willReturn('42 rue des Tests');
|
|
$customer->method('getAddress2')->willReturn($withAddress2 ? 'Batiment B, etage 3' : null);
|
|
$customer->method('getZipCode')->willReturn('75001');
|
|
$customer->method('getCity')->willReturn('Paris');
|
|
|
|
return $customer;
|
|
}
|
|
|
|
public function testGenerateEmptyFactureProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithLinesProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setTotalHt('100.00');
|
|
$facture->setTotalTva('0.00');
|
|
$facture->setTotalTtc('100.00');
|
|
|
|
$line1 = new FactureLine($facture, 'Hebergement Web', '60.00', 1);
|
|
$line1->setDescription('Hebergement annuel mutualisé');
|
|
$line2 = new FactureLine($facture, 'Nom de domaine', '40.00', 2);
|
|
$line2->setDescription('Renouvellement .fr annuel');
|
|
|
|
$facture->getLines()->add($line1);
|
|
$facture->getLines()->add($line2);
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
$this->assertGreaterThan(1000, \strlen($output));
|
|
}
|
|
|
|
public function testGenerateWithCustomerAddressProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setCustomer($this->makeCustomer(false, false));
|
|
$facture->setTotalHt('50.00');
|
|
$facture->setTotalTva('0.00');
|
|
$facture->setTotalTtc('50.00');
|
|
|
|
$line = new FactureLine($facture, 'Service test', '50.00', 1);
|
|
$facture->getLines()->add($line);
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithTvaProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setTotalHt('100.00');
|
|
$facture->setTotalTva('20.00');
|
|
$facture->setTotalTtc('120.00');
|
|
|
|
$line = new FactureLine($facture, 'Prestation avec TVA', '100.00', 1);
|
|
$facture->getLines()->add($line);
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithPaidFactureProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setTotalHt('200.00');
|
|
$facture->setTotalTva('0.00');
|
|
$facture->setTotalTtc('200.00');
|
|
$facture->setIsPaid(true);
|
|
$facture->setPaidAt(new \DateTimeImmutable('2026-02-15'));
|
|
$facture->setPaidMethod('Virement');
|
|
|
|
$line = new FactureLine($facture, 'Service payé', '200.00', 1);
|
|
$facture->getLines()->add($line);
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithLogoFileProducesValidPdf(): void
|
|
{
|
|
// Minimal valid 1x1 JPEG
|
|
$jpegData = base64_decode('/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AJQAB/9k=');
|
|
file_put_contents($this->projectDir.'/public/logo.jpg', $jpegData);
|
|
|
|
$facture = $this->makeFacture();
|
|
$line = new FactureLine($facture, 'Test', '10.00', 1);
|
|
$facture->getLines()->add($line);
|
|
$facture->setTotalHt('10.00');
|
|
$facture->setTotalTva('0.00');
|
|
$facture->setTotalTtc('10.00');
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithManyLinesSpansMultiplePages(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setTotalHt('1500.00');
|
|
$facture->setTotalTva('0.00');
|
|
$facture->setTotalTtc('1500.00');
|
|
|
|
for ($i = 1; $i <= 15; ++$i) {
|
|
$line = new FactureLine($facture, 'Service '.$i, '100.00', $i);
|
|
$line->setDescription('Description detaillee pour le service numero '.$i.' avec quelques mots supplementaires.');
|
|
$facture->getLines()->add($line);
|
|
}
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithCustomerRaisonSocialeProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture();
|
|
$facture->setCustomer($this->makeCustomer(true, true));
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithSplitIndexProducesValidPdf(): void
|
|
{
|
|
$facture = $this->makeFacture('04/2026-00002');
|
|
$facture->setSplitIndex(2);
|
|
|
|
$pdf = new FacturePdf($this->kernel, $facture);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
}
|