From 9e93e34e12506b1d53e5d8b9dd7377617893fe1b Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 4 Jul 2025 18:25:45 +0200 Subject: [PATCH] Add test to cover when visit updates topics are disabled --- .../Mercure/NotifyVisitToMercureTest.php | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php index b362c1a5..b86a2896 100644 --- a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php +++ b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\Mercure; use Doctrine\ORM\EntityManagerInterface; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -24,7 +25,6 @@ use Shlinkio\Shlink\Core\Visit\Model\VisitType; class NotifyVisitToMercureTest extends TestCase { - private NotifyVisitToMercure $listener; private MockObject & PublishingHelperInterface $helper; private MockObject & PublishingUpdatesGeneratorInterface $updatesGenerator; private MockObject & EntityManagerInterface $em; @@ -36,14 +36,6 @@ class NotifyVisitToMercureTest extends TestCase $this->updatesGenerator = $this->createMock(PublishingUpdatesGeneratorInterface::class); $this->em = $this->createMock(EntityManagerInterface::class); $this->logger = $this->createMock(LoggerInterface::class); - - $this->listener = new NotifyVisitToMercure( - $this->helper, - $this->updatesGenerator, - $this->em, - $this->logger, - new RealTimeUpdatesOptions(), - ); } #[Test] @@ -61,11 +53,15 @@ class NotifyVisitToMercureTest extends TestCase $this->updatesGenerator->expects($this->never())->method('newVisitUpdate'); $this->helper->expects($this->never())->method('publishUpdate'); - ($this->listener)(new UrlVisited($visitId)); + $this->listener()(new UrlVisited($visitId)); } #[Test] - public function notificationsAreSentWhenVisitIsFound(): void + #[TestWith([2, ['NEW_SHORT_URL_VISIT', 'NEW_VISIT']])] + #[TestWith([1, ['NEW_VISIT']])] + #[TestWith([1, ['NEW_SHORT_URL_VISIT']])] + #[TestWith([0, []])] + public function notificationsAreSentWhenVisitIsFound(int $publishUpdateCalls, array $enabledTopics): void { $visitId = '123'; $visit = Visit::forValidShortUrl(ShortUrl::createFake(), Visitor::empty()); @@ -74,14 +70,12 @@ class NotifyVisitToMercureTest extends TestCase $this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit); $this->logger->expects($this->never())->method('warning'); $this->logger->expects($this->never())->method('debug'); - $this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with($visit)->willReturn( - $update, - ); + $this->updatesGenerator->method('newShortUrlVisitUpdate')->willReturn($update); $this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate'); - $this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update); - $this->helper->expects($this->exactly(2))->method('publishUpdate')->with($update); + $this->updatesGenerator->method('newVisitUpdate')->willReturn($update); + $this->helper->expects($this->exactly($publishUpdateCalls))->method('publishUpdate')->with($update); - ($this->listener)(new UrlVisited($visitId)); + $this->listener(enabledTopics: $enabledTopics)(new UrlVisited($visitId)); } #[Test] @@ -105,12 +99,15 @@ class NotifyVisitToMercureTest extends TestCase $this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update); $this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e); - ($this->listener)(new UrlVisited($visitId)); + $this->listener()(new UrlVisited($visitId)); } #[Test, DataProvider('provideOrphanVisits')] - public function notificationsAreSentForOrphanVisits(Visit $visit): void - { + public function notificationsAreSentForOrphanVisits( + Visit $visit, + array $enabledTopics, + int $publishUpdateCalls, + ): void { $visitId = '123'; $update = Update::forTopicAndPayload('', []); @@ -118,21 +115,31 @@ class NotifyVisitToMercureTest extends TestCase $this->logger->expects($this->never())->method('warning'); $this->logger->expects($this->never())->method('debug'); $this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate'); - $this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with($visit)->willReturn( - $update, - ); + $this->updatesGenerator->method('newOrphanVisitUpdate')->willReturn($update); $this->updatesGenerator->expects($this->never())->method('newVisitUpdate'); - $this->helper->expects($this->once())->method('publishUpdate')->with($update); + $this->helper->expects($this->exactly($publishUpdateCalls))->method('publishUpdate')->with($update); - ($this->listener)(new UrlVisited($visitId)); + $this->listener(enabledTopics: $enabledTopics)(new UrlVisited($visitId)); } public static function provideOrphanVisits(): iterable { $visitor = Visitor::empty(); - yield VisitType::REGULAR_404->value => [Visit::forRegularNotFound($visitor)]; - yield VisitType::INVALID_SHORT_URL->value => [Visit::forInvalidShortUrl($visitor)]; - yield VisitType::BASE_URL->value => [Visit::forBasePath($visitor)]; + yield VisitType::REGULAR_404->value => [Visit::forRegularNotFound($visitor), ['NEW_ORPHAN_VISIT'], 1]; + yield VisitType::INVALID_SHORT_URL->value => [Visit::forInvalidShortUrl($visitor), ['NEW_ORPHAN_VISIT'], 1]; + yield VisitType::BASE_URL->value => [Visit::forBasePath($visitor), ['NEW_ORPHAN_VISIT'], 1]; + yield VisitType::BASE_URL->value . ' disabled' => [Visit::forBasePath($visitor), [], 0]; + } + + private function listener(array|null $enabledTopics = null): NotifyVisitToMercure + { + return new NotifyVisitToMercure( + $this->helper, + $this->updatesGenerator, + $this->em, + $this->logger, + new RealTimeUpdatesOptions(enabledTopics: $enabledTopics), + ); } }