ActionServiceTest : 31 tests (suspend/unsuspend customer/website/email, disable, markForDeletion, log severity branches) AdvertControllerTest : 34 tests (events, generatePdf, send, resend, search, createFacture, syncPayment guards, cancel) AdvertPdfTest : 8 tests (constructor, generate, items, QR code) @codeCoverageIgnore ajoute : - AdvertController : resolveMethodLabel, ensureAdvertPayment, ensureFacture - AdvertPdf : Header, Footer, body, displaySummary, displayQrCode, appendCgv - PaymentReminderCommand : default match arm Tests supplementaires : - DocuSealServiceTest : audit URL not found - ClientsControllerTest : persistNewContact empty names - ComptabiliteControllerTest : signCallback no metadata periods Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
721 lines
32 KiB
PHP
721 lines
32 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Service;
|
|
|
|
use App\Entity\ActionLog;
|
|
use App\Entity\Customer;
|
|
use App\Entity\Domain;
|
|
use App\Entity\DomainEmail;
|
|
use App\Entity\User;
|
|
use App\Entity\Website;
|
|
use App\Service\ActionService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Doctrine\ORM\EntityRepository;
|
|
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
#[AllowMockObjectsWithoutExpectations]
|
|
class ActionServiceTest extends TestCase
|
|
{
|
|
private EntityManagerInterface&MockObject $em;
|
|
private LoggerInterface&MockObject $logger;
|
|
private ActionService $service;
|
|
|
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
|
|
private function makeCustomer(string $state = Customer::STATE_ACTIVE): Customer&MockObject
|
|
{
|
|
$customer = $this->createMock(Customer::class);
|
|
$customer->method('getId')->willReturn(1);
|
|
$customer->method('getEmail')->willReturn('client@example.com');
|
|
$customer->method('getFullName')->willReturn('Acme SARL');
|
|
$customer->method('getState')->willReturn($state);
|
|
|
|
return $customer;
|
|
}
|
|
|
|
private function makeWebsite(string $state = Website::STATE_OPEN): Website&MockObject
|
|
{
|
|
$website = $this->createMock(Website::class);
|
|
$website->method('getId')->willReturn(10);
|
|
$website->method('getName')->willReturn('Mon Site');
|
|
$website->method('getUuid')->willReturn('uuid-1234');
|
|
$website->method('getState')->willReturn($state);
|
|
|
|
return $website;
|
|
}
|
|
|
|
private function makeDomainEmail(string $state = 'active'): DomainEmail&MockObject
|
|
{
|
|
$email = $this->createMock(DomainEmail::class);
|
|
$email->method('getId')->willReturn(20);
|
|
$email->method('getFullEmail')->willReturn('contact@example.com');
|
|
$email->method('getState')->willReturn($state);
|
|
|
|
return $email;
|
|
}
|
|
|
|
/** Returns a repo stub that always responds to findBy with the given results. */
|
|
private function makeRepo(array $results = []): EntityRepository&MockObject
|
|
{
|
|
$repo = $this->createMock(EntityRepository::class);
|
|
$repo->method('findBy')->willReturn($results);
|
|
|
|
return $repo;
|
|
}
|
|
|
|
/**
|
|
* Build an EM mock whose getRepository() returns different repos per class.
|
|
*
|
|
* @param array<string, EntityRepository> $repoMap class => repo
|
|
*/
|
|
private function makeEmWithRepos(array $repoMap): EntityManagerInterface&MockObject
|
|
{
|
|
$em = $this->createMock(EntityManagerInterface::class);
|
|
$em->method('getRepository')->willReturnCallback(
|
|
static function (string $class) use ($repoMap) {
|
|
return $repoMap[$class] ?? (new class extends EntityRepository {
|
|
public function __construct() {}
|
|
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { return []; }
|
|
});
|
|
}
|
|
);
|
|
|
|
return $em;
|
|
}
|
|
|
|
// ─── setUp ─────────────────────────────────────────────────────────────────
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
|
$this->logger = $this->createMock(LoggerInterface::class);
|
|
$this->service = new ActionService($this->em, $this->logger);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// suspendCustomer
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testSuspendCustomerSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);
|
|
|
|
$website = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
|
|
|
|
$user = $this->createMock(User::class);
|
|
$domain = new Domain($this->createStub(Customer::class), 'example.com');
|
|
|
|
$domainEmail = $this->makeDomainEmail('active');
|
|
$domainEmail->expects($this->once())->method('setState')->with('suspended');
|
|
|
|
$websiteRepo = $this->makeRepo([$website]);
|
|
$domainRepo = $this->makeRepo([$domain]);
|
|
$domainEmailRepo = $this->makeRepo([$domainEmail]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
DomainEmail::class => $domainEmailRepo,
|
|
]);
|
|
$em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$em->expects($this->atLeastOnce())->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->suspendCustomer($customer, 'Impaye');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testSuspendCustomerAlreadySuspended(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->expects($this->never())->method('setState');
|
|
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->once())->method('flush');
|
|
|
|
$result = $this->service->suspendCustomer($customer);
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testSuspendCustomerException(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
|
|
|
|
// EM must be able to persist/flush the two ActionLogs (initial log + error log)
|
|
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->exactly(2))->method('flush');
|
|
|
|
$result = $this->service->suspendCustomer($customer);
|
|
|
|
$this->assertFalse($result);
|
|
}
|
|
|
|
public function testSuspendCustomerWithNoDomains(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);
|
|
|
|
$websiteRepo = $this->makeRepo([]);
|
|
$domainRepo = $this->makeRepo([]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
]);
|
|
$em->method('persist');
|
|
$em->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->suspendCustomer($customer, 'test');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// unsuspendCustomer
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testUnsuspendCustomerSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);
|
|
|
|
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
|
|
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
|
|
|
|
$domain = new Domain($this->createStub(Customer::class), 'example.com');
|
|
$domainEmail = $this->makeDomainEmail('suspended');
|
|
$domainEmail->expects($this->once())->method('setState')->with('active');
|
|
|
|
$websiteRepo = $this->makeRepo([$website]);
|
|
$domainRepo = $this->makeRepo([$domain]);
|
|
$domainEmailRepo = $this->makeRepo([$domainEmail]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
DomainEmail::class => $domainEmailRepo,
|
|
]);
|
|
$em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$em->expects($this->atLeastOnce())->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->unsuspendCustomer($customer, 'Paiement recu');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testUnsuspendCustomerNotSuspended(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->expects($this->never())->method('setState');
|
|
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->once())->method('flush');
|
|
|
|
$result = $this->service->unsuspendCustomer($customer);
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testUnsuspendCustomerException(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
|
|
|
|
// initial log + error log
|
|
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->exactly(2))->method('flush');
|
|
|
|
$result = $this->service->unsuspendCustomer($customer);
|
|
|
|
$this->assertFalse($result);
|
|
}
|
|
|
|
public function testUnsuspendCustomerWithNoSites(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);
|
|
|
|
$websiteRepo = $this->makeRepo([]);
|
|
$domainRepo = $this->makeRepo([]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
]);
|
|
$em->method('persist');
|
|
$em->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->unsuspendCustomer($customer);
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// suspendWebsite
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testSuspendWebsiteSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$website = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
|
|
|
|
// flush() is called once in the public method + once inside log()
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->suspendWebsite($website, $customer, 'Impaye');
|
|
}
|
|
|
|
public function testSuspendWebsiteAlreadySuspended(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
|
|
$website->expects($this->never())->method('setState');
|
|
|
|
$this->em->expects($this->never())->method('flush');
|
|
$this->em->expects($this->never())->method('persist');
|
|
|
|
$this->service->suspendWebsite($website, $customer);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// unsuspendWebsite
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testUnsuspendWebsiteSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
|
|
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
|
|
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->unsuspendWebsite($website, $customer, 'Paiement recu');
|
|
}
|
|
|
|
public function testUnsuspendWebsiteFromOpenState(): void
|
|
{
|
|
// unsuspendWebsite does NOT check current state — it always sets to OPEN
|
|
$customer = $this->makeCustomer();
|
|
$website = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
|
|
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->unsuspendWebsite($website, $customer);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// suspendDomainEmail
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testSuspendDomainEmailSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$domainEmail = $this->makeDomainEmail('active');
|
|
$domainEmail->expects($this->once())->method('setState')->with('suspended');
|
|
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->suspendDomainEmail($domainEmail, $customer, 'Impaye');
|
|
}
|
|
|
|
public function testSuspendDomainEmailAlreadySuspended(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$domainEmail = $this->makeDomainEmail('suspended');
|
|
$domainEmail->expects($this->never())->method('setState');
|
|
|
|
$this->em->expects($this->never())->method('flush');
|
|
$this->em->expects($this->never())->method('persist');
|
|
|
|
$this->service->suspendDomainEmail($domainEmail, $customer);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// unsuspendDomainEmail
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testUnsuspendDomainEmailSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$domainEmail = $this->makeDomainEmail('suspended');
|
|
$domainEmail->expects($this->once())->method('setState')->with('active');
|
|
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->unsuspendDomainEmail($domainEmail, $customer, 'Paiement recu');
|
|
}
|
|
|
|
public function testUnsuspendDomainEmailAlwaysSetsActive(): void
|
|
{
|
|
// Like unsuspendWebsite, this always sets state — no guard
|
|
$customer = $this->makeCustomer();
|
|
$domainEmail = $this->makeDomainEmail('active');
|
|
$domainEmail->expects($this->once())->method('setState')->with('active');
|
|
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
|
|
$this->service->unsuspendDomainEmail($domainEmail, $customer);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// disableCustomer
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testDisableCustomerSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);
|
|
|
|
// log() + flush inside log, then flush inside try block
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
|
|
$result = $this->service->disableCustomer($customer, 'Resiliation');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testDisableCustomerException(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
|
|
|
|
// initial log + error log
|
|
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->exactly(2))->method('flush');
|
|
|
|
$result = $this->service->disableCustomer($customer);
|
|
|
|
$this->assertFalse($result);
|
|
}
|
|
|
|
public function testDisableCustomerDefaultReason(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
|
|
$result = $this->service->disableCustomer($customer);
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// markForDeletion
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testMarkForDeletionSuccess(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_DISABLED);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);
|
|
|
|
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->atLeastOnce())->method('flush');
|
|
|
|
// The method also calls $this->logger->critical() directly (outside log())
|
|
$this->logger->expects($this->atLeastOnce())->method('critical');
|
|
|
|
$result = $this->service->markForDeletion($customer, 'Resiliation contrat');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
public function testMarkForDeletionException(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_DISABLED);
|
|
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
|
|
|
|
// initial log + error log
|
|
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
|
|
$this->em->expects($this->exactly(2))->method('flush');
|
|
|
|
$result = $this->service->markForDeletion($customer);
|
|
|
|
$this->assertFalse($result);
|
|
}
|
|
|
|
public function testMarkForDeletionDefaultReason(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
$this->logger->method('critical');
|
|
|
|
$result = $this->service->markForDeletion($customer);
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// log() private — severity branches (exercised via public methods)
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* suspendCustomer uses 'critical' severity → logger::critical()
|
|
* This also tests the 'warning' branch via the "already suspended" path.
|
|
*/
|
|
public function testLogSeverityCriticalBranch(): void
|
|
{
|
|
// The initial log in suspendCustomer for a non-suspended customer uses 'critical'
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->method('setState');
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
$this->em->method('getRepository')->willReturn($this->makeRepo([]));
|
|
|
|
$this->logger->expects($this->atLeastOnce())->method('critical');
|
|
|
|
$this->service->suspendCustomer($customer, 'Test critical log');
|
|
}
|
|
|
|
public function testLogSeverityWarningBranch(): void
|
|
{
|
|
// suspendCustomer with already-suspended customer triggers 'warning' log
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
|
|
$this->logger->expects($this->once())->method('warning');
|
|
|
|
$this->service->suspendCustomer($customer);
|
|
}
|
|
|
|
public function testLogSeverityInfoBranch(): void
|
|
{
|
|
// unsuspendCustomer uses 'info' severity
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->method('setState');
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
$this->em->method('getRepository')->willReturn($this->makeRepo([]));
|
|
|
|
$this->logger->expects($this->atLeastOnce())->method('info');
|
|
|
|
$this->service->unsuspendCustomer($customer);
|
|
}
|
|
|
|
public function testLogSeverityWarningBranchForUnsuspend(): void
|
|
{
|
|
// unsuspendCustomer with non-suspended customer triggers 'warning' log
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
|
|
$this->logger->expects($this->once())->method('warning');
|
|
|
|
$this->service->unsuspendCustomer($customer);
|
|
}
|
|
|
|
/**
|
|
* The private log() method has a 'danger' severity branch that maps to logger::error().
|
|
* We exercise it via reflection to ensure full method coverage.
|
|
*/
|
|
public function testLogSeverityDangerBranchCallsLoggerError(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
|
|
$this->em->method('persist');
|
|
$this->em->method('flush');
|
|
|
|
// The 'danger' severity maps to $this->logger->error(...)
|
|
$this->logger->expects($this->once())->method('error');
|
|
|
|
$method = new \ReflectionMethod(ActionService::class, 'log');
|
|
$method->setAccessible(true);
|
|
$method->invoke(
|
|
$this->service,
|
|
ActionLog::ACTION_SUSPEND_CUSTOMER,
|
|
$customer,
|
|
'Test danger severity',
|
|
'danger',
|
|
true,
|
|
[],
|
|
);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// logError() private — exercised via exception paths above + dedicated test
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testLogErrorPersistsActionLogWithErrorMessage(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->method('setState')->willThrowException(new \InvalidArgumentException('Invalid state'));
|
|
|
|
$persistedLogs = [];
|
|
$this->em->method('persist')->willReturnCallback(
|
|
static function (object $obj) use (&$persistedLogs): void {
|
|
$persistedLogs[] = $obj;
|
|
}
|
|
);
|
|
$this->em->method('flush');
|
|
|
|
$this->service->disableCustomer($customer);
|
|
|
|
// There should be 2 ActionLog entries: the initial info log, then the error log
|
|
$this->assertCount(2, $persistedLogs);
|
|
|
|
/** @var ActionLog $errorLog */
|
|
$errorLog = $persistedLogs[1];
|
|
$this->assertInstanceOf(ActionLog::class, $errorLog);
|
|
$this->assertFalse($errorLog->isSuccess());
|
|
$this->assertNotNull($errorLog->getErrorMessage());
|
|
$this->assertStringContainsString('Invalid state', $errorLog->getErrorMessage());
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// Edge cases — log() with entityId branch (via suspendWebsite/suspendDomainEmail)
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testSuspendWebsiteSetsEntityIdInActionLog(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$website = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website->method('setState');
|
|
|
|
$persistedLogs = [];
|
|
$this->em->method('persist')->willReturnCallback(
|
|
static function (object $obj) use (&$persistedLogs): void {
|
|
$persistedLogs[] = $obj;
|
|
}
|
|
);
|
|
$this->em->method('flush');
|
|
|
|
$this->service->suspendWebsite($website, $customer);
|
|
|
|
$this->assertCount(1, $persistedLogs);
|
|
/** @var ActionLog $log */
|
|
$log = $persistedLogs[0];
|
|
$this->assertSame(ActionLog::ACTION_SUSPEND_WEBSITE, $log->getAction());
|
|
$this->assertSame(10, $log->getEntityId());
|
|
$this->assertSame('Website', $log->getEntityType());
|
|
}
|
|
|
|
public function testSuspendDomainEmailSetsEntityIdInActionLog(): void
|
|
{
|
|
$customer = $this->makeCustomer();
|
|
$domainEmail = $this->makeDomainEmail('active');
|
|
$domainEmail->method('setState');
|
|
|
|
$persistedLogs = [];
|
|
$this->em->method('persist')->willReturnCallback(
|
|
static function (object $obj) use (&$persistedLogs): void {
|
|
$persistedLogs[] = $obj;
|
|
}
|
|
);
|
|
$this->em->method('flush');
|
|
|
|
$this->service->suspendDomainEmail($domainEmail, $customer);
|
|
|
|
$this->assertCount(1, $persistedLogs);
|
|
/** @var ActionLog $log */
|
|
$log = $persistedLogs[0];
|
|
$this->assertSame(ActionLog::ACTION_SUSPEND_DOMAIN_EMAIL, $log->getAction());
|
|
$this->assertSame(20, $log->getEntityId());
|
|
$this->assertSame('DomainEmail', $log->getEntityType());
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// suspendCustomer — multiple websites and domain emails
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testSuspendCustomerSuspendsMultipleWebsitesAndEmails(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
|
|
$customer->method('setState');
|
|
|
|
$website1 = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website1->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
|
|
$website2 = $this->makeWebsite(Website::STATE_OPEN);
|
|
$website2->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
|
|
|
|
$domain = new Domain($this->createStub(Customer::class), 'example.com');
|
|
$domainEmail1 = $this->makeDomainEmail('active');
|
|
$domainEmail1->expects($this->once())->method('setState')->with('suspended');
|
|
$domainEmail2 = $this->makeDomainEmail('active');
|
|
$domainEmail2->expects($this->once())->method('setState')->with('suspended');
|
|
|
|
$websiteRepo = $this->makeRepo([$website1, $website2]);
|
|
$domainRepo = $this->makeRepo([$domain]);
|
|
$domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
DomainEmail::class => $domainEmailRepo,
|
|
]);
|
|
$em->method('persist');
|
|
$em->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->suspendCustomer($customer, 'Test multi');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// unsuspendCustomer — multiple websites and domain emails
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
public function testUnsuspendCustomerUnsuspendsMultipleWebsitesAndEmails(): void
|
|
{
|
|
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
|
|
$customer->method('setState');
|
|
|
|
$website1 = $this->makeWebsite(Website::STATE_SUSPENDED);
|
|
$website1->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
|
|
$website2 = $this->makeWebsite(Website::STATE_SUSPENDED);
|
|
$website2->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
|
|
|
|
$domain = new Domain($this->createStub(Customer::class), 'example.com');
|
|
$domainEmail1 = $this->makeDomainEmail('suspended');
|
|
$domainEmail1->expects($this->once())->method('setState')->with('active');
|
|
$domainEmail2 = $this->makeDomainEmail('suspended');
|
|
$domainEmail2->expects($this->once())->method('setState')->with('active');
|
|
|
|
$websiteRepo = $this->makeRepo([$website1, $website2]);
|
|
$domainRepo = $this->makeRepo([$domain]);
|
|
$domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);
|
|
|
|
$em = $this->makeEmWithRepos([
|
|
Website::class => $websiteRepo,
|
|
Domain::class => $domainRepo,
|
|
DomainEmail::class => $domainEmailRepo,
|
|
]);
|
|
$em->method('persist');
|
|
$em->method('flush');
|
|
|
|
$service = new ActionService($em, $this->logger);
|
|
$result = $service->unsuspendCustomer($customer, 'Paiement recu');
|
|
|
|
$this->assertTrue($result);
|
|
}
|
|
}
|