mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-18 16:29:56 +03:00
Merge pull request #1582 from acelaya-forks/feature/phpunit-mocks
Feature/phpunit mocks
This commit is contained in:
commit
983e3c9eaa
8 changed files with 313 additions and 392 deletions
|
@ -4,23 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Shlinkio\Shlink\Common\Doctrine\ReopeningEntityManagerInterface;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\CloseDbConnectionEventListenerDelegator;
|
||||
|
||||
class CloseDbConnectionEventListenerDelegatorTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private CloseDbConnectionEventListenerDelegator $delegator;
|
||||
private ObjectProphecy $container;
|
||||
private MockObject $container;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->container = $this->prophesize(ContainerInterface::class);
|
||||
$this->container = $this->createMock(ContainerInterface::class);
|
||||
$this->delegator = new CloseDbConnectionEventListenerDelegator();
|
||||
}
|
||||
|
||||
|
@ -35,12 +32,12 @@ class CloseDbConnectionEventListenerDelegatorTest extends TestCase
|
|||
};
|
||||
};
|
||||
|
||||
$em = $this->prophesize(ReopeningEntityManagerInterface::class);
|
||||
$getEm = $this->container->get('em')->willReturn($em->reveal());
|
||||
$this->container->expects($this->once())->method('get')->with($this->equalTo('em'))->willReturn(
|
||||
$this->createMock(ReopeningEntityManagerInterface::class),
|
||||
);
|
||||
|
||||
($this->delegator)($this->container->reveal(), '', $callback);
|
||||
($this->delegator)($this->container, '', $callback);
|
||||
|
||||
self::assertTrue($callbackInvoked);
|
||||
$getEm->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,8 @@ declare(strict_types=1);
|
|||
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use RuntimeException;
|
||||
use Shlinkio\Shlink\Common\Doctrine\ReopeningEntityManagerInterface;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\CloseDbConnectionEventListener;
|
||||
|
@ -16,13 +15,11 @@ use Throwable;
|
|||
|
||||
class CloseDbConnectionEventListenerTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private ObjectProphecy $em;
|
||||
private MockObject $em;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->em = $this->prophesize(ReopeningEntityManagerInterface::class);
|
||||
$this->em = $this->createMock(ReopeningEntityManagerInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,16 +28,14 @@ class CloseDbConnectionEventListenerTest extends TestCase
|
|||
*/
|
||||
public function connectionIsOpenedBeforeAndClosedAfter(callable $wrapped, bool &$wrappedWasCalled): void
|
||||
{
|
||||
$conn = $this->prophesize(Connection::class);
|
||||
$close = $conn->close()->will(function (): void {
|
||||
});
|
||||
$getConn = $this->em->getConnection()->willReturn($conn->reveal());
|
||||
$close = $this->em->close()->will(function (): void {
|
||||
});
|
||||
$open = $this->em->open()->will(function (): void {
|
||||
});
|
||||
$conn = $this->createMock(Connection::class);
|
||||
$conn->expects($this->once())->method('close');
|
||||
|
||||
$eventListener = new CloseDbConnectionEventListener($this->em->reveal(), $wrapped);
|
||||
$this->em->expects($this->once())->method('getConnection')->willReturn($conn);
|
||||
$this->em->expects($this->once())->method('close');
|
||||
$this->em->expects($this->once())->method('open');
|
||||
|
||||
$eventListener = new CloseDbConnectionEventListener($this->em, $wrapped);
|
||||
|
||||
try {
|
||||
($eventListener)(new stdClass());
|
||||
|
@ -49,25 +44,21 @@ class CloseDbConnectionEventListenerTest extends TestCase
|
|||
}
|
||||
|
||||
self::assertTrue($wrappedWasCalled);
|
||||
$close->shouldHaveBeenCalledOnce();
|
||||
$getConn->shouldHaveBeenCalledOnce();
|
||||
$close->shouldHaveBeenCalledOnce();
|
||||
$open->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideWrapped(): iterable
|
||||
{
|
||||
yield 'does not throw exception' => (function (): array {
|
||||
yield 'does not throw exception' => (static function (): array {
|
||||
$wrappedWasCalled = false;
|
||||
$wrapped = function () use (&$wrappedWasCalled): void {
|
||||
$wrapped = static function () use (&$wrappedWasCalled): void {
|
||||
$wrappedWasCalled = true;
|
||||
};
|
||||
|
||||
return [$wrapped, &$wrappedWasCalled];
|
||||
})();
|
||||
yield 'throws exception' => (function (): array {
|
||||
yield 'throws exception' => (static function (): array {
|
||||
$wrappedWasCalled = false;
|
||||
$wrapped = function () use (&$wrappedWasCalled): void {
|
||||
$wrapped = static function () use (&$wrappedWasCalled): void {
|
||||
$wrappedWasCalled = true;
|
||||
throw new RuntimeException('Some error');
|
||||
};
|
||||
|
|
|
@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\Event\GeoLiteDbCreated;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\LocateUnlocatedVisits;
|
||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||
|
@ -17,25 +16,23 @@ use Shlinkio\Shlink\IpGeolocation\Model\Location;
|
|||
|
||||
class LocateUnlocatedVisitsTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private LocateUnlocatedVisits $listener;
|
||||
private ObjectProphecy $locator;
|
||||
private ObjectProphecy $visitToLocation;
|
||||
private MockObject $locator;
|
||||
private MockObject $visitToLocation;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->locator = $this->prophesize(VisitLocatorInterface::class);
|
||||
$this->visitToLocation = $this->prophesize(VisitToLocationHelperInterface::class);
|
||||
$this->locator = $this->createMock(VisitLocatorInterface::class);
|
||||
$this->visitToLocation = $this->createMock(VisitToLocationHelperInterface::class);
|
||||
|
||||
$this->listener = new LocateUnlocatedVisits($this->locator->reveal(), $this->visitToLocation->reveal());
|
||||
$this->listener = new LocateUnlocatedVisits($this->locator, $this->visitToLocation);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function locatorIsCalledWhenInvoked(): void
|
||||
{
|
||||
$this->locator->expects($this->once())->method('locateUnlocatedVisits')->with($this->equalTo($this->listener));
|
||||
($this->listener)(new GeoLiteDbCreated());
|
||||
$this->locator->locateUnlocatedVisits($this->listener)->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -44,11 +41,12 @@ class LocateUnlocatedVisitsTest extends TestCase
|
|||
$visit = Visit::forBasePath(Visitor::emptyInstance());
|
||||
$location = Location::emptyInstance();
|
||||
|
||||
$resolve = $this->visitToLocation->resolveVisitLocation($visit)->willReturn($location);
|
||||
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->with(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($location);
|
||||
|
||||
$result = $this->listener->geolocateVisit($visit);
|
||||
|
||||
self::assertSame($location, $result);
|
||||
$resolve->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
|||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use OutOfRangeException;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Common\Util\IpAddress;
|
||||
|
@ -27,31 +25,27 @@ use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;
|
|||
|
||||
class LocateVisitTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private LocateVisit $locateVisit;
|
||||
private ObjectProphecy $ipLocationResolver;
|
||||
private ObjectProphecy $em;
|
||||
private ObjectProphecy $logger;
|
||||
private ObjectProphecy $dbUpdater;
|
||||
private ObjectProphecy $eventDispatcher;
|
||||
private MockObject $ipLocationResolver;
|
||||
private MockObject $em;
|
||||
private MockObject $logger;
|
||||
private MockObject $eventDispatcher;
|
||||
private MockObject $dbUpdater;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->ipLocationResolver = $this->prophesize(IpLocationResolverInterface::class);
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
$this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
|
||||
$this->dbUpdater = $this->prophesize(DbUpdaterInterface::class);
|
||||
$this->dbUpdater->databaseFileExists()->willReturn(true);
|
||||
$this->ipLocationResolver = $this->createMock(IpLocationResolverInterface::class);
|
||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->dbUpdater = $this->createMock(DbUpdaterInterface::class);
|
||||
|
||||
$this->locateVisit = new LocateVisit(
|
||||
$this->ipLocationResolver->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
$this->dbUpdater->reveal(),
|
||||
$this->eventDispatcher->reveal(),
|
||||
$this->ipLocationResolver,
|
||||
$this->em,
|
||||
$this->logger,
|
||||
$this->dbUpdater,
|
||||
$this->eventDispatcher,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -59,97 +53,91 @@ class LocateVisitTest extends TestCase
|
|||
public function invalidVisitLogsWarning(): void
|
||||
{
|
||||
$event = new UrlVisited('123');
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn(null);
|
||||
$logWarning = $this->logger->warning('Tried to locate visit with id "{visitId}", but it does not exist.', [
|
||||
'visitId' => 123,
|
||||
]);
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn(null);
|
||||
$this->em->expects($this->never())->method('flush');
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to locate visit with id "{visitId}", but it does not exist.'),
|
||||
$this->equalTo(['visitId' => 123]),
|
||||
);
|
||||
$this->eventDispatcher->expects($this->never())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||
$this->ipLocationResolver->resolveIpLocation(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$logWarning->shouldHaveBeenCalled();
|
||||
$dispatch->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function nonExistingGeoLiteDbLogsWarning(): void
|
||||
{
|
||||
$event = new UrlVisited('123');
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn(
|
||||
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
||||
$this->em->expects($this->never())->method('flush');
|
||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(false);
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.'),
|
||||
$this->equalTo(['visitId' => 123]),
|
||||
);
|
||||
$dbExists = $this->dbUpdater->databaseFileExists()->willReturn(false);
|
||||
$logWarning = $this->logger->warning(
|
||||
'Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.',
|
||||
['visitId' => 123],
|
||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$dbExists->shouldHaveBeenCalledOnce();
|
||||
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||
$this->ipLocationResolver->resolveIpLocation(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$logWarning->shouldHaveBeenCalled();
|
||||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function invalidAddressLogsWarning(): void
|
||||
{
|
||||
$event = new UrlVisited('123');
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn(
|
||||
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
||||
$this->em->expects($this->never())->method('flush');
|
||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||
$this->ipLocationResolver->expects(
|
||||
$this->once(),
|
||||
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(WrongIpException::fromIpAddress(''));
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}'),
|
||||
$this->isType('array'),
|
||||
);
|
||||
$resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow(
|
||||
WrongIpException::class,
|
||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$logWarning = $this->logger->warning(
|
||||
'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}',
|
||||
Argument::type('array'),
|
||||
);
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$resolveLocation->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldHaveBeenCalled();
|
||||
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function unhandledExceptionLogsError(): void
|
||||
{
|
||||
$event = new UrlVisited('123');
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn(
|
||||
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
||||
$this->em->expects($this->never())->method('flush');
|
||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||
$this->ipLocationResolver->expects(
|
||||
$this->once(),
|
||||
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(new OutOfRangeException());
|
||||
$this->logger->expects($this->once())->method('error')->with(
|
||||
$this->equalTo('An unexpected error occurred while trying to locate visit with id "{visitId}". {e}'),
|
||||
$this->isType('array'),
|
||||
);
|
||||
$resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow(
|
||||
OutOfRangeException::class,
|
||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$logError = $this->logger->error(
|
||||
'An unexpected error occurred while trying to locate visit with id "{visitId}". {e}',
|
||||
Argument::type('array'),
|
||||
);
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$resolveLocation->shouldHaveBeenCalledOnce();
|
||||
$logError->shouldHaveBeenCalled();
|
||||
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,21 +147,22 @@ class LocateVisitTest extends TestCase
|
|||
public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void
|
||||
{
|
||||
$event = new UrlVisited('123');
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||
$flush = $this->em->flush()->will(function (): void {
|
||||
});
|
||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation(Argument::any());
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn($visit);
|
||||
$this->em->expects($this->once())->method('flush');
|
||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||
|
||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation(Location::emptyInstance()));
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$flush->shouldHaveBeenCalledOnce();
|
||||
$resolveIp->shouldNotHaveBeenCalled();
|
||||
$this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideNonLocatableVisits(): iterable
|
||||
|
@ -195,21 +184,24 @@ class LocateVisitTest extends TestCase
|
|||
$location = new Location('', '', '', '', 0.0, 0.0, '');
|
||||
$event = UrlVisited::withOriginalIpAddress('123', $originalIpAddress);
|
||||
|
||||
$findVisit = $this->em->find(Visit::class, '123')->willReturn($visit);
|
||||
$flush = $this->em->flush()->will(function (): void {
|
||||
});
|
||||
$resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location);
|
||||
$dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void {
|
||||
});
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn($visit);
|
||||
$this->em->expects($this->once())->method('flush');
|
||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||
$this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with(
|
||||
$this->equalTo($ipAddr),
|
||||
)->willReturn($location);
|
||||
|
||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
||||
$this->equalTo(new VisitLocated('123')),
|
||||
);
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
|
||||
($this->locateVisit)($event);
|
||||
|
||||
self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation($location));
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$flush->shouldHaveBeenCalledOnce();
|
||||
$resolveIp->shouldHaveBeenCalledOnce();
|
||||
$this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$dispatch->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideIpAddresses(): iterable
|
||||
|
|
|
@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\Mercure;
|
|||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Common\UpdatePublishing\PublishingHelperInterface;
|
||||
use Shlinkio\Shlink\Common\UpdatePublishing\Update;
|
||||
|
@ -20,44 +18,43 @@ use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
|||
|
||||
class NotifyNewShortUrlToMercureTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private NotifyNewShortUrlToMercure $listener;
|
||||
private ObjectProphecy $helper;
|
||||
private ObjectProphecy $updatesGenerator;
|
||||
private ObjectProphecy $em;
|
||||
private ObjectProphecy $logger;
|
||||
private MockObject $helper;
|
||||
private MockObject $updatesGenerator;
|
||||
private MockObject $em;
|
||||
private MockObject $logger;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->helper = $this->prophesize(PublishingHelperInterface::class);
|
||||
$this->updatesGenerator = $this->prophesize(PublishingUpdatesGeneratorInterface::class);
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
$this->helper = $this->createMock(PublishingHelperInterface::class);
|
||||
$this->updatesGenerator = $this->createMock(PublishingUpdatesGeneratorInterface::class);
|
||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
$this->listener = new NotifyNewShortUrlToMercure(
|
||||
$this->helper->reveal(),
|
||||
$this->updatesGenerator->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
$this->helper,
|
||||
$this->updatesGenerator,
|
||||
$this->em,
|
||||
$this->logger,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function messageIsLoggedWhenShortUrlIsNotFound(): void
|
||||
{
|
||||
$find = $this->em->find(ShortUrl::class, '123')->willReturn(null);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(ShortUrl::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn(null);
|
||||
$this->helper->expects($this->never())->method('publishUpdate');
|
||||
$this->updatesGenerator->expects($this->never())->method('newShortUrlUpdate');
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.'),
|
||||
$this->equalTo(['shortUrlId' => '123', 'name' => 'Mercure']),
|
||||
);
|
||||
$this->logger->expects($this->never())->method('debug');
|
||||
|
||||
($this->listener)(new ShortUrlCreated('123'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$this->logger->warning(
|
||||
'Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.',
|
||||
['shortUrlId' => '123', 'name' => 'Mercure'],
|
||||
)->shouldHaveBeenCalledOnce();
|
||||
$this->helper->publishUpdate(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->updatesGenerator->newShortUrlUpdate(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->logger->debug(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -66,16 +63,18 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
|||
$shortUrl = ShortUrl::withLongUrl('');
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
|
||||
$find = $this->em->find(ShortUrl::class, '123')->willReturn($shortUrl);
|
||||
$newUpdate = $this->updatesGenerator->newShortUrlUpdate($shortUrl)->willReturn($update);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(ShortUrl::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn($shortUrl);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||
$this->equalTo($shortUrl),
|
||||
)->willReturn($update);
|
||||
$this->helper->expects($this->once())->method('publishUpdate')->with($this->equalTo($update));
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
$this->logger->expects($this->never())->method('debug');
|
||||
|
||||
($this->listener)(new ShortUrlCreated('123'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$newUpdate->shouldHaveBeenCalledOnce();
|
||||
$this->helper->publishUpdate($update)->shouldHaveBeenCalledOnce();
|
||||
$this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->logger->debug(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -85,19 +84,22 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
|||
$update = Update::forTopicAndPayload('', []);
|
||||
$e = new Exception('Error');
|
||||
|
||||
$find = $this->em->find(ShortUrl::class, '123')->willReturn($shortUrl);
|
||||
$newUpdate = $this->updatesGenerator->newShortUrlUpdate($shortUrl)->willReturn($update);
|
||||
$publish = $this->helper->publishUpdate($update)->willThrow($e);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(ShortUrl::class),
|
||||
$this->equalTo('123'),
|
||||
)->willReturn($shortUrl);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||
$this->equalTo($shortUrl),
|
||||
)->willReturn($update);
|
||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
||||
$this->equalTo($update),
|
||||
)->willThrowException($e);
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
$this->logger->expects($this->once())->method('debug')->with(
|
||||
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
|
||||
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
|
||||
);
|
||||
|
||||
($this->listener)(new ShortUrlCreated('123'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$newUpdate->shouldHaveBeenCalledOnce();
|
||||
$publish->shouldHaveBeenCalledOnce();
|
||||
$this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->logger->debug(
|
||||
'Error while trying to notify {name} with new short URL. {e}',
|
||||
['e' => $e, 'name' => 'Mercure'],
|
||||
)->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,8 @@ declare(strict_types=1);
|
|||
namespace ShlinkioTest\Shlink\Core\EventDispatcher\Mercure;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Shlinkio\Shlink\Common\UpdatePublishing\PublishingHelperInterface;
|
||||
|
@ -23,55 +21,41 @@ use Shlinkio\Shlink\Core\Visit\Model\VisitType;
|
|||
|
||||
class NotifyVisitToMercureTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private NotifyVisitToMercure $listener;
|
||||
private ObjectProphecy $helper;
|
||||
private ObjectProphecy $updatesGenerator;
|
||||
private ObjectProphecy $em;
|
||||
private ObjectProphecy $logger;
|
||||
private MockObject $helper;
|
||||
private MockObject $updatesGenerator;
|
||||
private MockObject $em;
|
||||
private MockObject $logger;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->helper = $this->prophesize(PublishingHelperInterface::class);
|
||||
$this->updatesGenerator = $this->prophesize(PublishingUpdatesGeneratorInterface::class);
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
$this->helper = $this->createMock(PublishingHelperInterface::class);
|
||||
$this->updatesGenerator = $this->createMock(PublishingUpdatesGeneratorInterface::class);
|
||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
$this->listener = new NotifyVisitToMercure(
|
||||
$this->helper->reveal(),
|
||||
$this->updatesGenerator->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
);
|
||||
$this->listener = new NotifyVisitToMercure($this->helper, $this->updatesGenerator, $this->em, $this->logger);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
||||
{
|
||||
$visitId = '123';
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn(null);
|
||||
$logWarning = $this->logger->warning(
|
||||
'Tried to notify {name} for visit with id "{visitId}", but it does not exist.',
|
||||
['visitId' => $visitId, 'name' => 'Mercure'],
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo($visitId),
|
||||
)->willReturn(null);
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to notify {name} for visit with id "{visitId}", but it does not exist.'),
|
||||
$this->equalTo(['visitId' => $visitId, 'name' => 'Mercure']),
|
||||
);
|
||||
$logDebug = $this->logger->debug(Argument::cetera());
|
||||
$buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate(
|
||||
Argument::type(Visit::class),
|
||||
);
|
||||
$buildNewOrphanVisitUpdate = $this->updatesGenerator->newOrphanVisitUpdate(Argument::type(Visit::class));
|
||||
$buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate(Argument::type(Visit::class));
|
||||
$publish = $this->helper->publishUpdate(Argument::type(Update::class));
|
||||
$this->logger->expects($this->never())->method('debug');
|
||||
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
|
||||
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
||||
$this->updatesGenerator->expects($this->never())->method('newVisitUpdate');
|
||||
$this->helper->expects($this->never())->method('publishUpdate');
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldHaveBeenCalledOnce();
|
||||
$logDebug->shouldNotHaveBeenCalled();
|
||||
$buildNewShortUrlVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$buildNewVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$buildNewOrphanVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$publish->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -81,23 +65,22 @@ class NotifyVisitToMercureTest extends TestCase
|
|||
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance());
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
|
||||
$logWarning = $this->logger->warning(Argument::cetera());
|
||||
$logDebug = $this->logger->debug(Argument::cetera());
|
||||
$buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewOrphanVisitUpdate = $this->updatesGenerator->newOrphanVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update);
|
||||
$publish = $this->helper->publishUpdate($update);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo($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(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($update);
|
||||
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
||||
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($update);
|
||||
$this->helper->expects($this->exactly(2))->method('publishUpdate')->with($this->equalTo($update));
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldNotHaveBeenCalled();
|
||||
$logDebug->shouldNotHaveBeenCalled();
|
||||
$buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce();
|
||||
$buildNewVisitUpdate->shouldHaveBeenCalledOnce();
|
||||
$buildNewOrphanVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$publish->shouldHaveBeenCalledTimes(2);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -108,26 +91,27 @@ class NotifyVisitToMercureTest extends TestCase
|
|||
$update = Update::forTopicAndPayload('', []);
|
||||
$e = new RuntimeException('Error');
|
||||
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
|
||||
$logWarning = $this->logger->warning(Argument::cetera());
|
||||
$logDebug = $this->logger->debug('Error while trying to notify {name} with new visit. {e}', [
|
||||
'e' => $e,
|
||||
'name' => 'Mercure',
|
||||
]);
|
||||
$buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewOrphanVisitUpdate = $this->updatesGenerator->newOrphanVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update);
|
||||
$publish = $this->helper->publishUpdate($update)->willThrow($e);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo($visitId),
|
||||
)->willReturn($visit);
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
$this->logger->expects($this->once())->method('debug')->with(
|
||||
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
|
||||
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
|
||||
);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($update);
|
||||
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
||||
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($update);
|
||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
||||
$this->equalTo($update),
|
||||
)->willThrowException($e);
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldNotHaveBeenCalled();
|
||||
$logDebug->shouldHaveBeenCalledOnce();
|
||||
$buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce();
|
||||
$buildNewVisitUpdate->shouldHaveBeenCalledOnce();
|
||||
$buildNewOrphanVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$publish->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,23 +123,20 @@ class NotifyVisitToMercureTest extends TestCase
|
|||
$visitId = '123';
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
|
||||
$findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit);
|
||||
$logWarning = $this->logger->warning(Argument::cetera());
|
||||
$logDebug = $this->logger->debug(Argument::cetera());
|
||||
$buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewOrphanVisitUpdate = $this->updatesGenerator->newOrphanVisitUpdate($visit)->willReturn($update);
|
||||
$buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update);
|
||||
$publish = $this->helper->publishUpdate($update);
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo($visitId),
|
||||
)->willReturn($visit);
|
||||
$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(
|
||||
$this->equalTo($visit),
|
||||
)->willReturn($update);
|
||||
$this->updatesGenerator->expects($this->never())->method('newVisitUpdate');
|
||||
$this->helper->expects($this->once())->method('publishUpdate')->with($this->equalTo($update));
|
||||
|
||||
($this->listener)(new VisitLocated($visitId));
|
||||
|
||||
$findVisit->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldNotHaveBeenCalled();
|
||||
$logDebug->shouldNotHaveBeenCalled();
|
||||
$buildNewShortUrlVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$buildNewVisitUpdate->shouldNotHaveBeenCalled();
|
||||
$buildNewOrphanVisitUpdate->shouldHaveBeenCalledOnce();
|
||||
$publish->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideOrphanVisits(): iterable
|
||||
|
|
|
@ -12,10 +12,8 @@ use GuzzleHttp\Promise\FulfilledPromise;
|
|||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
|
||||
use Shlinkio\Shlink\Core\EventDispatcher\NotifyVisitToWebHooks;
|
||||
|
@ -32,66 +30,52 @@ use function Functional\contains;
|
|||
|
||||
class NotifyVisitToWebHooksTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private ObjectProphecy $httpClient;
|
||||
private ObjectProphecy $em;
|
||||
private ObjectProphecy $logger;
|
||||
private MockObject $httpClient;
|
||||
private MockObject $em;
|
||||
private MockObject $logger;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->httpClient = $this->prophesize(ClientInterface::class);
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
$this->httpClient = $this->createMock(ClientInterface::class);
|
||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function emptyWebhooksMakeNoFurtherActions(): void
|
||||
{
|
||||
$find = $this->em->find(Visit::class, '1')->willReturn(null);
|
||||
$this->em->expects($this->never())->method('find');
|
||||
|
||||
$this->createListener([])(new VisitLocated('1'));
|
||||
|
||||
$find->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function invalidVisitDoesNotPerformAnyRequest(): void
|
||||
{
|
||||
$find = $this->em->find(Visit::class, '1')->willReturn(null);
|
||||
$requestAsync = $this->httpClient->requestAsync(
|
||||
RequestMethodInterface::METHOD_POST,
|
||||
Argument::type('string'),
|
||||
Argument::type('array'),
|
||||
)->willReturn(new FulfilledPromise(''));
|
||||
$logWarning = $this->logger->warning(
|
||||
'Tried to notify webhooks for visit with id "{visitId}", but it does not exist.',
|
||||
['visitId' => '1'],
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('1'),
|
||||
)->willReturn(null);
|
||||
$this->httpClient->expects($this->never())->method('requestAsync');
|
||||
$this->logger->expects($this->once())->method('warning')->with(
|
||||
$this->equalTo('Tried to notify webhooks for visit with id "{visitId}", but it does not exist.'),
|
||||
$this->equalTo(['visitId' => '1']),
|
||||
);
|
||||
|
||||
$this->createListener(['foo', 'bar'])(new VisitLocated('1'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldHaveBeenCalledOnce();
|
||||
$requestAsync->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function orphanVisitDoesNotPerformAnyRequestWhenDisabled(): void
|
||||
{
|
||||
$find = $this->em->find(Visit::class, '1')->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
||||
$requestAsync = $this->httpClient->requestAsync(
|
||||
RequestMethodInterface::METHOD_POST,
|
||||
Argument::type('string'),
|
||||
Argument::type('array'),
|
||||
)->willReturn(new FulfilledPromise(''));
|
||||
$logWarning = $this->logger->warning(Argument::cetera());
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('1'),
|
||||
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
||||
$this->httpClient->expects($this->never())->method('requestAsync');
|
||||
$this->logger->expects($this->never())->method('warning');
|
||||
|
||||
$this->createListener(['foo', 'bar'], false)(new VisitLocated('1'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$logWarning->shouldNotHaveBeenCalled();
|
||||
$requestAsync->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,16 +87,19 @@ class NotifyVisitToWebHooksTest extends TestCase
|
|||
$webhooks = ['foo', 'invalid', 'bar', 'baz'];
|
||||
$invalidWebhooks = ['invalid', 'baz'];
|
||||
|
||||
$find = $this->em->find(Visit::class, '1')->willReturn($visit);
|
||||
$requestAsync = $this->httpClient->requestAsync(
|
||||
RequestMethodInterface::METHOD_POST,
|
||||
Argument::type('string'),
|
||||
Argument::that(function (array $requestOptions) use ($expectedResponseKeys) {
|
||||
$this->em->expects($this->once())->method('find')->with(
|
||||
$this->equalTo(Visit::class),
|
||||
$this->equalTo('1'),
|
||||
)->willReturn($visit);
|
||||
$this->httpClient->expects($this->exactly(count($webhooks)))->method('requestAsync')->with(
|
||||
$this->equalTo(RequestMethodInterface::METHOD_POST),
|
||||
$this->istype('string'),
|
||||
$this->callback(function (array $requestOptions) use ($expectedResponseKeys) {
|
||||
Assert::assertArrayHasKey(RequestOptions::HEADERS, $requestOptions);
|
||||
Assert::assertArrayHasKey(RequestOptions::JSON, $requestOptions);
|
||||
Assert::assertArrayHasKey(RequestOptions::TIMEOUT, $requestOptions);
|
||||
Assert::assertEquals($requestOptions[RequestOptions::TIMEOUT], 10);
|
||||
Assert::assertEquals($requestOptions[RequestOptions::HEADERS], ['User-Agent' => 'Shlink:v1.2.3']);
|
||||
Assert::assertEquals(10, $requestOptions[RequestOptions::TIMEOUT]);
|
||||
Assert::assertEquals(['User-Agent' => 'Shlink:v1.2.3'], $requestOptions[RequestOptions::HEADERS]);
|
||||
|
||||
$json = $requestOptions[RequestOptions::JSON];
|
||||
Assert::assertCount(count($expectedResponseKeys), $json);
|
||||
|
@ -120,30 +107,24 @@ class NotifyVisitToWebHooksTest extends TestCase
|
|||
Assert::assertArrayHasKey($key, $json);
|
||||
}
|
||||
|
||||
return $requestOptions;
|
||||
return true;
|
||||
}),
|
||||
)->will(function (array $args) use ($invalidWebhooks) {
|
||||
[, $webhook] = $args;
|
||||
)->willReturnCallback(function ($_, $webhook) use ($invalidWebhooks) {
|
||||
$shouldReject = contains($invalidWebhooks, $webhook);
|
||||
|
||||
return $shouldReject ? new RejectedPromise(new Exception('')) : new FulfilledPromise('');
|
||||
});
|
||||
$logWarning = $this->logger->warning(
|
||||
'Failed to notify visit with id "{visitId}" to webhook "{webhook}". {e}',
|
||||
Argument::that(function (array $extra) {
|
||||
$this->logger->expects($this->exactly(count($invalidWebhooks)))->method('warning')->with(
|
||||
$this->equalTo('Failed to notify visit with id "{visitId}" to webhook "{webhook}". {e}'),
|
||||
$this->callback(function (array $extra): bool {
|
||||
Assert::assertArrayHasKey('webhook', $extra);
|
||||
Assert::assertArrayHasKey('visitId', $extra);
|
||||
Assert::assertArrayHasKey('e', $extra);
|
||||
|
||||
return $extra;
|
||||
return true;
|
||||
}),
|
||||
);
|
||||
|
||||
$this->createListener($webhooks)(new VisitLocated('1'));
|
||||
|
||||
$find->shouldHaveBeenCalledOnce();
|
||||
$requestAsync->shouldHaveBeenCalledTimes(count($webhooks));
|
||||
$logWarning->shouldHaveBeenCalledTimes(count($invalidWebhooks));
|
||||
}
|
||||
|
||||
public function provideVisits(): iterable
|
||||
|
@ -158,9 +139,9 @@ class NotifyVisitToWebHooksTest extends TestCase
|
|||
private function createListener(array $webhooks, bool $notifyOrphanVisits = true): NotifyVisitToWebHooks
|
||||
{
|
||||
return new NotifyVisitToWebHooks(
|
||||
$this->httpClient->reveal(),
|
||||
$this->em->reveal(),
|
||||
$this->logger->reveal(),
|
||||
$this->httpClient,
|
||||
$this->em,
|
||||
$this->logger,
|
||||
new WebhookOptions(
|
||||
['webhooks' => $webhooks, 'notify_orphan_visits_to_webhooks' => $notifyOrphanVisits],
|
||||
),
|
||||
|
|
|
@ -4,10 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace ShlinkioTest\Shlink\Core\EventDispatcher;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
|
@ -20,24 +18,18 @@ use function Functional\map;
|
|||
|
||||
class UpdateGeoLiteDbTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private UpdateGeoLiteDb $listener;
|
||||
private ObjectProphecy $dbUpdater;
|
||||
private ObjectProphecy $logger;
|
||||
private ObjectProphecy $eventDispatcher;
|
||||
private MockObject $dbUpdater;
|
||||
private MockObject $logger;
|
||||
private MockObject $eventDispatcher;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->dbUpdater = $this->prophesize(GeolocationDbUpdaterInterface::class);
|
||||
$this->logger = $this->prophesize(LoggerInterface::class);
|
||||
$this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
$this->dbUpdater = $this->createMock(GeolocationDbUpdaterInterface::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
|
||||
$this->listener = new UpdateGeoLiteDb(
|
||||
$this->dbUpdater->reveal(),
|
||||
$this->logger->reveal(),
|
||||
$this->eventDispatcher->reveal(),
|
||||
);
|
||||
$this->listener = new UpdateGeoLiteDb($this->dbUpdater, $this->logger, $this->eventDispatcher);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
@ -45,15 +37,15 @@ class UpdateGeoLiteDbTest extends TestCase
|
|||
{
|
||||
$e = new RuntimeException();
|
||||
|
||||
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willThrow($e);
|
||||
$logError = $this->logger->error('GeoLite2 database download failed. {e}', ['e' => $e]);
|
||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willThrowException($e);
|
||||
$this->logger->expects($this->once())->method('error')->with(
|
||||
$this->equalTo('GeoLite2 database download failed. {e}'),
|
||||
$this->equalTo(['e' => $e]),
|
||||
);
|
||||
$this->logger->expects($this->never())->method('notice');
|
||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||
|
||||
($this->listener)();
|
||||
|
||||
$checkDbUpdate->shouldHaveBeenCalledOnce();
|
||||
$logError->shouldHaveBeenCalledOnce();
|
||||
$this->logger->notice(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,22 +54,17 @@ class UpdateGeoLiteDbTest extends TestCase
|
|||
*/
|
||||
public function noticeMessageIsPrintedWhenFirstCallbackIsInvoked(bool $oldDbExists, string $expectedMessage): void
|
||||
{
|
||||
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will(
|
||||
function (array $args) use ($oldDbExists): GeolocationResult {
|
||||
[$firstCallback] = $args;
|
||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback(
|
||||
function (callable $firstCallback) use ($oldDbExists): GeolocationResult {
|
||||
$firstCallback($oldDbExists);
|
||||
|
||||
return GeolocationResult::DB_IS_UP_TO_DATE;
|
||||
},
|
||||
);
|
||||
$logNotice = $this->logger->notice($expectedMessage);
|
||||
$this->logger->expects($this->once())->method('notice')->with($this->equalTo($expectedMessage));
|
||||
$this->logger->expects($this->never())->method('error');
|
||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||
|
||||
($this->listener)();
|
||||
|
||||
$checkDbUpdate->shouldHaveBeenCalledOnce();
|
||||
$logNotice->shouldHaveBeenCalledOnce();
|
||||
$this->logger->error(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function provideFlags(): iterable
|
||||
|
@ -96,10 +83,8 @@ class UpdateGeoLiteDbTest extends TestCase
|
|||
bool $oldDbExists,
|
||||
?string $expectedMessage,
|
||||
): void {
|
||||
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will(
|
||||
function (array $args) use ($total, $downloaded, $oldDbExists): GeolocationResult {
|
||||
[, $secondCallback] = $args;
|
||||
|
||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback(
|
||||
function ($_, callable $secondCallback) use ($total, $downloaded, $oldDbExists): GeolocationResult {
|
||||
// Invoke several times to ensure the log is printed only once
|
||||
$secondCallback($total, $downloaded, $oldDbExists);
|
||||
$secondCallback($total, $downloaded, $oldDbExists);
|
||||
|
@ -108,18 +93,12 @@ class UpdateGeoLiteDbTest extends TestCase
|
|||
return GeolocationResult::DB_UPDATED;
|
||||
},
|
||||
);
|
||||
$logNotice = $this->logger->notice($expectedMessage ?? Argument::cetera());
|
||||
$logNoticeExpectation = $expectedMessage !== null ? $this->once() : $this->never();
|
||||
$this->logger->expects($logNoticeExpectation)->method('notice')->with($this->equalTo($expectedMessage));
|
||||
$this->logger->expects($this->never())->method('error');
|
||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||
|
||||
($this->listener)();
|
||||
|
||||
if ($expectedMessage !== null) {
|
||||
$logNotice->shouldHaveBeenCalledOnce();
|
||||
} else {
|
||||
$logNotice->shouldNotHaveBeenCalled();
|
||||
}
|
||||
$checkDbUpdate->shouldHaveBeenCalledOnce();
|
||||
$this->logger->error(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function provideDownloaded(): iterable
|
||||
|
@ -142,12 +121,12 @@ class UpdateGeoLiteDbTest extends TestCase
|
|||
GeolocationResult $result,
|
||||
int $expectedDispatches,
|
||||
): void {
|
||||
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->willReturn($result);
|
||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturn($result);
|
||||
$this->eventDispatcher->expects($this->exactly($expectedDispatches))->method('dispatch')->with(
|
||||
$this->equalTo(new GeoLiteDbCreated()),
|
||||
);
|
||||
|
||||
($this->listener)();
|
||||
|
||||
$checkDbUpdate->shouldHaveBeenCalledOnce();
|
||||
$this->eventDispatcher->dispatch(new GeoLiteDbCreated())->shouldHaveBeenCalledTimes($expectedDispatches);
|
||||
}
|
||||
|
||||
public function provideGeolocationResults(): iterable
|
||||
|
|
Loading…
Add table
Reference in a new issue