em = $this->createStub(EntityManagerInterface::class); $this->mailer = $this->createStub(MailerService::class); $this->twig = $this->createStub(Environment::class); $this->logger = $this->createStub(LoggerInterface::class); } private function makeCommand(): CheckNddCommand { return new CheckNddCommand( $this->em, $this->mailer, $this->twig, $this->logger, ); } private function execute(?CheckNddCommand $command = null): CommandTester { $tester = new CommandTester($command ?? $this->makeCommand()); $tester->execute([]); return $tester; } /** * Sets up the QueryBuilder chain on $this->em to return the given domains. */ private function mockQueryReturning(array $domains): void { $query = $this->createStub(Query::class); $query->method('getResult')->willReturn($domains); $qb = $this->createStub(QueryBuilder::class); $qb->method('select')->willReturnSelf(); $qb->method('from')->willReturnSelf(); $qb->method('where')->willReturnSelf(); $qb->method('andWhere')->willReturnSelf(); $qb->method('orderBy')->willReturnSelf(); $qb->method('setParameter')->willReturnSelf(); $qb->method('getQuery')->willReturn($query); $this->em->method('createQueryBuilder')->willReturn($qb); } private function makeDomain(string $fqdn, \DateTimeImmutable $expiredAt, ?string $email = 'client@example.com'): Domain { $customer = $this->createStub(Customer::class); $customer->method('getFullName')->willReturn('John Doe'); $customer->method('getEmail')->willReturn($email); $domain = $this->createStub(Domain::class); $domain->method('getFqdn')->willReturn($fqdn); $domain->method('getRegistrar')->willReturn('OVH'); $domain->method('getCustomer')->willReturn($customer); $domain->method('getExpiredAt')->willReturn($expiredAt); return $domain; } // ------------------------------------------------------------------ // No expiring domains → SUCCESS + email sent with empty subject line // ------------------------------------------------------------------ public function testNoExpiringDomains(): void { $this->mockQueryReturning([]); $this->twig->method('render')->willReturn('empty'); $mailer = $this->createMock(MailerService::class); $mailer->expects($this->once()) ->method('sendEmail') ->with( $this->anything(), $this->stringContains('Aucune expiration'), $this->anything(), ); $this->mailer = $mailer; $tester = $this->execute($this->makeCommand()); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('Aucun nom de domaine en expiration', $tester->getDisplay()); } // ------------------------------------------------------------------ // Multiple domains: some not yet expired (positive daysLeft), // some already expired (negative daysLeft) → SUCCESS + count in subject // ------------------------------------------------------------------ public function testMultipleDomainsWithMixedExpiry(): void { $now = new \DateTimeImmutable(); $soonExpiring = $this->makeDomain('example.fr', $now->modify('+10 days')); $alreadyExpired = $this->makeDomain('expired.fr', $now->modify('-5 days')); $this->mockQueryReturning([$soonExpiring, $alreadyExpired]); $this->twig->method('render')->willReturn('domains'); $mailer = $this->createMock(MailerService::class); $mailer->expects($this->once()) ->method('sendEmail') ->with( $this->anything(), $this->stringContains('2 expiration'), $this->anything(), ); $this->mailer = $mailer; $tester = $this->execute($this->makeCommand()); $this->assertSame(0, $tester->getStatusCode()); $this->assertStringContainsString('2 domaine(s) en expiration', $tester->getDisplay()); } // ------------------------------------------------------------------ // Email send throws → FAILURE + error logged // ------------------------------------------------------------------ public function testEmailSendThrowsReturnsFailure(): void { $this->mockQueryReturning([]); $this->twig->method('render')->willReturn('ok'); $mailer = $this->createStub(MailerService::class); $mailer->method('sendEmail')->willThrowException(new \RuntimeException('SMTP down')); $this->mailer = $mailer; $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once()) ->method('error') ->with($this->stringContains('SMTP down')); $this->logger = $logger; $tester = $this->execute($this->makeCommand()); $this->assertSame(1, $tester->getStatusCode()); $this->assertStringContainsString('Erreur envoi mail', $tester->getDisplay()); } // ------------------------------------------------------------------ // Domain with null customer email → covers `$customer->getEmail() ?? '-'` // ------------------------------------------------------------------ public function testDomainWithNullCustomerEmail(): void { $now = new \DateTimeImmutable(); $domain = $this->makeDomain('null-email.fr', $now->modify('+20 days'), null); $this->mockQueryReturning([$domain]); $this->twig->method('render')->willReturn('one'); $mailer = $this->createStub(MailerService::class); $this->mailer = $mailer; $tester = $this->execute($this->makeCommand()); $this->assertSame(0, $tester->getStatusCode()); // The io->text line uses `?? '-'` — make sure '-' appears in output $this->assertStringContainsString('-', $tester->getDisplay()); } }