Files
crm_ecosplay/tests/Command/CleanAttestationsCommandTest.php

229 lines
7.7 KiB
PHP
Raw Normal View History

<?php
namespace App\Tests\Command;
use App\Command\CleanAttestationsCommand;
use App\Entity\Attestation;
use App\Repository\AttestationRepository;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Docuseal\Api;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Filesystem\Filesystem;
class CleanAttestationsCommandTest extends TestCase
{
private EntityManagerInterface $em;
private AttestationRepository $repository;
private Filesystem $filesystem;
private Api $api;
private string $projectDir;
protected function setUp(): void
{
$this->em = $this->createStub(EntityManagerInterface::class);
$this->repository = $this->createStub(AttestationRepository::class);
$this->filesystem = $this->createStub(Filesystem::class);
$this->api = $this->createStub(Api::class);
$this->projectDir = sys_get_temp_dir().'/clean-test-'.bin2hex(random_bytes(4));
mkdir($this->projectDir, 0775, true);
}
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 execute(): CommandTester
{
// Ensure dirs exist so DirectoryIterator doesn't fail in cleanOrphanFiles
if (!is_dir($this->projectDir.'/var/rgpd/signed')) {
mkdir($this->projectDir.'/var/rgpd/signed', 0775, true);
}
$command = new CleanAttestationsCommand(
$this->em,
$this->repository,
$this->filesystem,
$this->projectDir,
'https://fake.docuseal.test',
'fake-key',
);
// Replace Api with stub
$ref = new \ReflectionProperty(CleanAttestationsCommand::class, 'docuSealApi');
$ref->setValue($command, $this->api);
$tester = new CommandTester($command);
$tester->execute([]);
return $tester;
}
private function mockQueryReturning(array $results): void
{
$query = $this->createStub(Query::class);
$query->method('getResult')->willReturn($results);
$qb = $this->createStub(QueryBuilder::class);
$qb->method('where')->willReturnSelf();
$qb->method('setParameter')->willReturnSelf();
$qb->method('getQuery')->willReturn($query);
$this->repository->method('createQueryBuilder')->willReturn($qb);
}
public function testNoAttestationsToClean(): void
{
$this->mockQueryReturning([]);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Aucune attestation', $tester->getDisplay());
}
public function testDeleteAttestationsWithFiles(): void
{
$attestation = new Attestation('access', '127.0.0.1', 'test@test.com', 'secret');
$attestation->setPdfFileUnsigned('/tmp/unsigned.pdf');
$attestation->setPdfFileSigned('/tmp/signed.pdf');
$attestation->setPdfFileCertificate('/tmp/cert.pdf');
$this->mockQueryReturning([$attestation]);
$this->filesystem->method('exists')->willReturn(false);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('1 attestation(s) supprimee(s)', $tester->getDisplay());
}
public function testDeleteAttestationWithSubmitterId(): void
{
$attestation = new Attestation('deletion', '127.0.0.1', 'test@test.com', 'secret');
$attestation->setSubmitterId(42);
$this->mockQueryReturning([$attestation]);
$this->api->method('getSubmitter')->willReturn(['submission_id' => 99]);
$this->filesystem->method('exists')->willReturn(false);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('1 attestation(s) supprimee(s)', $tester->getDisplay());
}
public function testDeleteAttestationSubmitterNoSubmissionId(): void
{
$attestation = new Attestation('no_data', '127.0.0.1', 'test@test.com', 'secret');
$attestation->setSubmitterId(42);
$this->mockQueryReturning([$attestation]);
$this->api->method('getSubmitter')->willReturn([]);
$this->filesystem->method('exists')->willReturn(false);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
}
public function testDeleteFromDocuSealThrows(): void
{
$attestation = new Attestation('access', '127.0.0.1', 'test@test.com', 'secret');
$attestation->setSubmitterId(42);
$this->mockQueryReturning([$attestation]);
$this->api->method('getSubmitter')->willThrowException(new \RuntimeException('API error'));
$this->filesystem->method('exists')->willReturn(false);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('DocuSeal: impossible de supprimer', $tester->getDisplay());
}
public function testCleanOrphanFilesInExistingDir(): void
{
$repository = $this->createStub(AttestationRepository::class);
// Create orphan file with old mtime
$rgpdDir = $this->projectDir.'/var/rgpd';
mkdir($rgpdDir, 0775, true);
$orphanFile = $rgpdDir.'/orphan.pdf';
file_put_contents($orphanFile, 'orphan');
touch($orphanFile, time() - 86400 * 30);
// Return one attestation so we get past the "aucune" check
$attestation = new Attestation('access', '127.0.0.1', 'test@test.com', 'secret');
$query = $this->createStub(Query::class);
$query->method('getResult')->willReturn([$attestation]);
$qb = $this->createStub(QueryBuilder::class);
$qb->method('where')->willReturnSelf();
$qb->method('setParameter')->willReturnSelf();
$qb->method('getQuery')->willReturn($query);
$repository->method('createQueryBuilder')->willReturn($qb);
$command = new CleanAttestationsCommand(
$this->em,
$repository,
new Filesystem(),
$this->projectDir,
'https://fake.docuseal.test',
'fake-key',
);
$ref = new \ReflectionProperty(CleanAttestationsCommand::class, 'docuSealApi');
$ref->setValue($command, $this->api);
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('fichier(s) orphelin(s) supprime(s)', $tester->getDisplay());
}
public function testDeleteFileWithNullPath(): void
{
$attestation = new Attestation('access', '127.0.0.1', 'test@test.com', 'secret');
// No PDF paths set (all null)
$this->mockQueryReturning([$attestation]);
$this->filesystem->method('exists')->willReturn(false);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
}
public function testDeleteFileExistsOnDisk(): void
{
$attestation = new Attestation('access', '127.0.0.1', 'test@test.com', 'secret');
$attestation->setPdfFileUnsigned('/tmp/exists.pdf');
$this->mockQueryReturning([$attestation]);
$this->filesystem->method('exists')->willReturn(true);
$tester = $this->execute();
$this->assertSame(0, $tester->getStatusCode());
}
}