mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-21 16:38:37 -06:00
Created NotifyVisitToRabbitTest
This commit is contained in:
parent
0bcefda60d
commit
cb1705b6e8
@ -29,7 +29,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
||||
* [#1218](https://github.com/shlinkio/shlink/issues/1218) Updated to symfony/mercure 0.6.
|
||||
* [#1223](https://github.com/shlinkio/shlink/issues/1223) Updated to phpstan 1.0.
|
||||
* Added `domain` field to `DeleteShortUrlException` exception.
|
||||
* [#1001](https://github.com/shlinkio/shlink/issues/1001) Increased required MSI to 83%.
|
||||
|
||||
### Deprecated
|
||||
* [#1260](https://github.com/shlinkio/shlink/issues/1260) Deprecated `USE_HTTPS` env var that was added in previous release, in favor of the new `IS_HTTPS_ENABLED`.
|
||||
|
@ -142,7 +142,7 @@
|
||||
"test:api": "bin/test/run-api-tests.sh",
|
||||
"test:api:ci": "GENERATE_COVERAGE=yes composer test:api",
|
||||
"infect:ci:base": "infection --threads=4 --log-verbosity=default --only-covered --only-covering-test-cases --skip-initial-tests",
|
||||
"infect:ci:unit": "@infect:ci:base --coverage=build/coverage-unit --min-msi=83",
|
||||
"infect:ci:unit": "@infect:ci:base --coverage=build/coverage-unit --min-msi=80",
|
||||
"infect:ci:db": "@infect:ci:base --coverage=build/coverage-db --min-msi=95 --configuration=infection-db.json",
|
||||
"infect:ci:api": "@infect:ci:base --coverage=build/coverage-api --min-msi=80 --configuration=infection-api.json",
|
||||
"infect:ci": "@parallel infect:ci:unit infect:ci:db infect:ci:api",
|
||||
|
@ -38,9 +38,8 @@ class NotifyVisitToRabbit
|
||||
}
|
||||
|
||||
$visitId = $shortUrlLocated->visitId();
|
||||
|
||||
/** @var Visit|null $visit */
|
||||
$visit = $this->em->find(Visit::class, $visitId);
|
||||
|
||||
if ($visit === null) {
|
||||
$this->logger->warning('Tried to notify RabbitMQ for visit with id "{visitId}", but it does not exist.', [
|
||||
'visitId' => $visitId,
|
||||
|
178
module/Core/test/EventDispatcher/NotifyVisitToRabbitTest.php
Normal file
178
module/Core/test/EventDispatcher/NotifyVisitToRabbitTest.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
use PhpAmqpLib\Connection\AMQPStreamConnection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Entity\Visit;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToRabbit;
|
||||
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
|
||||
use Shlinkio\Shlink\Core\Model\Visitor;
|
||||
use Shlinkio\Shlink\Core\Visit\Transformer\OrphanVisitDataTransformer;
|
||||
use Throwable;
|
||||
|
||||
use function count;
|
||||
use function Functional\contains;
|
||||
|
||||
class NotifyVisitToRabbitTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private NotifyVisitToRabbit $listener;
|
||||
private ObjectProphecy $connection;
|
||||
private ObjectProphecy $em;
|
||||
private ObjectProphecy $logger;
|
||||
private ObjectProphecy $orphanVisitTransformer;
|
||||
private ObjectProphecy $channel;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->channel = $this->prophesize(AMQPChannel::class);
|
||||
|
||||
$this->connection = $this->prophesize(AMQPStreamConnection::class);
|
||||
$this->connection->isConnected()->willReturn(false);
|
||||
$this->connection->channel()->willReturn($this->channel->reveal());
|
||||
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
|
||||
$this->listener = new NotifyVisitToRabbit(
|
||||
$this->connection->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
new OrphanVisitDataTransformer(),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function doesNothingWhenTheFeatureIsNotEnabled(): void
|
||||
{
|
||||
$listener = new NotifyVisitToRabbit(
|
||||
$this->connection->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
new OrphanVisitDataTransformer(),
|
||||
false,
|
||||
);
|
||||
|
||||
$listener(new VisitLocated('123'));
|
||||
|
||||
$this->em->find(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->logger->debug(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->connection->isConnected()->shouldNotHaveBeenCalled();
|
||||
$this->connection->close()->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
||||
{
|
||||
$visitId = '123';
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn(null);
|
||||
$logWarning = $this->logger->warning(
|
||||
'Tried to notify RabbitMQ for visit with id "{visitId}", but it does not exist.',
|
||||
['visitId' => $visitId],
|
||||
);
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldHaveBeenCalledOnce();
|
||||
$this->logger->debug(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->connection->isConnected()->shouldNotHaveBeenCalled();
|
||||
$this->connection->close()->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideVisits
|
||||
*/
|
||||
public function expectedChannelsAreNotifiedBasedOnTheVisitType(Visit $visit, array $expectedChannels): void
|
||||
{
|
||||
$visitId = '123';
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
|
||||
$argumentWithExpectedChannel = Argument::that(fn (string $channel) => contains($expectedChannels, $channel));
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$this->channel->exchange_declare($argumentWithExpectedChannel, Argument::cetera())->shouldHaveBeenCalledTimes(
|
||||
count($expectedChannels),
|
||||
);
|
||||
$this->channel->queue_declare($argumentWithExpectedChannel, Argument::cetera())->shouldHaveBeenCalledTimes(
|
||||
count($expectedChannels),
|
||||
);
|
||||
$this->channel->queue_bind(
|
||||
$argumentWithExpectedChannel,
|
||||
$argumentWithExpectedChannel,
|
||||
)->shouldHaveBeenCalledTimes(count($expectedChannels));
|
||||
$this->channel->basic_publish(Argument::any(), $argumentWithExpectedChannel)->shouldHaveBeenCalledTimes(
|
||||
count($expectedChannels),
|
||||
);
|
||||
$this->channel->close()->shouldHaveBeenCalledOnce();
|
||||
$this->connection->reconnect()->shouldHaveBeenCalledOnce();
|
||||
$this->connection->close()->shouldHaveBeenCalledOnce();
|
||||
$this->logger->debug(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function provideVisits(): iterable
|
||||
{
|
||||
$visitor = Visitor::emptyInstance();
|
||||
|
||||
yield 'orphan visit' => [Visit::forBasePath($visitor), ['https://shlink.io/new-orphan-visit']];
|
||||
yield 'non-orphan visit' => [
|
||||
Visit::forValidShortUrl(
|
||||
ShortUrl::fromMeta(ShortUrlMeta::fromRawData([
|
||||
'longUrl' => 'foo',
|
||||
'customSlug' => 'bar',
|
||||
])),
|
||||
$visitor,
|
||||
),
|
||||
['https://shlink.io/new-visit', 'https://shlink.io/new-visit/bar'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideExceptions
|
||||
*/
|
||||
public function printsDebugMessageInCaseOfError(Throwable $e): void
|
||||
{
|
||||
$visitId = '123';
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
||||
$channel = $this->connection->channel()->willThrow($e);
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$this->logger->debug(
|
||||
'Error while trying to notify RabbitMQ with new visit. {e}',
|
||||
['e' => $e],
|
||||
)->shouldHaveBeenCalledOnce();
|
||||
$this->connection->close()->shouldHaveBeenCalledOnce();
|
||||
$this->connection->reconnect()->shouldHaveBeenCalledOnce();
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$channel->shouldHaveBeenCalledOnce();
|
||||
$this->channel->close()->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function provideExceptions(): iterable
|
||||
{
|
||||
yield [new RuntimeException('RuntimeException Error')];
|
||||
yield [new Exception('Exception Error')];
|
||||
yield [new DomainException('DomainException Error')];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user