diff --git a/src/Controller/Admin/DevisController.php b/src/Controller/Admin/DevisController.php index 0112556..5039119 100644 --- a/src/Controller/Admin/DevisController.php +++ b/src/Controller/Admin/DevisController.php @@ -267,7 +267,7 @@ class DevisController extends AbstractController $hadOld = null !== $devis->getUnsignedPdf(); $uploadDir = $kernel->getProjectDir().'/public/uploads/devis'; - // @codeCoverageIgnoreStart -- Regeneration : supprime l'ancien fichier + // Regeneration : supprime l'ancien fichier if ($hadOld) { $oldPath = $uploadDir.'/'.$devis->getUnsignedPdf(); if (file_exists($oldPath)) { @@ -275,7 +275,6 @@ class DevisController extends AbstractController } $devis->setUnsignedPdf(null); } - // @codeCoverageIgnoreEnd // UploadedFile avec test=true : contourne la verification "is_uploaded_file" // qui rejetterait un fichier genere serveur-side diff --git a/tests/Controller/Admin/DevisControllerTest.php b/tests/Controller/Admin/DevisControllerTest.php index ee8132d..3b4c978 100644 --- a/tests/Controller/Admin/DevisControllerTest.php +++ b/tests/Controller/Admin/DevisControllerTest.php @@ -1615,6 +1615,130 @@ class DevisControllerTest extends TestCase @rmdir($tmpDir); } + public function testGeneratePdfWithExistingPdf(): void + { + $on = new \App\Entity\OrderNumber('04/2026-00095'); + $devis = new \App\Entity\Devis($on, 'secret'); + $devis->setTotalHt('50.00'); + $devis->setTotalTva('0.00'); + $devis->setTotalTtc('50.00'); + + $tmpDir = sys_get_temp_dir().'/devis_pdf_old_'.bin2hex(random_bytes(4)); + mkdir($tmpDir.'/public/uploads/devis', 0777, true); + + // Simulate existing PDF file + $oldPdfName = 'old-devis.pdf'; + file_put_contents($tmpDir.'/public/uploads/devis/'.$oldPdfName, '%PDF-old'); + $devis->setUnsignedPdf($oldPdfName); + + $repo = $this->createStub(\Doctrine\ORM\EntityRepository::class); + $repo->method('find')->willReturn($devis); + $em = $this->createMock(EntityManagerInterface::class); + $em->method('getRepository')->willReturn($repo); + $em->expects($this->once())->method('flush'); + + $kernel = $this->createStub(\Symfony\Component\HttpKernel\KernelInterface::class); + $kernel->method('getProjectDir')->willReturn($tmpDir); + + $twig = $this->createStub(Environment::class); + + $controller = new DevisController( + $em, + $this->createStub(\App\Service\OrderNumberService::class), + $this->createStub(\App\Service\DevisService::class), + $this->createStub(\App\Service\MeilisearchService::class), + ); + + $session = new Session(new MockArraySessionStorage()); + $stack = $this->createStub(RequestStack::class); + $stack->method('getSession')->willReturn($session); + $router = $this->createStub(RouterInterface::class); + $router->method('generate')->willReturn('/redirect'); + $container = $this->createStub(ContainerInterface::class); + $container->method('has')->willReturnMap([ + ['twig', true], ['router', true], ['security.authorization_checker', true], + ['security.token_storage', true], ['request_stack', true], ['parameter_bag', true], + ]); + $container->method('get')->willReturnMap([ + ['twig', $this->createStub(Environment::class)], + ['router', $router], + ['security.authorization_checker', $this->createStub(AuthorizationCheckerInterface::class)], + ['security.token_storage', $this->createStub(TokenStorageInterface::class)], + ['request_stack', $stack], + ['parameter_bag', $this->createStub(ParameterBagInterface::class)], + ]); + $controller->setContainer($container); + + $response = $controller->generatePdf(1, $kernel, $twig); + $this->assertSame(302, $response->getStatusCode()); + + // Old PDF should have been deleted + $this->assertFileDoesNotExist($tmpDir.'/public/uploads/devis/'.$oldPdfName); + + @array_map('unlink', glob($tmpDir.'/public/uploads/devis/*')); + @rmdir($tmpDir.'/public/uploads/devis'); + @rmdir($tmpDir.'/public/uploads'); + @rmdir($tmpDir.'/public'); + @rmdir($tmpDir); + } + + public function testGeneratePdfWithExistingPdfNotOnDisk(): void + { + $on = new \App\Entity\OrderNumber('04/2026-00094'); + $devis = new \App\Entity\Devis($on, 'secret'); + $devis->setTotalHt('30.00'); + $devis->setTotalTva('0.00'); + $devis->setTotalTtc('30.00'); + $devis->setUnsignedPdf('ghost-file.pdf'); // File doesn't exist on disk + + $tmpDir = sys_get_temp_dir().'/devis_pdf_ghost_'.bin2hex(random_bytes(4)); + mkdir($tmpDir.'/public/uploads/devis', 0777, true); + + $repo = $this->createStub(\Doctrine\ORM\EntityRepository::class); + $repo->method('find')->willReturn($devis); + $em = $this->createMock(EntityManagerInterface::class); + $em->method('getRepository')->willReturn($repo); + + $kernel = $this->createStub(\Symfony\Component\HttpKernel\KernelInterface::class); + $kernel->method('getProjectDir')->willReturn($tmpDir); + + $controller = new DevisController( + $em, + $this->createStub(\App\Service\OrderNumberService::class), + $this->createStub(\App\Service\DevisService::class), + $this->createStub(\App\Service\MeilisearchService::class), + ); + + $session = new Session(new MockArraySessionStorage()); + $stack = $this->createStub(RequestStack::class); + $stack->method('getSession')->willReturn($session); + $router = $this->createStub(RouterInterface::class); + $router->method('generate')->willReturn('/redirect'); + $container = $this->createStub(ContainerInterface::class); + $container->method('has')->willReturnMap([ + ['twig', true], ['router', true], ['security.authorization_checker', true], + ['security.token_storage', true], ['request_stack', true], ['parameter_bag', true], + ]); + $container->method('get')->willReturnMap([ + ['twig', $this->createStub(Environment::class)], + ['router', $router], + ['security.authorization_checker', $this->createStub(AuthorizationCheckerInterface::class)], + ['security.token_storage', $this->createStub(TokenStorageInterface::class)], + ['request_stack', $stack], + ['parameter_bag', $this->createStub(ParameterBagInterface::class)], + ]); + $controller->setContainer($container); + + $response = $controller->generatePdf(1, $kernel, $this->createStub(Environment::class)); + $this->assertSame(302, $response->getStatusCode()); + + @array_map('unlink', glob($tmpDir.'/public/uploads/devis/*')); + @rmdir($tmpDir.'/public/uploads/devis'); + @rmdir($tmpDir.'/public/uploads'); + @rmdir($tmpDir.'/public'); + @rmdir($tmpDir); + } + // ── search ── public function testSearchEmptyQuery(): void