refactor: rebrand project to CRM SITECONSEIL (SARL SITECONSEIL)
- Rename all references from E-Cosplay/Ecosplay to SITECONSEIL - Update entity from Association to SARL SITECONSEIL (Siret: 418664058) - Update address to 27 rue Le Serurier, 02100 Saint-Quentin - Update emails: contact@siteconseil.fr, rgpd@siteconseil.fr - Update hosting from GCP to OVHcloud (Roubaix, Gravelines, Strasbourg, Paris) - Update legal pages: mentions legales, CGV, RGPD, conformite, hebergement, cookies, CGU - Add tarifs page with tabs: Site Internet, E-Commerce, Nom de domaine, Esy-Mail, Esy-Mailer, Esy-Tchat, Esy-Meet, Esy-Defender - Add Discord webhook notification workflow - Disable deploy and sonarqube workflows - Update OAuth Keycloak realm to master - Update logo references to logo_facture.png - Remove forced image sizing in Liip Imagine filters - Update SonarQube project key and badge token - Update tribunal competent to Saint-Quentin - Move tarif tabs JS to app.js (CSP compliance) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
228
tests/Command/CleanAttestationsCommandTest.php
Normal file
228
tests/Command/CleanAttestationsCommandTest.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?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());
|
||||
}
|
||||
}
|
||||
57
tests/Command/MeilisearchSetupCommandTest.php
Normal file
57
tests/Command/MeilisearchSetupCommandTest.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\MeilisearchSetupCommand;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Revendeur;
|
||||
use App\Entity\User;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\RevendeurRepository;
|
||||
use App\Service\MeilisearchService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class MeilisearchSetupCommandTest extends TestCase
|
||||
{
|
||||
public function testExecute(): void
|
||||
{
|
||||
$meilisearch = $this->createStub(MeilisearchService::class);
|
||||
$customerRepo = $this->createStub(CustomerRepository::class);
|
||||
$revendeurRepo = $this->createStub(RevendeurRepository::class);
|
||||
|
||||
$customerRepo->method('findAll')->willReturn([]);
|
||||
$revendeurRepo->method('findAll')->willReturn([]);
|
||||
|
||||
$command = new MeilisearchSetupCommand($meilisearch, $customerRepo, $revendeurRepo);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$this->assertStringContainsString('Meilisearch configure et donnees indexees', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testExecuteWithData(): void
|
||||
{
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$customerRepo = $this->createStub(CustomerRepository::class);
|
||||
$revendeurRepo = $this->createStub(RevendeurRepository::class);
|
||||
|
||||
$user = $this->createStub(User::class);
|
||||
$customer = new Customer($user);
|
||||
$revendeur = new Revendeur($user, 'REF-123');
|
||||
|
||||
$customerRepo->method('findAll')->willReturn([$customer]);
|
||||
$revendeurRepo->method('findAll')->willReturn([$revendeur]);
|
||||
|
||||
$meilisearch->expects($this->once())->method('indexCustomer')->with($customer);
|
||||
$meilisearch->expects($this->once())->method('indexRevendeur')->with($revendeur);
|
||||
|
||||
$command = new MeilisearchSetupCommand($meilisearch, $customerRepo, $revendeurRepo);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertStringContainsString('1 client(s) indexe(s)', $tester->getDisplay());
|
||||
$this->assertStringContainsString('1 revendeur(s) indexe(s)', $tester->getDisplay());
|
||||
}
|
||||
}
|
||||
185
tests/Command/StripeSyncCommandTest.php
Normal file
185
tests/Command/StripeSyncCommandTest.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\StripeSyncCommand;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class StripeSyncCommandTest extends TestCase
|
||||
{
|
||||
public function testNoStripeKeyConfigured(): void
|
||||
{
|
||||
$command = new StripeSyncCommand('');
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$this->assertStringContainsString('Cle Stripe non configuree', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testTestPlaceholderKey(): void
|
||||
{
|
||||
$command = new StripeSyncCommand('sk_test_***');
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$this->assertStringContainsString('Cle Stripe non configuree', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testSyncWithEmptyResults(): void
|
||||
{
|
||||
$command = $this->createTestCommand([], [], [], []);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$display = $tester->getDisplay();
|
||||
$this->assertStringContainsString('0 paiement(s)', $display);
|
||||
$this->assertStringContainsString('0 remboursement(s)', $display);
|
||||
$this->assertStringContainsString('0 versement(s)', $display);
|
||||
$this->assertStringContainsString('0 compte(s) Connect', $display);
|
||||
$this->assertStringContainsString('Synchronisation Stripe terminee', $display);
|
||||
}
|
||||
|
||||
public function testSyncWithData(): void
|
||||
{
|
||||
$charge = (object) ['id' => 'ch_123'];
|
||||
$refund = (object) ['id' => 're_456'];
|
||||
$payout = (object) ['id' => 'po_789'];
|
||||
$account = (object) [
|
||||
'id' => 'acct_abc',
|
||||
'email' => 'test@test.com',
|
||||
'charges_enabled' => true,
|
||||
'payouts_enabled' => false,
|
||||
];
|
||||
|
||||
$command = $this->createTestCommand([$charge], [$refund], [$payout], [$account]);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$display = $tester->getDisplay();
|
||||
$this->assertStringContainsString('ch_123', $display);
|
||||
$this->assertStringContainsString('re_456', $display);
|
||||
$this->assertStringContainsString('po_789', $display);
|
||||
$this->assertStringContainsString('acct_abc', $display);
|
||||
$this->assertStringContainsString('actif', $display);
|
||||
$this->assertStringContainsString('non', $display);
|
||||
$this->assertStringContainsString('1 paiement(s)', $display);
|
||||
$this->assertStringContainsString('1 remboursement(s)', $display);
|
||||
$this->assertStringContainsString('1 versement(s)', $display);
|
||||
$this->assertStringContainsString('1 compte(s) Connect', $display);
|
||||
}
|
||||
|
||||
public function testSyncAccountWithNoEmail(): void
|
||||
{
|
||||
$account = (object) [
|
||||
'id' => 'acct_noemail',
|
||||
'email' => null,
|
||||
'charges_enabled' => false,
|
||||
'payouts_enabled' => true,
|
||||
];
|
||||
|
||||
$command = $this->createTestCommand([], [], [], [$account]);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$display = $tester->getDisplay();
|
||||
$this->assertStringContainsString('N/A', $display);
|
||||
$this->assertStringContainsString('inactif', $display);
|
||||
$this->assertStringContainsString('oui', $display);
|
||||
}
|
||||
|
||||
public function testSyncPaymentsThrows(): void
|
||||
{
|
||||
$command = $this->createTestCommand(new \RuntimeException('payment error'), [], [], []);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertStringContainsString('Erreur paiements', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testSyncRefundsThrows(): void
|
||||
{
|
||||
$command = $this->createTestCommand([], new \RuntimeException('refund error'), [], []);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertStringContainsString('Erreur remboursements', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testSyncPayoutsThrows(): void
|
||||
{
|
||||
$command = $this->createTestCommand([], [], new \RuntimeException('payout error'), []);
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertStringContainsString('Erreur versements', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testSyncConnectAccountsThrows(): void
|
||||
{
|
||||
$command = $this->createTestCommand([], [], [], new \RuntimeException('connect error'));
|
||||
$tester = new CommandTester($command);
|
||||
$tester->execute([]);
|
||||
|
||||
$this->assertStringContainsString('Erreur comptes Connect', $tester->getDisplay());
|
||||
}
|
||||
|
||||
private function createTestCommand(
|
||||
array|\Throwable $charges,
|
||||
array|\Throwable $refunds,
|
||||
array|\Throwable $payouts,
|
||||
array|\Throwable $accounts,
|
||||
): StripeSyncCommand {
|
||||
return new class('sk_test_real', $charges, $refunds, $payouts, $accounts) extends StripeSyncCommand {
|
||||
public function __construct(
|
||||
string $key,
|
||||
private array|\Throwable $charges,
|
||||
private array|\Throwable $refunds,
|
||||
private array|\Throwable $payouts,
|
||||
private array|\Throwable $accounts,
|
||||
) {
|
||||
parent::__construct($key);
|
||||
}
|
||||
|
||||
protected function fetchCharges(): iterable
|
||||
{
|
||||
if ($this->charges instanceof \Throwable) {
|
||||
throw $this->charges;
|
||||
}
|
||||
|
||||
return $this->charges;
|
||||
}
|
||||
|
||||
protected function fetchRefunds(): iterable
|
||||
{
|
||||
if ($this->refunds instanceof \Throwable) {
|
||||
throw $this->refunds;
|
||||
}
|
||||
|
||||
return $this->refunds;
|
||||
}
|
||||
|
||||
protected function fetchPayouts(): iterable
|
||||
{
|
||||
if ($this->payouts instanceof \Throwable) {
|
||||
throw $this->payouts;
|
||||
}
|
||||
|
||||
return $this->payouts;
|
||||
}
|
||||
|
||||
protected function fetchConnectAccounts(): iterable
|
||||
{
|
||||
if ($this->accounts instanceof \Throwable) {
|
||||
throw $this->accounts;
|
||||
}
|
||||
|
||||
return $this->accounts;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user