NotifyVisitToMercureTest::setUp()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 12
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
use PHPUnit\Framework\TestCase;
9
use Prophecy\Argument;
10
use Prophecy\PhpUnit\ProphecyTrait;
11
use Prophecy\Prophecy\ObjectProphecy;
12
use Psr\Log\LoggerInterface;
13
use RuntimeException;
14
use Shlinkio\Shlink\Core\Entity\ShortUrl;
15
use Shlinkio\Shlink\Core\Entity\Visit;
16
use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToMercure;
17
use Shlinkio\Shlink\Core\EventDispatcher\VisitLocated;
18
use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGeneratorInterface;
19
use Shlinkio\Shlink\Core\Model\Visitor;
20
use Symfony\Component\Mercure\PublisherInterface;
21
use Symfony\Component\Mercure\Update;
22
23
class NotifyVisitToMercureTest extends TestCase
24
{
25
    use ProphecyTrait;
26
27
    private NotifyVisitToMercure $listener;
28
    private ObjectProphecy $publisher;
29
    private ObjectProphecy $updatesGenerator;
30
    private ObjectProphecy $em;
31
    private ObjectProphecy $logger;
32
33
    public function setUp(): void
34
    {
35
        $this->publisher = $this->prophesize(PublisherInterface::class);
36
        $this->updatesGenerator = $this->prophesize(MercureUpdatesGeneratorInterface::class);
37
        $this->em = $this->prophesize(EntityManagerInterface::class);
38
        $this->logger = $this->prophesize(LoggerInterface::class);
39
40
        $this->listener = new NotifyVisitToMercure(
41
            $this->publisher->reveal(),
42
            $this->updatesGenerator->reveal(),
43
            $this->em->reveal(),
44
            $this->logger->reveal(),
45
        );
46
    }
47
48
    /** @test */
49
    public function notificationsAreNotSentWhenVisitCannotBeFound(): void
50
    {
51
        $visitId = '123';
52
        $findVisit = $this->em->find(Visit::class, $visitId)->willReturn(null);
53
        $logWarning = $this->logger->warning(
54
            'Tried to notify mercure for visit with id "{visitId}", but it does not exist.',
55
            ['visitId' => $visitId],
56
        );
57
        $logDebug = $this->logger->debug(Argument::cetera());
58
        $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate(
59
            Argument::type(Visit::class),
60
        )->willReturn(new Update('', ''));
61
        $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate(Argument::type(Visit::class))->willReturn(
62
            new Update('', ''),
63
        );
64
        $publish = $this->publisher->__invoke(Argument::type(Update::class));
65
66
        ($this->listener)(new VisitLocated($visitId));
67
68
        $findVisit->shouldHaveBeenCalledOnce();
69
        $logWarning->shouldHaveBeenCalledOnce();
70
        $logDebug->shouldNotHaveBeenCalled();
71
        $buildNewShortUrlVisitUpdate->shouldNotHaveBeenCalled();
72
        $buildNewVisitUpdate->shouldNotHaveBeenCalled();
73
        $publish->shouldNotHaveBeenCalled();
74
    }
75
76
    /** @test */
77
    public function notificationsAreSentWhenVisitIsFound(): void
78
    {
79
        $visitId = '123';
80
        $visit = new Visit(new ShortUrl(''), Visitor::emptyInstance());
81
        $update = new Update('', '');
82
83
        $findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
84
        $logWarning = $this->logger->warning(Argument::cetera());
85
        $logDebug = $this->logger->debug(Argument::cetera());
86
        $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update);
87
        $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update);
88
        $publish = $this->publisher->__invoke($update);
89
90
        ($this->listener)(new VisitLocated($visitId));
91
92
        $findVisit->shouldHaveBeenCalledOnce();
93
        $logWarning->shouldNotHaveBeenCalled();
94
        $logDebug->shouldNotHaveBeenCalled();
95
        $buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce();
96
        $buildNewVisitUpdate->shouldHaveBeenCalledOnce();
97
        $publish->shouldHaveBeenCalledTimes(2);
98
    }
99
100
    /** @test */
101
    public function debugIsLoggedWhenExceptionIsThrown(): void
102
    {
103
        $visitId = '123';
104
        $visit = new Visit(new ShortUrl(''), Visitor::emptyInstance());
105
        $update = new Update('', '');
106
        $e = new RuntimeException('Error');
107
108
        $findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
109
        $logWarning = $this->logger->warning(Argument::cetera());
110
        $logDebug = $this->logger->debug('Error while trying to notify mercure hub with new visit. {e}', [
111
            'e' => $e,
112
        ]);
113
        $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update);
114
        $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update);
115
        $publish = $this->publisher->__invoke($update)->willThrow($e);
116
117
        ($this->listener)(new VisitLocated($visitId));
118
119
        $findVisit->shouldHaveBeenCalledOnce();
120
        $logWarning->shouldNotHaveBeenCalled();
121
        $logDebug->shouldHaveBeenCalledOnce();
122
        $buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce();
123
        $buildNewVisitUpdate->shouldNotHaveBeenCalled();
124
        $publish->shouldHaveBeenCalledOnce();
125
    }
126
}
127