Entites completes a 100% : - AdvertTest : 12 nouveaux (state, customer, totals, hmac, lines, payments) - CustomerTest : 3 nouveaux (isPendingDelete, revendeurCode, updatedAt) - DevisTest : 6 nouveaux (customer, submissionId, lines, state constants) - FactureTest : 10 nouveaux (state, totals, isPaid, lines, hmac, splitIndex) - OrderNumberTest : 1 nouveau (markAsUnused) - WebsiteTest : 1 nouveau (revendeurCode) Services completes/ameliores : - DocuSealServiceTest : 30 nouveaux (sendDevis, resendDevis, download, compta) - AdvertServiceTest : 6 nouveaux (isTvaEnabled, getTvaRate, computeTotals) - DevisServiceTest : 6 nouveaux (idem) - FactureServiceTest : 8 nouveaux (idem + createPaidFactureFromAdvert) - MailerServiceTest : 7 nouveaux (unsubscribe headers, VCF, formatFileSize) - MeilisearchServiceTest : 42 nouveaux (index/remove/search tous types) - RgpdServiceTest : 6 nouveaux (sendVerificationCode, verifyCode) - OrderNumberServiceTest : 2 nouveaux (preview/generate unused) - TarificationServiceTest : 1 nouveau (stripe error logger) - ComptaPdfTest : 4 nouveaux (totaux, colonnes numeriques, signature) - FacturePdfTest : 6 nouveaux (QR code, RIB, CGV Twig, footer skip) Controllers ameliores : - ComptabiliteControllerTest : 13 nouveaux (JSON, PDF, sign, callback) - StatsControllerTest : 2 nouveaux (rich data, 6-month evolution) - SyncControllerTest : 13 nouveaux (sync 6 types + purge) - ClientsControllerTest : 7 nouveaux (show, delete, resendWelcome) - FactureControllerTest : 2 nouveaux (generatePdf 404, send success) - LegalControllerTest : 6 nouveaux (rgpdVerify GET/POST) - TarificationControllerTest : 3 nouveaux (purge paths) - AdminControllersTest : 9 nouveaux (dashboard search, services) - WebhookStripeControllerTest : 3 nouveaux (invalid signatures) - KeycloakAuthenticatorTest : 4 nouveaux (groups, domain check) Commands : - PaymentReminderCommandTest : 1 nouveau (formalNotice step) - TestMailCommandTest : 2 nouveaux (force-dsn success/failure) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
233 lines
7.2 KiB
PHP
233 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Service\Pdf;
|
|
|
|
use App\Service\Pdf\ComptaPdf;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\HttpKernel\KernelInterface;
|
|
|
|
class ComptaPdfTest extends TestCase
|
|
{
|
|
private KernelInterface $kernel;
|
|
private string $projectDir;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->projectDir = sys_get_temp_dir().'/compta-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 makePdf(string $title = 'Journal des ventes', string $from = '01/01/2026', string $to = '31/03/2026'): ComptaPdf
|
|
{
|
|
return new ComptaPdf($this->kernel, $title, $from, $to);
|
|
}
|
|
|
|
public function testGenerateEmptyDataProducesValidPdf(): void
|
|
{
|
|
$pdf = $this->makePdf();
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithRowsProducesValidPdf(): void
|
|
{
|
|
$pdf = $this->makePdf('Journal des ventes');
|
|
$pdf->setData([
|
|
[
|
|
'JournalCode' => 'VTE',
|
|
'JournalLib' => 'Ventes',
|
|
'EcritureNum' => 'E001',
|
|
'EcritureDate' => '01/01/2026',
|
|
'CompteNum' => '411000',
|
|
'CompteLib' => 'Clients',
|
|
'Debit' => '100.00',
|
|
'Credit' => '0.00',
|
|
'EcritureLib' => 'Facture 001',
|
|
],
|
|
[
|
|
'JournalCode' => 'VTE',
|
|
'JournalLib' => 'Ventes',
|
|
'EcritureNum' => 'E002',
|
|
'EcritureDate' => '15/01/2026',
|
|
'CompteNum' => '706000',
|
|
'CompteLib' => 'Prestations',
|
|
'Debit' => '0.00',
|
|
'Credit' => '100.00',
|
|
'EcritureLib' => 'Facture 001',
|
|
],
|
|
]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithDebitCreditSummarised(): void
|
|
{
|
|
$pdf = $this->makePdf('Grand Livre');
|
|
$pdf->setData([
|
|
['Debit' => '200.00', 'Credit' => '50.00', 'EcritureLib' => 'Test'],
|
|
['Debit' => '300.00', 'Credit' => '100.00', 'EcritureLib' => 'Test2'],
|
|
]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
// The PDF should contain total text; check binary content for encoded values
|
|
$this->assertGreaterThan(1000, \strlen($output));
|
|
}
|
|
|
|
public function testGenerateWithUnknownColumnsDistributesWidth(): void
|
|
{
|
|
$pdf = $this->makePdf('Rapport custom');
|
|
$pdf->setData([
|
|
['ColA' => 'Valeur1', 'ColB' => 'Valeur2', 'ColC' => '42.00'],
|
|
['ColA' => 'Valeur3', 'ColB' => 'Valeur4', 'ColC' => '99.00'],
|
|
]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithLogoFile(): void
|
|
{
|
|
// Create a minimal valid JPEG file in the project public dir
|
|
// We use a 1x1 white JPEG for testing
|
|
$jpegData = base64_decode('/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AJQAB/9k=');
|
|
file_put_contents($this->projectDir.'/public/logo.jpg', $jpegData);
|
|
|
|
$pdf = $this->makePdf();
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testSetDataWithEmptyRowsGeneratesNoDataMessage(): void
|
|
{
|
|
$pdf = $this->makePdf();
|
|
$pdf->setData([]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
// Should still produce a valid PDF even with empty data
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testMultiplePagesWithManyRows(): void
|
|
{
|
|
$rows = [];
|
|
for ($i = 1; $i <= 100; ++$i) {
|
|
$rows[] = [
|
|
'JournalCode' => 'VTE',
|
|
'JournalLib' => 'Ventes',
|
|
'EcritureNum' => 'E'.str_pad((string) $i, 4, '0', STR_PAD_LEFT),
|
|
'EcritureDate' => '01/01/2026',
|
|
'CompteNum' => '411000',
|
|
'CompteLib' => 'Clients',
|
|
'Debit' => number_format($i * 10.5, 2),
|
|
'Credit' => '0.00',
|
|
'EcritureLib' => 'Ligne '.$i,
|
|
];
|
|
}
|
|
|
|
$pdf = $this->makePdf('Export FEC');
|
|
$pdf->setData($rows);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithMontantHtColumn(): void
|
|
{
|
|
// Covers the 'MontantHT' totals path in writeSummary (grand livre / balance)
|
|
$pdf = $this->makePdf('Grand Livre');
|
|
$pdf->setData([
|
|
['MontantHT' => '100.00', 'MontantTVA' => '20.00', 'MontantTTC' => '120.00', 'EcritureLib' => 'Test'],
|
|
]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateWithAllNumericColumns(): void
|
|
{
|
|
// Covers isNumericColumn for: Solde, MontantDevise, Montantdevise, JoursRetard
|
|
$pdf = $this->makePdf('Balance');
|
|
$pdf->setData([
|
|
[
|
|
'Debit' => '500.00',
|
|
'Credit' => '200.00',
|
|
'Solde' => '300.00',
|
|
'MontantDevise' => '300.00',
|
|
'Montantdevise' => '300.00',
|
|
'JoursRetard' => '5',
|
|
'EcritureLib' => 'Test',
|
|
],
|
|
]);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
|
|
public function testGenerateSignatureBlockNearPageBottom(): void
|
|
{
|
|
// Creates many rows so the signature block needs a new page
|
|
$rows = [];
|
|
for ($i = 1; $i <= 60; ++$i) {
|
|
$rows[] = [
|
|
'JournalCode' => 'VTE',
|
|
'EcritureLib' => 'Ligne '.$i,
|
|
'Debit' => '0.00',
|
|
'Credit' => '0.00',
|
|
];
|
|
}
|
|
|
|
$pdf = $this->makePdf('Grand Livre');
|
|
$pdf->setData($rows);
|
|
$pdf->generate();
|
|
|
|
$output = $pdf->Output('S');
|
|
|
|
$this->assertStringStartsWith('%PDF', $output);
|
|
}
|
|
}
|