mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-28 00:38:46 +03:00
Merge pull request #1585 from acelaya-forks/feature/phpunit-mocks
Feature/phpunit mocks
This commit is contained in:
commit
7ceae7af87
53 changed files with 475 additions and 674 deletions
1
.github/workflows/ci-db-tests.yml
vendored
1
.github/workflows/ci-db-tests.yml
vendored
|
@ -14,7 +14,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
php-version: ['8.1', '8.2']
|
php-version: ['8.1', '8.2']
|
||||||
continue-on-error: ${{ matrix.php-version == '8.2' }}
|
|
||||||
env:
|
env:
|
||||||
LC_ALL: C
|
LC_ALL: C
|
||||||
steps:
|
steps:
|
||||||
|
|
1
.github/workflows/ci-mutation-tests.yml
vendored
1
.github/workflows/ci-mutation-tests.yml
vendored
|
@ -14,7 +14,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
php-version: ['8.1', '8.2']
|
php-version: ['8.1', '8.2']
|
||||||
continue-on-error: ${{ matrix.php-version == '8.2' }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: './.github/actions/ci-setup'
|
- uses: './.github/actions/ci-setup'
|
||||||
|
|
1
.github/workflows/ci-tests.yml
vendored
1
.github/workflows/ci-tests.yml
vendored
|
@ -14,7 +14,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
php-version: ['8.1', '8.2']
|
php-version: ['8.1', '8.2']
|
||||||
continue-on-error: ${{ matrix.php-version == '8.2' }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Start postgres database server
|
- name: Start postgres database server
|
||||||
|
|
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
|
@ -44,7 +44,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
php-version: ['8.1', '8.2']
|
php-version: ['8.1', '8.2']
|
||||||
continue-on-error: ${{ matrix.php-version == '8.2' }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d shlink_db_postgres
|
- run: docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d shlink_db_postgres
|
||||||
|
|
|
@ -36,11 +36,9 @@ class RoleResolverTest extends TestCase
|
||||||
array $expectedRoles,
|
array $expectedRoles,
|
||||||
int $expectedDomainCalls,
|
int $expectedDomainCalls,
|
||||||
): void {
|
): void {
|
||||||
$this->domainService
|
$this->domainService->expects($this->exactly($expectedDomainCalls))->method('getOrCreate')->with(
|
||||||
->expects($this->exactly($expectedDomainCalls))
|
'example.com',
|
||||||
->method('getOrCreate')
|
)->willReturn(Domain::withAuthority('example.com')->setId('1'));
|
||||||
->with($this->equalTo('example.com'))
|
|
||||||
->willReturn(Domain::withAuthority('example.com')->setId('1'));
|
|
||||||
|
|
||||||
$result = $this->resolver->determineRoles($input);
|
$result = $this->resolver->determineRoles($input);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class DisableKeyCommandTest extends TestCase
|
||||||
public function providedApiKeyIsDisabled(): void
|
public function providedApiKeyIsDisabled(): void
|
||||||
{
|
{
|
||||||
$apiKey = 'abcd1234';
|
$apiKey = 'abcd1234';
|
||||||
$this->apiKeyService->expects($this->once())->method('disable')->with($this->equalTo($apiKey));
|
$this->apiKeyService->expects($this->once())->method('disable')->with($apiKey);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
'apiKey' => $apiKey,
|
'apiKey' => $apiKey,
|
||||||
|
@ -44,9 +44,9 @@ class DisableKeyCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$apiKey = 'abcd1234';
|
$apiKey = 'abcd1234';
|
||||||
$expectedMessage = 'API key "abcd1234" does not exist.';
|
$expectedMessage = 'API key "abcd1234" does not exist.';
|
||||||
$this->apiKeyService->expects($this->once())->method('disable')->with(
|
$this->apiKeyService->expects($this->once())->method('disable')->with($apiKey)->willThrowException(
|
||||||
$this->equalTo($apiKey),
|
new InvalidArgumentException($expectedMessage),
|
||||||
)->willThrowException(new InvalidArgumentException($expectedMessage));
|
);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
'apiKey' => $apiKey,
|
'apiKey' => $apiKey,
|
||||||
|
|
|
@ -35,9 +35,7 @@ class ListKeysCommandTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function returnsExpectedOutput(array $keys, bool $enabledOnly, string $expected): void
|
public function returnsExpectedOutput(array $keys, bool $enabledOnly, string $expected): void
|
||||||
{
|
{
|
||||||
$this->apiKeyService->expects($this->once())->method('listKeys')->with(
|
$this->apiKeyService->expects($this->once())->method('listKeys')->with($enabledOnly)->willReturn($keys);
|
||||||
$this->equalTo($enabledOnly),
|
|
||||||
)->willReturn($keys);
|
|
||||||
|
|
||||||
$this->commandTester->execute(['--enabled-only' => $enabledOnly]);
|
$this->commandTester->execute(['--enabled-only' => $enabledOnly]);
|
||||||
$output = $this->commandTester->getDisplay();
|
$output = $this->commandTester->getDisplay();
|
||||||
|
|
|
@ -87,7 +87,7 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
$shlinkDatabase = 'shlink_database';
|
$shlinkDatabase = 'shlink_database';
|
||||||
$this->regularConn->expects($this->once())->method('getParams')->willReturn(['dbname' => $shlinkDatabase]);
|
$this->regularConn->expects($this->once())->method('getParams')->willReturn(['dbname' => $shlinkDatabase]);
|
||||||
$this->schemaManager->expects($this->once())->method('listDatabases')->willReturn(['foo', 'bar']);
|
$this->schemaManager->expects($this->once())->method('listDatabases')->willReturn(['foo', 'bar']);
|
||||||
$this->schemaManager->expects($this->once())->method('createDatabase')->with($this->equalTo($shlinkDatabase));
|
$this->schemaManager->expects($this->once())->method('createDatabase')->with($shlinkDatabase);
|
||||||
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn(
|
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn(
|
||||||
['foo_table', 'bar_table', MIGRATIONS_TABLE],
|
['foo_table', 'bar_table', MIGRATIONS_TABLE],
|
||||||
);
|
);
|
||||||
|
@ -109,15 +109,12 @@ class CreateDatabaseCommandTest extends TestCase
|
||||||
);
|
);
|
||||||
$this->schemaManager->expects($this->never())->method('createDatabase');
|
$this->schemaManager->expects($this->never())->method('createDatabase');
|
||||||
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn($tables);
|
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn($tables);
|
||||||
$this->processHelper->expects($this->once())->method('run')->with(
|
$this->processHelper->expects($this->once())->method('run')->with($this->isInstanceOf(OutputInterface::class), [
|
||||||
$this->isInstanceOf(OutputInterface::class),
|
'/usr/local/bin/php',
|
||||||
$this->equalTo([
|
CreateDatabaseCommand::DOCTRINE_SCRIPT,
|
||||||
'/usr/local/bin/php',
|
CreateDatabaseCommand::DOCTRINE_CREATE_SCHEMA_COMMAND,
|
||||||
CreateDatabaseCommand::DOCTRINE_SCRIPT,
|
'--no-interaction',
|
||||||
CreateDatabaseCommand::DOCTRINE_CREATE_SCHEMA_COMMAND,
|
]);
|
||||||
'--no-interaction',
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
|
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
|
||||||
|
|
||||||
$this->commandTester->execute([]);
|
$this->commandTester->execute([]);
|
||||||
|
|
|
@ -41,15 +41,12 @@ class MigrateDatabaseCommandTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function migrationsCommandIsRunWithProperVerbosity(): void
|
public function migrationsCommandIsRunWithProperVerbosity(): void
|
||||||
{
|
{
|
||||||
$this->processHelper->expects($this->once())->method('run')->with(
|
$this->processHelper->expects($this->once())->method('run')->with($this->isInstanceOf(OutputInterface::class), [
|
||||||
$this->isInstanceOf(OutputInterface::class),
|
'/usr/local/bin/php',
|
||||||
$this->equalTo([
|
MigrateDatabaseCommand::DOCTRINE_MIGRATIONS_SCRIPT,
|
||||||
'/usr/local/bin/php',
|
MigrateDatabaseCommand::DOCTRINE_MIGRATE_COMMAND,
|
||||||
MigrateDatabaseCommand::DOCTRINE_MIGRATIONS_SCRIPT,
|
'--no-interaction',
|
||||||
MigrateDatabaseCommand::DOCTRINE_MIGRATE_COMMAND,
|
]);
|
||||||
'--no-interaction',
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->commandTester->execute([]);
|
$this->commandTester->execute([]);
|
||||||
$output = $this->commandTester->getDisplay();
|
$output = $this->commandTester->getDisplay();
|
||||||
|
|
|
@ -37,12 +37,12 @@ class DomainRedirectsCommandTest extends TestCase
|
||||||
public function onlyPlainQuestionsAreAskedForNewDomainsAndDomainsWithNoRedirects(?Domain $domain): void
|
public function onlyPlainQuestionsAreAskedForNewDomainsAndDomainsWithNoRedirects(?Domain $domain): void
|
||||||
{
|
{
|
||||||
$domainAuthority = 'my-domain.com';
|
$domainAuthority = 'my-domain.com';
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->with(
|
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
|
||||||
$this->equalTo($domainAuthority),
|
$domain,
|
||||||
)->willReturn($domain);
|
);
|
||||||
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
||||||
$this->equalTo($domainAuthority),
|
$domainAuthority,
|
||||||
$this->equalTo(NotFoundRedirects::withRedirects('foo.com', null, 'baz.com')),
|
NotFoundRedirects::withRedirects('foo.com', null, 'baz.com'),
|
||||||
)->willReturn(Domain::withAuthority(''));
|
)->willReturn(Domain::withAuthority(''));
|
||||||
$this->domainService->expects($this->never())->method('listDomains');
|
$this->domainService->expects($this->never())->method('listDomains');
|
||||||
|
|
||||||
|
@ -73,12 +73,12 @@ class DomainRedirectsCommandTest extends TestCase
|
||||||
$domain = Domain::withAuthority($domainAuthority);
|
$domain = Domain::withAuthority($domainAuthority);
|
||||||
$domain->configureNotFoundRedirects(NotFoundRedirects::withRedirects('foo.com', 'bar.com', 'baz.com'));
|
$domain->configureNotFoundRedirects(NotFoundRedirects::withRedirects('foo.com', 'bar.com', 'baz.com'));
|
||||||
|
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->with(
|
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
|
||||||
$this->equalTo($domainAuthority),
|
$domain,
|
||||||
)->willReturn($domain);
|
);
|
||||||
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
||||||
$this->equalTo($domainAuthority),
|
$domainAuthority,
|
||||||
$this->equalTo(NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com')),
|
NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com'),
|
||||||
)->willReturn($domain);
|
)->willReturn($domain);
|
||||||
$this->domainService->expects($this->never())->method('listDomains');
|
$this->domainService->expects($this->never())->method('listDomains');
|
||||||
|
|
||||||
|
@ -102,12 +102,12 @@ class DomainRedirectsCommandTest extends TestCase
|
||||||
$domain = Domain::withAuthority($domainAuthority);
|
$domain = Domain::withAuthority($domainAuthority);
|
||||||
|
|
||||||
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([]);
|
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([]);
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->with(
|
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
|
||||||
$this->equalTo($domainAuthority),
|
$domain,
|
||||||
)->willReturn($domain);
|
);
|
||||||
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
||||||
$this->equalTo($domainAuthority),
|
$domainAuthority,
|
||||||
$this->equalTo(NotFoundRedirects::withoutRedirects()),
|
NotFoundRedirects::withoutRedirects(),
|
||||||
)->willReturn($domain);
|
)->willReturn($domain);
|
||||||
|
|
||||||
$this->commandTester->setInputs([$domainAuthority, '', '', '']);
|
$this->commandTester->setInputs([$domainAuthority, '', '', '']);
|
||||||
|
@ -128,12 +128,12 @@ class DomainRedirectsCommandTest extends TestCase
|
||||||
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
|
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
|
||||||
DomainItem::forNonDefaultDomain(Domain::withAuthority($domainAuthority)),
|
DomainItem::forNonDefaultDomain(Domain::withAuthority($domainAuthority)),
|
||||||
]);
|
]);
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->with(
|
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
|
||||||
$this->equalTo($domainAuthority),
|
$domain,
|
||||||
)->willReturn($domain);
|
);
|
||||||
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
||||||
$this->equalTo($domainAuthority),
|
$domainAuthority,
|
||||||
$this->equalTo(NotFoundRedirects::withoutRedirects()),
|
NotFoundRedirects::withoutRedirects(),
|
||||||
)->willReturn($domain);
|
)->willReturn($domain);
|
||||||
|
|
||||||
$this->commandTester->setInputs(['1', '', '', '']);
|
$this->commandTester->setInputs(['1', '', '', '']);
|
||||||
|
@ -157,12 +157,12 @@ class DomainRedirectsCommandTest extends TestCase
|
||||||
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
|
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
|
||||||
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-two.com')),
|
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-two.com')),
|
||||||
]);
|
]);
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->with(
|
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
|
||||||
$this->equalTo($domainAuthority),
|
$domain,
|
||||||
)->willReturn($domain);
|
);
|
||||||
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
|
||||||
$this->equalTo($domainAuthority),
|
$domainAuthority,
|
||||||
$this->equalTo(NotFoundRedirects::withoutRedirects()),
|
NotFoundRedirects::withoutRedirects(),
|
||||||
)->willReturn($domain);
|
)->willReturn($domain);
|
||||||
|
|
||||||
$this->commandTester->setInputs(['2', $domainAuthority, '', '', '']);
|
$this->commandTester->setInputs(['2', $domainAuthority, '', '', '']);
|
||||||
|
|
|
@ -46,10 +46,10 @@ class GetDomainVisitsCommandTest extends TestCase
|
||||||
);
|
);
|
||||||
$domain = 'doma.in';
|
$domain = 'doma.in';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForDomain')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForDomain')->with(
|
||||||
$this->equalTo($domain),
|
$domain,
|
||||||
$this->anything(),
|
$this->anything(),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
|
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
|
||||||
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
|
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn(
|
||||||
'the_short_url',
|
'the_short_url',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ class CreateShortUrlCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortUrl = ShortUrl::createEmpty();
|
$shortUrl = ShortUrl::createEmpty();
|
||||||
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willReturn($shortUrl);
|
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willReturn($shortUrl);
|
||||||
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
|
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn(
|
||||||
'stringified_short_url',
|
'stringified_short_url',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class CreateShortUrlCommandTest extends TestCase
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
|
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn(
|
||||||
'stringified_short_url',
|
'stringified_short_url',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->isFalse(),
|
$this->isFalse(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
||||||
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
||||||
$this->equalTo($identifier),
|
$identifier,
|
||||||
$this->isFalse(),
|
$this->isFalse(),
|
||||||
)->willThrowException(Exception\ShortUrlNotFoundException::fromNotFound($identifier));
|
)->willThrowException(Exception\ShortUrlNotFoundException::fromNotFound($identifier));
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
||||||
$this->service->expects($this->exactly($expectedDeleteCalls))->method('deleteByShortCode')->with(
|
$this->service->expects($this->exactly($expectedDeleteCalls))->method('deleteByShortCode')->with(
|
||||||
$this->equalTo($identifier),
|
$identifier,
|
||||||
$this->isType('bool'),
|
$this->isType('bool'),
|
||||||
)->willReturnCallback(function ($_, bool $ignoreThreshold) use ($shortCode): void {
|
)->willReturnCallback(function ($_, bool $ignoreThreshold) use ($shortCode): void {
|
||||||
if (!$ignoreThreshold) {
|
if (!$ignoreThreshold) {
|
||||||
|
@ -110,7 +110,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
$this->service->expects($this->once())->method('deleteByShortCode')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->isFalse(),
|
$this->isFalse(),
|
||||||
)->willThrowException(Exception\DeleteShortUrlException::fromVisitsThreshold(
|
)->willThrowException(Exception\DeleteShortUrlException::fromVisitsThreshold(
|
||||||
10,
|
10,
|
||||||
|
|
|
@ -44,8 +44,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->equalTo(new VisitsParams(DateRange::allTime())),
|
new VisitsParams(DateRange::allTime()),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
)->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
@ -58,8 +58,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
|
||||||
$startDate = '2016-01-01';
|
$startDate = '2016-01-01';
|
||||||
$endDate = '2016-02-01';
|
$endDate = '2016-02-01';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->equalTo(new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate)))),
|
new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate))),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
)->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
@ -75,8 +75,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$startDate = 'foo';
|
$startDate = 'foo';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->equalTo(new VisitsParams(DateRange::allTime())),
|
new VisitsParams(DateRange::allTime()),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
)->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
@ -99,7 +99,7 @@ class GetShortUrlVisitsCommandTest extends TestCase
|
||||||
);
|
);
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
$this->anything(),
|
$this->anything(),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
|
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
||||||
$this->equalTo(ShortUrlsParams::emptyInstance()),
|
ShortUrlsParams::emptyInstance(),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter($data)));
|
)->willReturn(new Paginator(new ArrayAdapter($data)));
|
||||||
|
|
||||||
$this->commandTester->setInputs(['n']);
|
$this->commandTester->setInputs(['n']);
|
||||||
|
@ -94,7 +94,7 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
$page = 5;
|
$page = 5;
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
||||||
$this->equalTo(ShortUrlsParams::fromRawData(['page' => $page])),
|
ShortUrlsParams::fromRawData(['page' => $page]),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
)->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
|
|
||||||
$this->commandTester->setInputs(['y']);
|
$this->commandTester->setInputs(['y']);
|
||||||
|
@ -112,7 +112,7 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
ApiKey $apiKey,
|
ApiKey $apiKey,
|
||||||
): void {
|
): void {
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
||||||
$this->equalTo(ShortUrlsParams::emptyInstance()),
|
ShortUrlsParams::emptyInstance(),
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([
|
)->willReturn(new Paginator(new ArrayAdapter([
|
||||||
ShortUrl::fromMeta(ShortUrlCreation::fromRawData([
|
ShortUrl::fromMeta(ShortUrlCreation::fromRawData([
|
||||||
'longUrl' => 'foo.com',
|
'longUrl' => 'foo.com',
|
||||||
|
@ -187,16 +187,14 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
?string $startDate = null,
|
?string $startDate = null,
|
||||||
?string $endDate = null,
|
?string $endDate = null,
|
||||||
): void {
|
): void {
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
|
||||||
$this->equalTo(ShortUrlsParams::fromRawData([
|
'page' => $page,
|
||||||
'page' => $page,
|
'searchTerm' => $searchTerm,
|
||||||
'searchTerm' => $searchTerm,
|
'tags' => $tags,
|
||||||
'tags' => $tags,
|
'tagsMode' => $tagsMode,
|
||||||
'tagsMode' => $tagsMode,
|
'startDate' => $startDate !== null ? Chronos::parse($startDate)->toAtomString() : null,
|
||||||
'startDate' => $startDate !== null ? Chronos::parse($startDate)->toAtomString() : null,
|
'endDate' => $endDate !== null ? Chronos::parse($endDate)->toAtomString() : null,
|
||||||
'endDate' => $endDate !== null ? Chronos::parse($endDate)->toAtomString() : null,
|
]))->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
])),
|
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
|
||||||
|
|
||||||
$this->commandTester->setInputs(['n']);
|
$this->commandTester->setInputs(['n']);
|
||||||
$this->commandTester->execute($commandArgs);
|
$this->commandTester->execute($commandArgs);
|
||||||
|
@ -249,11 +247,9 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void
|
public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void
|
||||||
{
|
{
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
|
||||||
$this->equalTo(ShortUrlsParams::fromRawData([
|
'orderBy' => $expectedOrderBy,
|
||||||
'orderBy' => $expectedOrderBy,
|
]))->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
])),
|
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
|
||||||
|
|
||||||
$this->commandTester->setInputs(['n']);
|
$this->commandTester->setInputs(['n']);
|
||||||
$this->commandTester->execute($commandArgs);
|
$this->commandTester->execute($commandArgs);
|
||||||
|
@ -271,18 +267,16 @@ class ListShortUrlsCommandTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function requestingAllElementsWillSetItemsPerPage(): void
|
public function requestingAllElementsWillSetItemsPerPage(): void
|
||||||
{
|
{
|
||||||
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
|
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
|
||||||
$this->equalTo(ShortUrlsParams::fromRawData([
|
'page' => 1,
|
||||||
'page' => 1,
|
'searchTerm' => null,
|
||||||
'searchTerm' => null,
|
'tags' => [],
|
||||||
'tags' => [],
|
'tagsMode' => TagsMode::ANY->value,
|
||||||
'tagsMode' => TagsMode::ANY->value,
|
'startDate' => null,
|
||||||
'startDate' => null,
|
'endDate' => null,
|
||||||
'endDate' => null,
|
'orderBy' => null,
|
||||||
'orderBy' => null,
|
'itemsPerPage' => Paginator::ALL_ITEMS,
|
||||||
'itemsPerPage' => Paginator::ALL_ITEMS,
|
]))->willReturn(new Paginator(new ArrayAdapter([])));
|
||||||
])),
|
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([])));
|
|
||||||
|
|
||||||
$this->commandTester->execute(['--all' => true]);
|
$this->commandTester->execute(['--all' => true]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ class ResolveUrlCommandTest extends TestCase
|
||||||
$expectedUrl = 'http://domain.com/foo/bar';
|
$expectedUrl = 'http://domain.com/foo/bar';
|
||||||
$shortUrl = ShortUrl::withLongUrl($expectedUrl);
|
$shortUrl = ShortUrl::withLongUrl($expectedUrl);
|
||||||
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
|
@ -52,9 +52,9 @@ class ResolveUrlCommandTest extends TestCase
|
||||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123');
|
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123');
|
||||||
$shortCode = $identifier->shortCode;
|
$shortCode = $identifier->shortCode;
|
||||||
|
|
||||||
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with($identifier)->willThrowException(
|
||||||
$this->equalTo($identifier),
|
ShortUrlNotFoundException::fromNotFound($identifier),
|
||||||
)->willThrowException(ShortUrlNotFoundException::fromNotFound($identifier));
|
);
|
||||||
|
|
||||||
$this->commandTester->execute(['shortCode' => $shortCode]);
|
$this->commandTester->execute(['shortCode' => $shortCode]);
|
||||||
$output = $this->commandTester->getDisplay();
|
$output = $this->commandTester->getDisplay();
|
||||||
|
|
|
@ -37,7 +37,7 @@ class DeleteTagsCommandTest extends TestCase
|
||||||
public function serviceIsInvokedOnSuccess(): void
|
public function serviceIsInvokedOnSuccess(): void
|
||||||
{
|
{
|
||||||
$tagNames = ['foo', 'bar'];
|
$tagNames = ['foo', 'bar'];
|
||||||
$this->tagService->expects($this->once())->method('deleteTags')->with($this->equalTo($tagNames));
|
$this->tagService->expects($this->once())->method('deleteTags')->with($tagNames);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
'--name' => $tagNames,
|
'--name' => $tagNames,
|
||||||
|
|
|
@ -45,13 +45,10 @@ class GetTagVisitsCommandTest extends TestCase
|
||||||
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
|
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
|
||||||
);
|
);
|
||||||
$tag = 'abc123';
|
$tag = 'abc123';
|
||||||
$this->visitsHelper->expects($this->once())->method('visitsForTag')->with(
|
$this->visitsHelper->expects($this->once())->method('visitsForTag')->with($tag, $this->anything())->willReturn(
|
||||||
$this->equalTo($tag),
|
new Paginator(new ArrayAdapter([$visit])),
|
||||||
$this->anything(),
|
|
||||||
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
|
|
||||||
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
|
|
||||||
'the_short_url',
|
|
||||||
);
|
);
|
||||||
|
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn('the_short_url');
|
||||||
|
|
||||||
$this->commandTester->execute(['tag' => $tag]);
|
$this->commandTester->execute(['tag' => $tag]);
|
||||||
$output = $this->commandTester->getDisplay();
|
$output = $this->commandTester->getDisplay();
|
||||||
|
|
|
@ -33,7 +33,7 @@ class RenameTagCommandTest extends TestCase
|
||||||
$oldName = 'foo';
|
$oldName = 'foo';
|
||||||
$newName = 'bar';
|
$newName = 'bar';
|
||||||
$this->tagService->expects($this->once())->method('renameTag')->with(
|
$this->tagService->expects($this->once())->method('renameTag')->with(
|
||||||
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
|
TagRenaming::fromNames($oldName, $newName),
|
||||||
)->willThrowException(TagNotFoundException::fromTag('foo'));
|
)->willThrowException(TagNotFoundException::fromTag('foo'));
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
@ -51,7 +51,7 @@ class RenameTagCommandTest extends TestCase
|
||||||
$oldName = 'foo';
|
$oldName = 'foo';
|
||||||
$newName = 'bar';
|
$newName = 'bar';
|
||||||
$this->tagService->expects($this->once())->method('renameTag')->with(
|
$this->tagService->expects($this->once())->method('renameTag')->with(
|
||||||
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
|
TagRenaming::fromNames($oldName, $newName),
|
||||||
)->willReturn(new Tag($newName));
|
)->willReturn(new Tag($newName));
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
|
|
|
@ -47,9 +47,7 @@ class GetNonOrphanVisitsCommandTest extends TestCase
|
||||||
$this->visitsHelper->expects($this->once())->method('nonOrphanVisits')->withAnyParameters()->willReturn(
|
$this->visitsHelper->expects($this->once())->method('nonOrphanVisits')->withAnyParameters()->willReturn(
|
||||||
new Paginator(new ArrayAdapter([$visit])),
|
new Paginator(new ArrayAdapter([$visit])),
|
||||||
);
|
);
|
||||||
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
|
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn('the_short_url');
|
||||||
'the_short_url',
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->commandTester->execute([]);
|
$this->commandTester->execute([]);
|
||||||
$output = $this->commandTester->getDisplay();
|
$output = $this->commandTester->getDisplay();
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ProcessRunnerTest extends TestCase
|
||||||
$this->helper = $this->createMock(ProcessHelper::class);
|
$this->helper = $this->createMock(ProcessHelper::class);
|
||||||
$this->formatter = $this->createMock(DebugFormatterHelper::class);
|
$this->formatter = $this->createMock(DebugFormatterHelper::class);
|
||||||
$helperSet = $this->createMock(HelperSet::class);
|
$helperSet = $this->createMock(HelperSet::class);
|
||||||
$helperSet->method('get')->with($this->equalTo('debug_formatter'))->willReturn($this->formatter);
|
$helperSet->method('get')->with('debug_formatter')->willReturn($this->formatter);
|
||||||
$this->helper->method('getHelperSet')->with()->willReturn($helperSet);
|
$this->helper->method('getHelperSet')->with()->willReturn($helperSet);
|
||||||
$this->process = $this->createMock(Process::class);
|
$this->process = $this->createMock(Process::class);
|
||||||
$this->output = $this->createMock(OutputInterface::class);
|
$this->output = $this->createMock(OutputInterface::class);
|
||||||
|
|
|
@ -34,16 +34,10 @@ class ShlinkTableTest extends TestCase
|
||||||
$this->baseTable->expects($this->once())->method('setStyle')->with(
|
$this->baseTable->expects($this->once())->method('setStyle')->with(
|
||||||
$this->isInstanceOf(TableStyle::class),
|
$this->isInstanceOf(TableStyle::class),
|
||||||
)->willReturnSelf();
|
)->willReturnSelf();
|
||||||
$this->baseTable->expects($this->once())->method('setHeaders')->with(
|
$this->baseTable->expects($this->once())->method('setHeaders')->with($headers)->willReturnSelf();
|
||||||
$this->equalTo($headers),
|
$this->baseTable->expects($this->once())->method('setRows')->with($rows)->willReturnSelf();
|
||||||
)->willReturnSelf();
|
$this->baseTable->expects($this->once())->method('setFooterTitle')->with($footerTitle)->willReturnSelf();
|
||||||
$this->baseTable->expects($this->once())->method('setRows')->with($this->equalTo($rows))->willReturnSelf();
|
$this->baseTable->expects($this->once())->method('setHeaderTitle')->with($headerTitle)->willReturnSelf();
|
||||||
$this->baseTable->expects($this->once())->method('setFooterTitle')->with(
|
|
||||||
$this->equalTo($footerTitle),
|
|
||||||
)->willReturnSelf();
|
|
||||||
$this->baseTable->expects($this->once())->method('setHeaderTitle')->with(
|
|
||||||
$this->equalTo($headerTitle),
|
|
||||||
)->willReturnSelf();
|
|
||||||
$this->baseTable->expects($this->once())->method('render')->with()->willReturnSelf();
|
$this->baseTable->expects($this->once())->method('render')->with()->willReturnSelf();
|
||||||
|
|
||||||
$this->shlinkTable->render($headers, $rows, $footerTitle, $headerTitle);
|
$this->shlinkTable->render($headers, $rows, $footerTitle, $headerTitle);
|
||||||
|
|
|
@ -21,8 +21,9 @@ class PersistenceShortUrlRelationResolver implements ShortUrlRelationResolverInt
|
||||||
/** @var array<string, Tag> */
|
/** @var array<string, Tag> */
|
||||||
private array $memoizedNewTags = [];
|
private array $memoizedNewTags = [];
|
||||||
|
|
||||||
public function __construct(private EntityManagerInterface $em)
|
public function __construct(private readonly EntityManagerInterface $em)
|
||||||
{
|
{
|
||||||
|
// Registering this as an event listener will make the postFlush method to be called automatically
|
||||||
$this->em->getEventManager()->addEventListener(Events::postFlush, $this);
|
$this->em->getEventManager()->addEventListener(Events::postFlush, $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ class PersistenceShortUrlRelationResolver implements ShortUrlRelationResolverInt
|
||||||
|
|
||||||
return new Collections\ArrayCollection(map($tags, function (string $tagName) use ($repo): Tag {
|
return new Collections\ArrayCollection(map($tags, function (string $tagName) use ($repo): Tag {
|
||||||
// Memoize only new tags, and let doctrine handle objects hydrated from persistence
|
// Memoize only new tags, and let doctrine handle objects hydrated from persistence
|
||||||
$tag = $repo->findOneBy(['name' => $tagName]) ?? $this->memoizeNewTag($tagName);
|
$tag = $repo->findOneBy(['name' => $tagName]) ?? $this->memoizeNewTag($tagName);
|
||||||
$this->em->persist($tag);
|
$this->em->persist($tag);
|
||||||
|
|
||||||
return $tag;
|
return $tag;
|
||||||
|
|
|
@ -34,7 +34,7 @@ class PixelActionTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
|
||||||
)->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar'));
|
)->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar'));
|
||||||
$this->requestTracker->expects($this->once())->method('trackIfApplicable')->withAnyParameters();
|
$this->requestTracker->expects($this->once())->method('trackIfApplicable')->withAnyParameters();
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class QrCodeActionTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
|
||||||
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
|
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
|
||||||
$delegate = $this->createMock(RequestHandlerInterface::class);
|
$delegate = $this->createMock(RequestHandlerInterface::class);
|
||||||
$delegate->expects($this->once())->method('handle')->withAnyParameters()->willReturn(new Response());
|
$delegate->expects($this->once())->method('handle')->withAnyParameters()->willReturn(new Response());
|
||||||
|
@ -55,7 +55,7 @@ class QrCodeActionTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
|
||||||
)->willReturn(ShortUrl::createEmpty());
|
)->willReturn(ShortUrl::createEmpty());
|
||||||
$delegate = $this->createMock(RequestHandlerInterface::class);
|
$delegate = $this->createMock(RequestHandlerInterface::class);
|
||||||
$delegate->expects($this->never())->method('handle');
|
$delegate->expects($this->never())->method('handle');
|
||||||
|
@ -77,7 +77,7 @@ class QrCodeActionTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$code = 'abc123';
|
$code = 'abc123';
|
||||||
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
|
||||||
)->willReturn(ShortUrl::createEmpty());
|
)->willReturn(ShortUrl::createEmpty());
|
||||||
$delegate = $this->createMock(RequestHandlerInterface::class);
|
$delegate = $this->createMock(RequestHandlerInterface::class);
|
||||||
$req = (new ServerRequest())->withAttribute('shortCode', $code)->withQueryParams($query);
|
$req = (new ServerRequest())->withAttribute('shortCode', $code)->withQueryParams($query);
|
||||||
|
@ -110,7 +110,7 @@ class QrCodeActionTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$code = 'abc123';
|
$code = 'abc123';
|
||||||
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
|
||||||
)->willReturn(ShortUrl::createEmpty());
|
)->willReturn(ShortUrl::createEmpty());
|
||||||
$delegate = $this->createMock(RequestHandlerInterface::class);
|
$delegate = $this->createMock(RequestHandlerInterface::class);
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ class QrCodeActionTest extends TestCase
|
||||||
->withAttribute('shortCode', $code);
|
->withAttribute('shortCode', $code);
|
||||||
|
|
||||||
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
|
||||||
)->willReturn(ShortUrl::withLongUrl('https://shlink.io'));
|
)->willReturn(ShortUrl::withLongUrl('https://shlink.io'));
|
||||||
$delegate = $this->createMock(RequestHandlerInterface::class);
|
$delegate = $this->createMock(RequestHandlerInterface::class);
|
||||||
|
|
||||||
|
|
|
@ -50,12 +50,12 @@ class RedirectActionTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$shortUrl = ShortUrl::withLongUrl(self::LONG_URL);
|
$shortUrl = ShortUrl::withLongUrl(self::LONG_URL);
|
||||||
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$this->requestTracker->expects($this->once())->method('trackIfApplicable');
|
$this->requestTracker->expects($this->once())->method('trackIfApplicable');
|
||||||
$expectedResp = new Response\RedirectResponse(self::LONG_URL);
|
$expectedResp = new Response\RedirectResponse(self::LONG_URL);
|
||||||
$this->redirectRespHelper->expects($this->once())->method('buildRedirectResponse')->with(
|
$this->redirectRespHelper->expects($this->once())->method('buildRedirectResponse')->with(
|
||||||
$this->equalTo(self::LONG_URL),
|
self::LONG_URL,
|
||||||
)->willReturn($expectedResp);
|
)->willReturn($expectedResp);
|
||||||
|
|
||||||
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
|
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
|
||||||
|
@ -69,7 +69,7 @@ class RedirectActionTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
|
||||||
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
|
||||||
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
|
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
|
||||||
$this->requestTracker->expects($this->never())->method('trackIfApplicable');
|
$this->requestTracker->expects($this->never())->method('trackIfApplicable');
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@ class NotFoundRedirectResolverTest extends TestCase
|
||||||
string $expectedRedirectTo,
|
string $expectedRedirectTo,
|
||||||
): void {
|
): void {
|
||||||
$expectedResp = new Response();
|
$expectedResp = new Response();
|
||||||
$this->helper->expects($this->once())->method('buildRedirectResponse')->with(
|
$this->helper->expects($this->once())->method('buildRedirectResponse')->with($expectedRedirectTo)->willReturn(
|
||||||
$this->equalTo($expectedRedirectTo),
|
$expectedResp,
|
||||||
)->willReturn($expectedResp);
|
);
|
||||||
|
|
||||||
$resp = $this->resolver->resolveRedirectResponse($notFoundType, $redirectConfig, $uri);
|
$resp = $this->resolver->resolveRedirectResponse($notFoundType, $redirectConfig, $uri);
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,7 @@ class CrawlingHelperTest extends TestCase
|
||||||
{
|
{
|
||||||
$repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
$repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
||||||
$repo->expects($this->once())->method('findCrawlableShortCodes')->willReturn([]);
|
$repo->expects($this->once())->method('findCrawlableShortCodes')->willReturn([]);
|
||||||
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(ShortUrl::class))->willReturn(
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
|
||||||
$repo,
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $this->helper->listCrawlableShortCodes();
|
$result = $this->helper->listCrawlableShortCodes();
|
||||||
foreach ($result as $shortCode) {
|
foreach ($result as $shortCode) {
|
||||||
|
|
|
@ -36,10 +36,8 @@ class DomainServiceTest extends TestCase
|
||||||
public function listDomainsDelegatesIntoRepository(array $domains, array $expectedResult, ?ApiKey $apiKey): void
|
public function listDomainsDelegatesIntoRepository(array $domains, array $expectedResult, ?ApiKey $apiKey): void
|
||||||
{
|
{
|
||||||
$repo = $this->createMock(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$repo->expects($this->once())->method('findDomains')->with($this->equalTo($apiKey))->willReturn($domains);
|
$repo->expects($this->once())->method('findDomains')->with($apiKey)->willReturn($domains);
|
||||||
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
|
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
$repo,
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $this->domainService->listDomains($apiKey);
|
$result = $this->domainService->listDomains($apiKey);
|
||||||
|
|
||||||
|
@ -105,10 +103,7 @@ class DomainServiceTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function getDomainThrowsExceptionWhenDomainIsNotFound(): void
|
public function getDomainThrowsExceptionWhenDomainIsNotFound(): void
|
||||||
{
|
{
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Domain::class, '123')->willReturn(null);
|
||||||
$this->equalTo(Domain::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn(null);
|
|
||||||
|
|
||||||
$this->expectException(DomainNotFoundException::class);
|
$this->expectException(DomainNotFoundException::class);
|
||||||
|
|
||||||
|
@ -119,10 +114,7 @@ class DomainServiceTest extends TestCase
|
||||||
public function getDomainReturnsEntityWhenFound(): void
|
public function getDomainReturnsEntityWhenFound(): void
|
||||||
{
|
{
|
||||||
$domain = Domain::withAuthority('');
|
$domain = Domain::withAuthority('');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Domain::class, '123')->willReturn($domain);
|
||||||
$this->equalTo(Domain::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn($domain);
|
|
||||||
|
|
||||||
$result = $this->domainService->getDomain('123');
|
$result = $this->domainService->getDomain('123');
|
||||||
|
|
||||||
|
@ -137,15 +129,11 @@ class DomainServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$authority = 'example.com';
|
$authority = 'example.com';
|
||||||
$repo = $this->createMock(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
|
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn(
|
||||||
$foundDomain,
|
$foundDomain,
|
||||||
);
|
);
|
||||||
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
|
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
$repo,
|
$this->em->expects($this->once())->method('persist')->with($foundDomain ?? $this->isInstanceOf(Domain::class));
|
||||||
);
|
|
||||||
$this->em->expects($this->once())->method('persist')->with(
|
|
||||||
$foundDomain !== null ? $this->equalTo($foundDomain) : $this->isInstanceOf(Domain::class),
|
|
||||||
);
|
|
||||||
$this->em->expects($this->once())->method('flush');
|
$this->em->expects($this->once())->method('flush');
|
||||||
|
|
||||||
$result = $this->domainService->getOrCreate($authority, $apiKey);
|
$result = $this->domainService->getOrCreate($authority, $apiKey);
|
||||||
|
@ -162,12 +150,8 @@ class DomainServiceTest extends TestCase
|
||||||
$domain = Domain::withAuthority($authority)->setId('1');
|
$domain = Domain::withAuthority($authority)->setId('1');
|
||||||
$apiKey = ApiKey::fromMeta(ApiKeyMeta::withRoles(RoleDefinition::forDomain($domain)));
|
$apiKey = ApiKey::fromMeta(ApiKeyMeta::withRoles(RoleDefinition::forDomain($domain)));
|
||||||
$repo = $this->createMock(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
|
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn(null);
|
||||||
null,
|
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
);
|
|
||||||
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
|
|
||||||
$repo,
|
|
||||||
);
|
|
||||||
$this->em->expects($this->never())->method('persist');
|
$this->em->expects($this->never())->method('persist');
|
||||||
$this->em->expects($this->never())->method('flush');
|
$this->em->expects($this->never())->method('flush');
|
||||||
|
|
||||||
|
@ -184,15 +168,9 @@ class DomainServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$authority = 'example.com';
|
$authority = 'example.com';
|
||||||
$repo = $this->createMock(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
|
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn($foundDomain);
|
||||||
$foundDomain,
|
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
);
|
$this->em->expects($this->once())->method('persist')->with($foundDomain ?? $this->isInstanceOf(Domain::class));
|
||||||
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
|
|
||||||
$repo,
|
|
||||||
);
|
|
||||||
$this->em->expects($this->once())->method('persist')->with(
|
|
||||||
$foundDomain !== null ? $this->equalTo($foundDomain) : $this->isInstanceOf(Domain::class),
|
|
||||||
);
|
|
||||||
$this->em->expects($this->once())->method('flush');
|
$this->em->expects($this->once())->method('flush');
|
||||||
|
|
||||||
$result = $this->domainService->configureNotFoundRedirects($authority, NotFoundRedirects::withRedirects(
|
$result = $this->domainService->configureNotFoundRedirects($authority, NotFoundRedirects::withRedirects(
|
||||||
|
|
|
@ -51,9 +51,7 @@ class NotFoundRedirectHandlerTest extends TestCase
|
||||||
$expectedResp = new Response();
|
$expectedResp = new Response();
|
||||||
|
|
||||||
$setUp($this->domainService, $this->resolver);
|
$setUp($this->domainService, $this->resolver);
|
||||||
$this->next->expects($this->once())->method('handle')->with($this->equalTo($this->req))->willReturn(
|
$this->next->expects($this->once())->method('handle')->with($this->req)->willReturn($expectedResp);
|
||||||
$expectedResp,
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $this->middleware->process($this->req, $this->next);
|
$result = $this->middleware->process($this->req, $this->next);
|
||||||
|
|
||||||
|
@ -105,7 +103,7 @@ class NotFoundRedirectHandlerTest extends TestCase
|
||||||
$this->domainService->expects($this->once())->method('findByAuthority')->withAnyParameters()->willReturn(null);
|
$this->domainService->expects($this->once())->method('findByAuthority')->withAnyParameters()->willReturn(null);
|
||||||
$this->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
|
$this->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
|
||||||
$this->isInstanceOf(NotFoundType::class),
|
$this->isInstanceOf(NotFoundType::class),
|
||||||
$this->equalTo($this->redirectOptions),
|
$this->redirectOptions,
|
||||||
$this->isInstanceOf(UriInterface::class),
|
$this->isInstanceOf(UriInterface::class),
|
||||||
)->willReturn($expectedResp);
|
)->willReturn($expectedResp);
|
||||||
$this->next->expects($this->never())->method('handle');
|
$this->next->expects($this->never())->method('handle');
|
||||||
|
@ -126,7 +124,7 @@ class NotFoundRedirectHandlerTest extends TestCase
|
||||||
);
|
);
|
||||||
$this->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
|
$this->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
|
||||||
$this->isInstanceOf(NotFoundType::class),
|
$this->isInstanceOf(NotFoundType::class),
|
||||||
$this->equalTo($domain),
|
$domain,
|
||||||
$this->isInstanceOf(UriInterface::class),
|
$this->isInstanceOf(UriInterface::class),
|
||||||
)->willReturn($expectedResp);
|
)->willReturn($expectedResp);
|
||||||
$this->next->expects($this->never())->method('handle');
|
$this->next->expects($this->never())->method('handle');
|
||||||
|
|
|
@ -35,10 +35,8 @@ class NotFoundTrackerMiddlewareTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function delegatesIntoRequestTracker(): void
|
public function delegatesIntoRequestTracker(): void
|
||||||
{
|
{
|
||||||
$this->handler->expects($this->once())->method('handle')->with($this->equalTo($this->request));
|
$this->handler->expects($this->once())->method('handle')->with($this->request);
|
||||||
$this->requestTracker->expects($this->once())->method('trackNotFoundIfApplicable')->with(
|
$this->requestTracker->expects($this->once())->method('trackNotFoundIfApplicable')->with($this->request);
|
||||||
$this->equalTo($this->request),
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->middleware->process($this->request, $this->handler);
|
$this->middleware->process($this->request, $this->handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class CloseDbConnectionEventListenerDelegatorTest extends TestCase
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
$this->container->expects($this->once())->method('get')->with($this->equalTo('em'))->willReturn(
|
$this->container->expects($this->once())->method('get')->with('em')->willReturn(
|
||||||
$this->createMock(ReopeningEntityManagerInterface::class),
|
$this->createMock(ReopeningEntityManagerInterface::class),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class LocateUnlocatedVisitsTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function locatorIsCalledWhenInvoked(): void
|
public function locatorIsCalledWhenInvoked(): void
|
||||||
{
|
{
|
||||||
$this->locator->expects($this->once())->method('locateUnlocatedVisits')->with($this->equalTo($this->listener));
|
$this->locator->expects($this->once())->method('locateUnlocatedVisits')->with($this->listener);
|
||||||
($this->listener)(new GeoLiteDbCreated());
|
($this->listener)(new GeoLiteDbCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ class LocateUnlocatedVisitsTest extends TestCase
|
||||||
$visit = Visit::forBasePath(Visitor::emptyInstance());
|
$visit = Visit::forBasePath(Visitor::emptyInstance());
|
||||||
$location = Location::emptyInstance();
|
$location = Location::emptyInstance();
|
||||||
|
|
||||||
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->with(
|
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->with($visit)->willReturn(
|
||||||
$this->equalTo($visit),
|
$location,
|
||||||
)->willReturn($location);
|
);
|
||||||
|
|
||||||
$result = $this->listener->geolocateVisit($visit);
|
$result = $this->listener->geolocateVisit($visit);
|
||||||
|
|
||||||
|
|
|
@ -53,18 +53,13 @@ class LocateVisitTest extends TestCase
|
||||||
public function invalidVisitLogsWarning(): void
|
public function invalidVisitLogsWarning(): void
|
||||||
{
|
{
|
||||||
$event = new UrlVisited('123');
|
$event = new UrlVisited('123');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(null);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->em->expects($this->never())->method('flush');
|
$this->em->expects($this->never())->method('flush');
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$this->logger->expects($this->once())->method('warning')->with(
|
||||||
$this->equalTo('Tried to locate visit with id "{visitId}", but it does not exist.'),
|
'Tried to locate visit with id "{visitId}", but it does not exist.',
|
||||||
$this->equalTo(['visitId' => 123]),
|
['visitId' => 123],
|
||||||
);
|
|
||||||
$this->eventDispatcher->expects($this->never())->method('dispatch')->with(
|
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
);
|
||||||
|
$this->eventDispatcher->expects($this->never())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -74,19 +69,16 @@ class LocateVisitTest extends TestCase
|
||||||
public function nonExistingGeoLiteDbLogsWarning(): void
|
public function nonExistingGeoLiteDbLogsWarning(): void
|
||||||
{
|
{
|
||||||
$event = new UrlVisited('123');
|
$event = new UrlVisited('123');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||||
$this->equalTo('123'),
|
);
|
||||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
|
||||||
$this->em->expects($this->never())->method('flush');
|
$this->em->expects($this->never())->method('flush');
|
||||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(false);
|
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(false);
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$this->logger->expects($this->once())->method('warning')->with(
|
||||||
$this->equalTo('Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.'),
|
'Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.',
|
||||||
$this->equalTo(['visitId' => 123]),
|
['visitId' => 123],
|
||||||
);
|
|
||||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
);
|
||||||
|
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -96,22 +88,19 @@ class LocateVisitTest extends TestCase
|
||||||
public function invalidAddressLogsWarning(): void
|
public function invalidAddressLogsWarning(): void
|
||||||
{
|
{
|
||||||
$event = new UrlVisited('123');
|
$event = new UrlVisited('123');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||||
$this->equalTo('123'),
|
);
|
||||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
|
||||||
$this->em->expects($this->never())->method('flush');
|
$this->em->expects($this->never())->method('flush');
|
||||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||||
$this->ipLocationResolver->expects(
|
$this->ipLocationResolver->expects(
|
||||||
$this->once(),
|
$this->once(),
|
||||||
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(WrongIpException::fromIpAddress(''));
|
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(WrongIpException::fromIpAddress(''));
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$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}'),
|
'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}',
|
||||||
$this->isType('array'),
|
$this->isType('array'),
|
||||||
);
|
);
|
||||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
}
|
}
|
||||||
|
@ -120,22 +109,19 @@ class LocateVisitTest extends TestCase
|
||||||
public function unhandledExceptionLogsError(): void
|
public function unhandledExceptionLogsError(): void
|
||||||
{
|
{
|
||||||
$event = new UrlVisited('123');
|
$event = new UrlVisited('123');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
|
||||||
$this->equalTo('123'),
|
);
|
||||||
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
|
|
||||||
$this->em->expects($this->never())->method('flush');
|
$this->em->expects($this->never())->method('flush');
|
||||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||||
$this->ipLocationResolver->expects(
|
$this->ipLocationResolver->expects(
|
||||||
$this->once(),
|
$this->once(),
|
||||||
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(new OutOfRangeException());
|
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(new OutOfRangeException());
|
||||||
$this->logger->expects($this->once())->method('error')->with(
|
$this->logger->expects($this->once())->method('error')->with(
|
||||||
$this->equalTo('An unexpected error occurred while trying to locate visit with id "{visitId}". {e}'),
|
'An unexpected error occurred while trying to locate visit with id "{visitId}". {e}',
|
||||||
$this->isType('array'),
|
$this->isType('array'),
|
||||||
);
|
);
|
||||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
}
|
}
|
||||||
|
@ -147,17 +133,12 @@ class LocateVisitTest extends TestCase
|
||||||
public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void
|
public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void
|
||||||
{
|
{
|
||||||
$event = new UrlVisited('123');
|
$event = new UrlVisited('123');
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->em->expects($this->once())->method('flush');
|
$this->em->expects($this->once())->method('flush');
|
||||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||||
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
|
||||||
|
|
||||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
@ -184,19 +165,14 @@ class LocateVisitTest extends TestCase
|
||||||
$location = new Location('', '', '', '', 0.0, 0.0, '');
|
$location = new Location('', '', '', '', 0.0, 0.0, '');
|
||||||
$event = UrlVisited::withOriginalIpAddress('123', $originalIpAddress);
|
$event = UrlVisited::withOriginalIpAddress('123', $originalIpAddress);
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->em->expects($this->once())->method('flush');
|
$this->em->expects($this->once())->method('flush');
|
||||||
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
|
||||||
$this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with(
|
$this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with($ipAddr)->willReturn(
|
||||||
$this->equalTo($ipAddr),
|
$location,
|
||||||
)->willReturn($location);
|
|
||||||
|
|
||||||
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
|
|
||||||
$this->equalTo(new VisitLocated('123')),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
|
|
||||||
($this->locateVisit)($event);
|
($this->locateVisit)($event);
|
||||||
|
|
|
@ -42,15 +42,12 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function messageIsLoggedWhenShortUrlIsNotFound(): void
|
public function messageIsLoggedWhenShortUrlIsNotFound(): void
|
||||||
{
|
{
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn(null);
|
||||||
$this->equalTo(ShortUrl::class),
|
|
||||||
$this->equalTo('123'),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->helper->expects($this->never())->method('publishUpdate');
|
$this->helper->expects($this->never())->method('publishUpdate');
|
||||||
$this->updatesGenerator->expects($this->never())->method('newShortUrlUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newShortUrlUpdate');
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$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.'),
|
'Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.',
|
||||||
$this->equalTo(['shortUrlId' => '123', 'name' => 'Mercure']),
|
['shortUrlId' => '123', 'name' => 'Mercure'],
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
|
|
||||||
|
@ -63,14 +60,11 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
||||||
$shortUrl = ShortUrl::withLongUrl('');
|
$shortUrl = ShortUrl::withLongUrl('');
|
||||||
$update = Update::forTopicAndPayload('', []);
|
$update = Update::forTopicAndPayload('', []);
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn($shortUrl);
|
||||||
$this->equalTo(ShortUrl::class),
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with($shortUrl)->willReturn(
|
||||||
$this->equalTo('123'),
|
$update,
|
||||||
)->willReturn($shortUrl);
|
);
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update);
|
||||||
$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('warning');
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
|
|
||||||
|
@ -85,19 +79,17 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
||||||
$e = new Exception('Error');
|
$e = new Exception('Error');
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(
|
||||||
$this->equalTo(ShortUrl::class),
|
ShortUrl::class,
|
||||||
$this->equalTo('123'),
|
'123',
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with($shortUrl)->willReturn(
|
||||||
$this->equalTo($shortUrl),
|
$update,
|
||||||
)->willReturn($update);
|
);
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
|
||||||
$this->equalTo($update),
|
|
||||||
)->willThrowException($e);
|
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
|
'Error while trying to notify {name} with new short URL. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
|
['e' => $e, 'name' => 'Mercure'],
|
||||||
);
|
);
|
||||||
|
|
||||||
($this->listener)(new ShortUrlCreated('123'));
|
($this->listener)(new ShortUrlCreated('123'));
|
||||||
|
|
|
@ -41,13 +41,10 @@ class NotifyVisitToMercureTest extends TestCase
|
||||||
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
||||||
{
|
{
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(null);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$this->logger->expects($this->once())->method('warning')->with(
|
||||||
$this->equalTo('Tried to notify {name} for visit with id "{visitId}", but it does not exist.'),
|
'Tried to notify {name} for visit with id "{visitId}", but it does not exist.',
|
||||||
$this->equalTo(['visitId' => $visitId, 'name' => 'Mercure']),
|
['visitId' => $visitId, 'name' => 'Mercure'],
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
|
||||||
|
@ -65,20 +62,15 @@ class NotifyVisitToMercureTest extends TestCase
|
||||||
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance());
|
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance());
|
||||||
$update = Update::forTopicAndPayload('', []);
|
$update = Update::forTopicAndPayload('', []);
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with($visit)->willReturn(
|
||||||
$this->equalTo($visit),
|
$update,
|
||||||
)->willReturn($update);
|
);
|
||||||
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
||||||
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update);
|
||||||
$this->equalTo($visit),
|
$this->helper->expects($this->exactly(2))->method('publishUpdate')->with($update);
|
||||||
)->willReturn($update);
|
|
||||||
$this->helper->expects($this->exactly(2))->method('publishUpdate')->with($this->equalTo($update));
|
|
||||||
|
|
||||||
($this->listener)(new VisitLocated($visitId));
|
($this->listener)(new VisitLocated($visitId));
|
||||||
}
|
}
|
||||||
|
@ -91,25 +83,18 @@ class NotifyVisitToMercureTest extends TestCase
|
||||||
$update = Update::forTopicAndPayload('', []);
|
$update = Update::forTopicAndPayload('', []);
|
||||||
$e = new RuntimeException('Error');
|
$e = new RuntimeException('Error');
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
|
'Error while trying to notify {name} with new visit. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
|
['e' => $e, 'name' => 'Mercure'],
|
||||||
|
);
|
||||||
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with($visit)->willReturn(
|
||||||
|
$update,
|
||||||
);
|
);
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with(
|
|
||||||
$this->equalTo($visit),
|
|
||||||
)->willReturn($update);
|
|
||||||
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
|
||||||
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update);
|
||||||
$this->equalTo($visit),
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
|
||||||
)->willReturn($update);
|
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
|
||||||
$this->equalTo($update),
|
|
||||||
)->willThrowException($e);
|
|
||||||
|
|
||||||
($this->listener)(new VisitLocated($visitId));
|
($this->listener)(new VisitLocated($visitId));
|
||||||
}
|
}
|
||||||
|
@ -123,18 +108,15 @@ class NotifyVisitToMercureTest extends TestCase
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$update = Update::forTopicAndPayload('', []);
|
$update = Update::forTopicAndPayload('', []);
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
|
||||||
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with($visit)->willReturn(
|
||||||
$this->equalTo($visit),
|
$update,
|
||||||
)->willReturn($update);
|
);
|
||||||
$this->updatesGenerator->expects($this->never())->method('newVisitUpdate');
|
$this->updatesGenerator->expects($this->never())->method('newVisitUpdate');
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with($this->equalTo($update));
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update);
|
||||||
|
|
||||||
($this->listener)(new VisitLocated($visitId));
|
($this->listener)(new VisitLocated($visitId));
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,14 +52,11 @@ class NotifyVisitToWebHooksTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function invalidVisitDoesNotPerformAnyRequest(): void
|
public function invalidVisitDoesNotPerformAnyRequest(): void
|
||||||
{
|
{
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn(null);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo('1'),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->httpClient->expects($this->never())->method('requestAsync');
|
$this->httpClient->expects($this->never())->method('requestAsync');
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$this->logger->expects($this->once())->method('warning')->with(
|
||||||
$this->equalTo('Tried to notify webhooks for visit with id "{visitId}", but it does not exist.'),
|
'Tried to notify webhooks for visit with id "{visitId}", but it does not exist.',
|
||||||
$this->equalTo(['visitId' => '1']),
|
['visitId' => '1'],
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->createListener(['foo', 'bar'])(new VisitLocated('1'));
|
$this->createListener(['foo', 'bar'])(new VisitLocated('1'));
|
||||||
|
@ -68,10 +65,9 @@ class NotifyVisitToWebHooksTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function orphanVisitDoesNotPerformAnyRequestWhenDisabled(): void
|
public function orphanVisitDoesNotPerformAnyRequestWhenDisabled(): void
|
||||||
{
|
{
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forBasePath(Visitor::emptyInstance()),
|
||||||
$this->equalTo('1'),
|
);
|
||||||
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
|
||||||
$this->httpClient->expects($this->never())->method('requestAsync');
|
$this->httpClient->expects($this->never())->method('requestAsync');
|
||||||
$this->logger->expects($this->never())->method('warning');
|
$this->logger->expects($this->never())->method('warning');
|
||||||
|
|
||||||
|
@ -87,12 +83,9 @@ class NotifyVisitToWebHooksTest extends TestCase
|
||||||
$webhooks = ['foo', 'invalid', 'bar', 'baz'];
|
$webhooks = ['foo', 'invalid', 'bar', 'baz'];
|
||||||
$invalidWebhooks = ['invalid', 'baz'];
|
$invalidWebhooks = ['invalid', 'baz'];
|
||||||
|
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo('1'),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$this->httpClient->expects($this->exactly(count($webhooks)))->method('requestAsync')->with(
|
$this->httpClient->expects($this->exactly(count($webhooks)))->method('requestAsync')->with(
|
||||||
$this->equalTo(RequestMethodInterface::METHOD_POST),
|
RequestMethodInterface::METHOD_POST,
|
||||||
$this->istype('string'),
|
$this->istype('string'),
|
||||||
$this->callback(function (array $requestOptions) use ($expectedResponseKeys) {
|
$this->callback(function (array $requestOptions) use ($expectedResponseKeys) {
|
||||||
Assert::assertArrayHasKey(RequestOptions::HEADERS, $requestOptions);
|
Assert::assertArrayHasKey(RequestOptions::HEADERS, $requestOptions);
|
||||||
|
@ -114,7 +107,7 @@ class NotifyVisitToWebHooksTest extends TestCase
|
||||||
return $shouldReject ? new RejectedPromise(new Exception('')) : new FulfilledPromise('');
|
return $shouldReject ? new RejectedPromise(new Exception('')) : new FulfilledPromise('');
|
||||||
});
|
});
|
||||||
$this->logger->expects($this->exactly(count($invalidWebhooks)))->method('warning')->with(
|
$this->logger->expects($this->exactly(count($invalidWebhooks)))->method('warning')->with(
|
||||||
$this->equalTo('Failed to notify visit with id "{visitId}" to webhook "{webhook}". {e}'),
|
'Failed to notify visit with id "{visitId}" to webhook "{webhook}". {e}',
|
||||||
$this->callback(function (array $extra): bool {
|
$this->callback(function (array $extra): bool {
|
||||||
Assert::assertArrayHasKey('webhook', $extra);
|
Assert::assertArrayHasKey('webhook', $extra);
|
||||||
Assert::assertArrayHasKey('visitId', $extra);
|
Assert::assertArrayHasKey('visitId', $extra);
|
||||||
|
|
|
@ -51,13 +51,10 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
|
||||||
public function notificationsAreNotSentWhenShortUrlCannotBeFound(): void
|
public function notificationsAreNotSentWhenShortUrlCannotBeFound(): void
|
||||||
{
|
{
|
||||||
$shortUrlId = '123';
|
$shortUrlId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(null);
|
||||||
$this->equalTo(ShortUrl::class),
|
|
||||||
$this->equalTo($shortUrlId),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$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.'),
|
'Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.',
|
||||||
$this->equalTo(['shortUrlId' => $shortUrlId, 'name' => 'RabbitMQ']),
|
['shortUrlId' => $shortUrlId, 'name' => 'RabbitMQ'],
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
$this->helper->expects($this->never())->method('publishUpdate');
|
$this->helper->expects($this->never())->method('publishUpdate');
|
||||||
|
@ -70,14 +67,13 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortUrlId = '123';
|
$shortUrlId = '123';
|
||||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||||
$this->equalTo(ShortUrl::class),
|
ShortUrl::withLongUrl(''),
|
||||||
$this->equalTo($shortUrlId),
|
);
|
||||||
)->willReturn(ShortUrl::withLongUrl(''));
|
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||||
$this->isInstanceOf(ShortUrl::class),
|
$this->isInstanceOf(ShortUrl::class),
|
||||||
)->willReturn($update);
|
)->willReturn($update);
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with($this->equalTo($update));
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update);
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
|
|
||||||
($this->listener())(new ShortUrlCreated($shortUrlId));
|
($this->listener())(new ShortUrlCreated($shortUrlId));
|
||||||
|
@ -91,19 +87,16 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortUrlId = '123';
|
$shortUrlId = '123';
|
||||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||||
$this->equalTo(ShortUrl::class),
|
ShortUrl::withLongUrl(''),
|
||||||
$this->equalTo($shortUrlId),
|
);
|
||||||
)->willReturn(ShortUrl::withLongUrl(''));
|
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||||
$this->isInstanceOf(ShortUrl::class),
|
$this->isInstanceOf(ShortUrl::class),
|
||||||
)->willReturn($update);
|
)->willReturn($update);
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
|
||||||
$this->equalTo($update),
|
|
||||||
)->willThrowException($e);
|
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
|
'Error while trying to notify {name} with new short URL. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'RabbitMQ']),
|
['e' => $e, 'name' => 'RabbitMQ'],
|
||||||
);
|
);
|
||||||
|
|
||||||
($this->listener())(new ShortUrlCreated($shortUrlId));
|
($this->listener())(new ShortUrlCreated($shortUrlId));
|
||||||
|
|
|
@ -59,13 +59,10 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||||
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
|
||||||
{
|
{
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(null);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn(null);
|
|
||||||
$this->logger->expects($this->once())->method('warning')->with(
|
$this->logger->expects($this->once())->method('warning')->with(
|
||||||
$this->equalTo('Tried to notify {name} for visit with id "{visitId}", but it does not exist.'),
|
'Tried to notify {name} for visit with id "{visitId}", but it does not exist.',
|
||||||
$this->equalTo(['visitId' => $visitId, 'name' => 'RabbitMQ']),
|
['visitId' => $visitId, 'name' => 'RabbitMQ'],
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->never())->method('debug');
|
$this->logger->expects($this->never())->method('debug');
|
||||||
$this->helper->expects($this->never())->method('publishUpdate');
|
$this->helper->expects($this->never())->method('publishUpdate');
|
||||||
|
@ -80,10 +77,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||||
public function expectedChannelsAreNotifiedBasedOnTheVisitType(Visit $visit, array $expectedChannels): void
|
public function expectedChannelsAreNotifiedBasedOnTheVisitType(Visit $visit, array $expectedChannels): void
|
||||||
{
|
{
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn($visit);
|
|
||||||
each($expectedChannels, function (string $method): void {
|
each($expectedChannels, function (string $method): void {
|
||||||
$this->updatesGenerator->expects($this->once())->method($method)->with(
|
$this->updatesGenerator->expects($this->once())->method($method)->with(
|
||||||
$this->isInstanceOf(Visit::class),
|
$this->isInstanceOf(Visit::class),
|
||||||
|
@ -121,17 +115,16 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||||
public function printsDebugMessageInCaseOfError(Throwable $e): void
|
public function printsDebugMessageInCaseOfError(Throwable $e): void
|
||||||
{
|
{
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forBasePath(Visitor::emptyInstance()),
|
||||||
$this->equalTo($visitId),
|
);
|
||||||
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
|
||||||
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
|
||||||
$this->isInstanceOf(Visit::class),
|
$this->isInstanceOf(Visit::class),
|
||||||
)->willReturn(Update::forTopicAndPayload('', []));
|
)->willReturn(Update::forTopicAndPayload('', []));
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
|
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
|
'Error while trying to notify {name} with new visit. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'RabbitMQ']),
|
['e' => $e, 'name' => 'RabbitMQ'],
|
||||||
);
|
);
|
||||||
|
|
||||||
($this->listener())(new VisitLocated($visitId));
|
($this->listener())(new VisitLocated($visitId));
|
||||||
|
@ -155,10 +148,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||||
callable $expect,
|
callable $expect,
|
||||||
): void {
|
): void {
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
|
||||||
$this->equalTo(Visit::class),
|
|
||||||
$this->equalTo($visitId),
|
|
||||||
)->willReturn($visit);
|
|
||||||
$setup($this->updatesGenerator);
|
$setup($this->updatesGenerator);
|
||||||
$expect($this->helper, $this->updatesGenerator);
|
$expect($this->helper, $this->updatesGenerator);
|
||||||
|
|
||||||
|
|
|
@ -54,19 +54,16 @@ class NotifyNewShortUrlToRedisTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortUrlId = '123';
|
$shortUrlId = '123';
|
||||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||||
$this->equalTo(ShortUrl::class),
|
ShortUrl::withLongUrl(''),
|
||||||
$this->equalTo($shortUrlId),
|
);
|
||||||
)->willReturn(ShortUrl::withLongUrl(''));
|
|
||||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||||
$this->isInstanceOf(ShortUrl::class),
|
$this->isInstanceOf(ShortUrl::class),
|
||||||
)->willReturn($update);
|
)->willReturn($update);
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->with(
|
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
|
||||||
$this->equalTo($update),
|
|
||||||
)->willThrowException($e);
|
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
|
'Error while trying to notify {name} with new short URL. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'Redis pub/sub']),
|
['e' => $e, 'name' => 'Redis pub/sub'],
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->createListener()(new ShortUrlCreated($shortUrlId));
|
$this->createListener()(new ShortUrlCreated($shortUrlId));
|
||||||
|
|
|
@ -53,17 +53,16 @@ class NotifyVisitToRedisTest extends TestCase
|
||||||
public function printsDebugMessageInCaseOfError(Throwable $e): void
|
public function printsDebugMessageInCaseOfError(Throwable $e): void
|
||||||
{
|
{
|
||||||
$visitId = '123';
|
$visitId = '123';
|
||||||
$this->em->expects($this->once())->method('find')->with(
|
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(
|
||||||
$this->equalTo(Visit::class),
|
Visit::forBasePath(Visitor::emptyInstance()),
|
||||||
$this->equalTo($visitId),
|
);
|
||||||
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
|
|
||||||
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
|
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
|
||||||
$this->isInstanceOf(Visit::class),
|
$this->isInstanceOf(Visit::class),
|
||||||
)->willReturn(Update::forTopicAndPayload('', []));
|
)->willReturn(Update::forTopicAndPayload('', []));
|
||||||
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
|
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
|
||||||
$this->logger->expects($this->once())->method('debug')->with(
|
$this->logger->expects($this->once())->method('debug')->with(
|
||||||
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
|
'Error while trying to notify {name} with new visit. {e}',
|
||||||
$this->equalTo(['e' => $e, 'name' => 'Redis pub/sub']),
|
['e' => $e, 'name' => 'Redis pub/sub'],
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->createListener()(new VisitLocated($visitId));
|
$this->createListener()(new VisitLocated($visitId));
|
||||||
|
|
|
@ -39,8 +39,8 @@ class UpdateGeoLiteDbTest extends TestCase
|
||||||
|
|
||||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willThrowException($e);
|
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willThrowException($e);
|
||||||
$this->logger->expects($this->once())->method('error')->with(
|
$this->logger->expects($this->once())->method('error')->with(
|
||||||
$this->equalTo('GeoLite2 database download failed. {e}'),
|
'GeoLite2 database download failed. {e}',
|
||||||
$this->equalTo(['e' => $e]),
|
['e' => $e],
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->never())->method('notice');
|
$this->logger->expects($this->never())->method('notice');
|
||||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||||
|
@ -60,7 +60,7 @@ class UpdateGeoLiteDbTest extends TestCase
|
||||||
return GeolocationResult::DB_IS_UP_TO_DATE;
|
return GeolocationResult::DB_IS_UP_TO_DATE;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
$this->logger->expects($this->once())->method('notice')->with($this->equalTo($expectedMessage));
|
$this->logger->expects($this->once())->method('notice')->with($expectedMessage);
|
||||||
$this->logger->expects($this->never())->method('error');
|
$this->logger->expects($this->never())->method('error');
|
||||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ class UpdateGeoLiteDbTest extends TestCase
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
$logNoticeExpectation = $expectedMessage !== null ? $this->once() : $this->never();
|
$logNoticeExpectation = $expectedMessage !== null ? $this->once() : $this->never();
|
||||||
$this->logger->expects($logNoticeExpectation)->method('notice')->with($this->equalTo($expectedMessage));
|
$this->logger->expects($logNoticeExpectation)->method('notice')->with($expectedMessage);
|
||||||
$this->logger->expects($this->never())->method('error');
|
$this->logger->expects($this->never())->method('error');
|
||||||
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
$this->eventDispatcher->expects($this->never())->method('dispatch');
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class UpdateGeoLiteDbTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturn($result);
|
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturn($result);
|
||||||
$this->eventDispatcher->expects($this->exactly($expectedDispatches))->method('dispatch')->with(
|
$this->eventDispatcher->expects($this->exactly($expectedDispatches))->method('dispatch')->with(
|
||||||
$this->equalTo(new GeoLiteDbCreated()),
|
new GeoLiteDbCreated(),
|
||||||
);
|
);
|
||||||
|
|
||||||
($this->listener)();
|
($this->listener)();
|
||||||
|
|
|
@ -41,7 +41,7 @@ class ImportedLinksProcessorTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
||||||
$this->em->method('getRepository')->with($this->equalTo(ShortUrl::class))->willReturn($this->repo);
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
|
|
||||||
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
|
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
|
||||||
$batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);
|
$batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);
|
||||||
|
|
|
@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException;
|
use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException;
|
||||||
use Shlinkio\Shlink\Core\Options\DeleteShortUrlsOptions;
|
use Shlinkio\Shlink\Core\Options\DeleteShortUrlsOptions;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlService;
|
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlService;
|
||||||
|
@ -25,10 +23,8 @@ use function sprintf;
|
||||||
|
|
||||||
class DeleteShortUrlServiceTest extends TestCase
|
class DeleteShortUrlServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
private MockObject $em;
|
||||||
|
private MockObject $urlResolver;
|
||||||
private ObjectProphecy $em;
|
|
||||||
private ObjectProphecy $urlResolver;
|
|
||||||
private string $shortCode;
|
private string $shortCode;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
|
@ -38,10 +34,10 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
));
|
));
|
||||||
$this->shortCode = $shortUrl->getShortCode();
|
$this->shortCode = $shortUrl->getShortCode();
|
||||||
|
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
|
|
||||||
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
|
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
|
||||||
$this->urlResolver->resolveShortUrl(Argument::cetera())->willReturn($shortUrl);
|
$this->urlResolver->method('resolveShortUrl')->willReturn($shortUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -63,13 +59,12 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$service = $this->createService();
|
$service = $this->createService();
|
||||||
|
|
||||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
|
||||||
$flush = $this->em->flush()->willReturn(null);
|
null,
|
||||||
|
);
|
||||||
|
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
|
||||||
|
|
||||||
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode), true);
|
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode), true);
|
||||||
|
|
||||||
$remove->shouldHaveBeenCalledOnce();
|
|
||||||
$flush->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -77,13 +72,12 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$service = $this->createService(false);
|
$service = $this->createService(false);
|
||||||
|
|
||||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
|
||||||
$flush = $this->em->flush()->willReturn(null);
|
null,
|
||||||
|
);
|
||||||
|
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
|
||||||
|
|
||||||
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
|
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
|
||||||
|
|
||||||
$remove->shouldHaveBeenCalledOnce();
|
|
||||||
$flush->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -91,20 +85,19 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$service = $this->createService(true, 100);
|
$service = $this->createService(true, 100);
|
||||||
|
|
||||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
|
||||||
$flush = $this->em->flush()->willReturn(null);
|
null,
|
||||||
|
);
|
||||||
|
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
|
||||||
|
|
||||||
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
|
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
|
||||||
|
|
||||||
$remove->shouldHaveBeenCalledOnce();
|
|
||||||
$flush->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createService(bool $checkVisitsThreshold = true, int $visitsThreshold = 5): DeleteShortUrlService
|
private function createService(bool $checkVisitsThreshold = true, int $visitsThreshold = 5): DeleteShortUrlService
|
||||||
{
|
{
|
||||||
return new DeleteShortUrlService($this->em->reveal(), new DeleteShortUrlsOptions(
|
return new DeleteShortUrlService($this->em, new DeleteShortUrlsOptions(
|
||||||
$visitsThreshold,
|
$visitsThreshold,
|
||||||
$checkVisitsThreshold,
|
$checkVisitsThreshold,
|
||||||
), $this->urlResolver->reveal());
|
), $this->urlResolver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,8 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
|
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
|
||||||
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortCodeUniquenessHelper;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortCodeUniquenessHelper;
|
||||||
|
@ -16,19 +15,17 @@ use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlRepository;
|
||||||
|
|
||||||
class ShortCodeUniquenessHelperTest extends TestCase
|
class ShortCodeUniquenessHelperTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private ShortCodeUniquenessHelper $helper;
|
private ShortCodeUniquenessHelper $helper;
|
||||||
private ObjectProphecy $em;
|
private MockObject $em;
|
||||||
private ObjectProphecy $shortUrl;
|
private MockObject $shortUrl;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->helper = new ShortCodeUniquenessHelper($this->em->reveal());
|
$this->helper = new ShortCodeUniquenessHelper($this->em);
|
||||||
|
|
||||||
$this->shortUrl = $this->prophesize(ShortUrl::class);
|
$this->shortUrl = $this->createMock(ShortUrl::class);
|
||||||
$this->shortUrl->getShortCode()->willReturn('abc123');
|
$this->shortUrl->method('getShortCode')->willReturn('abc123');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,22 +36,22 @@ class ShortCodeUniquenessHelperTest extends TestCase
|
||||||
{
|
{
|
||||||
$callIndex = 0;
|
$callIndex = 0;
|
||||||
$expectedCalls = 3;
|
$expectedCalls = 3;
|
||||||
$repo = $this->prophesize(ShortUrlRepository::class);
|
$repo = $this->createMock(ShortUrlRepository::class);
|
||||||
$shortCodeIsInUse = $repo->shortCodeIsInUseWithLock(
|
$repo->expects($this->exactly($expectedCalls))->method('shortCodeIsInUseWithLock')->with(
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain('abc123', $expectedAuthority),
|
ShortUrlIdentifier::fromShortCodeAndDomain('abc123', $expectedAuthority),
|
||||||
)->will(function () use (&$callIndex, $expectedCalls) {
|
)->willReturnCallback(function () use (&$callIndex, $expectedCalls) {
|
||||||
$callIndex++;
|
$callIndex++;
|
||||||
return $callIndex < $expectedCalls;
|
return $callIndex < $expectedCalls;
|
||||||
});
|
});
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->expects($this->exactly($expectedCalls))->method('getRepository')->with(ShortUrl::class)->willReturn(
|
||||||
$this->shortUrl->getDomain()->willReturn($domain);
|
$repo,
|
||||||
|
);
|
||||||
|
$this->shortUrl->method('getDomain')->willReturn($domain);
|
||||||
|
$this->shortUrl->expects($this->exactly($expectedCalls - 1))->method('regenerateShortCode')->with();
|
||||||
|
|
||||||
$result = $this->helper->ensureShortCodeUniqueness($this->shortUrl->reveal(), false);
|
$result = $this->helper->ensureShortCodeUniqueness($this->shortUrl, false);
|
||||||
|
|
||||||
self::assertTrue($result);
|
self::assertTrue($result);
|
||||||
$this->shortUrl->regenerateShortCode()->shouldHaveBeenCalledTimes($expectedCalls - 1);
|
|
||||||
$getRepo->shouldBeCalledTimes($expectedCalls);
|
|
||||||
$shortCodeIsInUse->shouldBeCalledTimes($expectedCalls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideDomains(): iterable
|
public function provideDomains(): iterable
|
||||||
|
@ -66,18 +63,16 @@ class ShortCodeUniquenessHelperTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function inUseSlugReturnsError(): void
|
public function inUseSlugReturnsError(): void
|
||||||
{
|
{
|
||||||
$repo = $this->prophesize(ShortUrlRepository::class);
|
$repo = $this->createMock(ShortUrlRepository::class);
|
||||||
$shortCodeIsInUse = $repo->shortCodeIsInUseWithLock(
|
$repo->expects($this->once())->method('shortCodeIsInUseWithLock')->with(
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
||||||
)->willReturn(true);
|
)->willReturn(true);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
|
||||||
$this->shortUrl->getDomain()->willReturn(null);
|
$this->shortUrl->method('getDomain')->willReturn(null);
|
||||||
|
$this->shortUrl->expects($this->never())->method('regenerateShortCode');
|
||||||
|
|
||||||
$result = $this->helper->ensureShortCodeUniqueness($this->shortUrl->reveal(), true);
|
$result = $this->helper->ensureShortCodeUniqueness($this->shortUrl, true);
|
||||||
|
|
||||||
self::assertFalse($result);
|
self::assertFalse($result);
|
||||||
$this->shortUrl->regenerateShortCode()->shouldNotHaveBeenCalled();
|
|
||||||
$getRepo->shouldBeCalledOnce();
|
|
||||||
$shortCodeIsInUse->shouldBeCalledOnce();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,21 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
|
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelper;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelper;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
||||||
use Shlinkio\Shlink\Core\Util\UrlValidatorInterface;
|
use Shlinkio\Shlink\Core\Util\UrlValidatorInterface;
|
||||||
|
|
||||||
class ShortUrlTitleResolutionHelperTest extends TestCase
|
class ShortUrlTitleResolutionHelperTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private ShortUrlTitleResolutionHelper $helper;
|
private ShortUrlTitleResolutionHelper $helper;
|
||||||
private ObjectProphecy $urlValidator;
|
private MockObject $urlValidator;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->urlValidator = $this->prophesize(UrlValidatorInterface::class);
|
$this->urlValidator = $this->createMock(UrlValidatorInterface::class);
|
||||||
$this->helper = new ShortUrlTitleResolutionHelper($this->urlValidator->reveal());
|
$this->helper = new ShortUrlTitleResolutionHelper($this->urlValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,14 +28,18 @@ class ShortUrlTitleResolutionHelperTest extends TestCase
|
||||||
public function urlIsProperlyShortened(?string $title, int $validateWithTitleCallsNum, int $validateCallsNum): void
|
public function urlIsProperlyShortened(?string $title, int $validateWithTitleCallsNum, int $validateCallsNum): void
|
||||||
{
|
{
|
||||||
$longUrl = 'http://foobar.com/12345/hello?foo=bar';
|
$longUrl = 'http://foobar.com/12345/hello?foo=bar';
|
||||||
|
$this->urlValidator->expects($this->exactly($validateWithTitleCallsNum))->method('validateUrlWithTitle')->with(
|
||||||
|
$longUrl,
|
||||||
|
$this->isFalse(),
|
||||||
|
);
|
||||||
|
$this->urlValidator->expects($this->exactly($validateCallsNum))->method('validateUrl')->with(
|
||||||
|
$longUrl,
|
||||||
|
$this->isFalse(),
|
||||||
|
);
|
||||||
|
|
||||||
$this->helper->processTitleAndValidateUrl(
|
$this->helper->processTitleAndValidateUrl(
|
||||||
ShortUrlCreation::fromRawData(['longUrl' => $longUrl, 'title' => $title]),
|
ShortUrlCreation::fromRawData(['longUrl' => $longUrl, 'title' => $title]),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->urlValidator->validateUrlWithTitle($longUrl, false)->shouldHaveBeenCalledTimes(
|
|
||||||
$validateWithTitleCallsNum,
|
|
||||||
);
|
|
||||||
$this->urlValidator->validateUrl($longUrl, false)->shouldHaveBeenCalledTimes($validateCallsNum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideTitles(): iterable
|
public function provideTitles(): iterable
|
||||||
|
|
|
@ -9,10 +9,8 @@ use Laminas\Diactoros\ServerRequestFactory;
|
||||||
use Laminas\Diactoros\Uri;
|
use Laminas\Diactoros\Uri;
|
||||||
use Mezzio\Router\Route;
|
use Mezzio\Router\Route;
|
||||||
use Mezzio\Router\RouteResult;
|
use Mezzio\Router\RouteResult;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
@ -32,22 +30,20 @@ use function str_starts_with;
|
||||||
|
|
||||||
class ExtraPathRedirectMiddlewareTest extends TestCase
|
class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
private MockObject $resolver;
|
||||||
|
private MockObject $requestTracker;
|
||||||
private ObjectProphecy $resolver;
|
private MockObject $redirectionBuilder;
|
||||||
private ObjectProphecy $requestTracker;
|
private MockObject $redirectResponseHelper;
|
||||||
private ObjectProphecy $redirectionBuilder;
|
private MockObject $handler;
|
||||||
private ObjectProphecy $redirectResponseHelper;
|
|
||||||
private ObjectProphecy $handler;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->resolver = $this->prophesize(ShortUrlResolverInterface::class);
|
$this->resolver = $this->createMock(ShortUrlResolverInterface::class);
|
||||||
$this->requestTracker = $this->prophesize(RequestTrackerInterface::class);
|
$this->requestTracker = $this->createMock(RequestTrackerInterface::class);
|
||||||
$this->redirectionBuilder = $this->prophesize(ShortUrlRedirectionBuilderInterface::class);
|
$this->redirectionBuilder = $this->createMock(ShortUrlRedirectionBuilderInterface::class);
|
||||||
$this->redirectResponseHelper = $this->prophesize(RedirectResponseHelperInterface::class);
|
$this->redirectResponseHelper = $this->createMock(RedirectResponseHelperInterface::class);
|
||||||
$this->handler = $this->prophesize(RequestHandlerInterface::class);
|
$this->handler = $this->createMock(RequestHandlerInterface::class);
|
||||||
$this->handler->handle(Argument::cetera())->willReturn(new RedirectResponse(''));
|
$this->handler->method('handle')->willReturn(new RedirectResponse(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,14 +59,13 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
appendExtraPath: $appendExtraPath,
|
appendExtraPath: $appendExtraPath,
|
||||||
multiSegmentSlugsEnabled: $multiSegmentEnabled,
|
multiSegmentSlugsEnabled: $multiSegmentEnabled,
|
||||||
);
|
);
|
||||||
|
$this->resolver->expects($this->never())->method('resolveEnabledShortUrl');
|
||||||
|
$this->requestTracker->expects($this->never())->method('trackIfApplicable');
|
||||||
|
$this->redirectionBuilder->expects($this->never())->method('buildShortUrlRedirect');
|
||||||
|
$this->redirectResponseHelper->expects($this->never())->method('buildRedirectResponse');
|
||||||
|
$this->handler->expects($this->once())->method('handle');
|
||||||
|
|
||||||
$this->middleware($options)->process($request, $this->handler->reveal());
|
$this->middleware($options)->process($request, $this->handler);
|
||||||
|
|
||||||
$this->handler->handle($request)->shouldHaveBeenCalledOnce();
|
|
||||||
$this->resolver->resolveEnabledShortUrl(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->redirectionBuilder->buildShortUrlRedirect(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->redirectResponseHelper->buildRedirectResponse(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideNonRedirectingRequests(): iterable
|
public function provideNonRedirectingRequests(): iterable
|
||||||
|
@ -89,7 +84,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
RouteResult::class,
|
RouteResult::class,
|
||||||
RouteResult::fromRoute(new Route(
|
RouteResult::fromRoute(new Route(
|
||||||
'/foo',
|
'/foo',
|
||||||
$this->prophesize(MiddlewareInterface::class)->reveal(),
|
$this->createMock(MiddlewareInterface::class),
|
||||||
['GET'],
|
['GET'],
|
||||||
RedirectAction::class,
|
RedirectAction::class,
|
||||||
)),
|
)),
|
||||||
|
@ -115,22 +110,20 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
|
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
|
||||||
|
|
||||||
$type = $this->prophesize(NotFoundType::class);
|
$type = $this->createMock(NotFoundType::class);
|
||||||
$type->isRegularNotFound()->willReturn(true);
|
$type->method('isRegularNotFound')->willReturn(true);
|
||||||
$type->isInvalidShortUrl()->willReturn(true);
|
$type->method('isInvalidShortUrl')->willReturn(true);
|
||||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
|
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type)
|
||||||
->withUri(new Uri('/shortCode/bar/baz'));
|
->withUri(new Uri('/shortCode/bar/baz'));
|
||||||
|
|
||||||
$resolve = $this->resolver->resolveEnabledShortUrl(
|
$this->resolver->expects($this->exactly($expectedResolveCalls))->method('resolveEnabledShortUrl')->with(
|
||||||
Argument::that(fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode')),
|
$this->callback(fn (ShortUrlIdentifier $id) => str_starts_with($id->shortCode, 'shortCode')),
|
||||||
)->willThrow(ShortUrlNotFoundException::class);
|
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
|
||||||
|
$this->requestTracker->expects($this->never())->method('trackIfApplicable');
|
||||||
|
$this->redirectionBuilder->expects($this->never())->method('buildShortUrlRedirect');
|
||||||
|
$this->redirectResponseHelper->expects($this->never())->method('buildRedirectResponse');
|
||||||
|
|
||||||
$this->middleware($options)->process($request, $this->handler->reveal());
|
$this->middleware($options)->process($request, $this->handler);
|
||||||
|
|
||||||
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
|
|
||||||
$this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->redirectionBuilder->buildShortUrlRedirect(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->redirectResponseHelper->buildRedirectResponse(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,18 +137,17 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
): void {
|
): void {
|
||||||
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
|
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
|
||||||
|
|
||||||
$type = $this->prophesize(NotFoundType::class);
|
$type = $this->createMock(NotFoundType::class);
|
||||||
$type->isRegularNotFound()->willReturn(true);
|
$type->method('isRegularNotFound')->willReturn(true);
|
||||||
$type->isInvalidShortUrl()->willReturn(true);
|
$type->method('isInvalidShortUrl')->willReturn(true);
|
||||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
|
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type)
|
||||||
->withUri(new Uri('https://doma.in/shortCode/bar/baz'));
|
->withUri(new Uri('https://doma.in/shortCode/bar/baz'));
|
||||||
$shortUrl = ShortUrl::withLongUrl('');
|
$shortUrl = ShortUrl::withLongUrl('');
|
||||||
$identifier = Argument::that(
|
|
||||||
fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode'),
|
|
||||||
);
|
|
||||||
|
|
||||||
$currentIteration = 1;
|
$currentIteration = 1;
|
||||||
$resolve = $this->resolver->resolveEnabledShortUrl($identifier)->will(
|
$this->resolver->expects($this->exactly($expectedResolveCalls))->method('resolveEnabledShortUrl')->with(
|
||||||
|
$this->callback(fn (ShortUrlIdentifier $id) => str_starts_with($id->shortCode, 'shortCode')),
|
||||||
|
)->willReturnCallback(
|
||||||
function () use ($shortUrl, &$currentIteration, $expectedResolveCalls): ShortUrl {
|
function () use ($shortUrl, &$currentIteration, $expectedResolveCalls): ShortUrl {
|
||||||
if ($expectedResolveCalls === $currentIteration) {
|
if ($expectedResolveCalls === $currentIteration) {
|
||||||
return $shortUrl;
|
return $shortUrl;
|
||||||
|
@ -165,18 +157,17 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
throw ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortUrl($shortUrl));
|
throw ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortUrl($shortUrl));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
$buildLongUrl = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, [], $expectedExtraPath)
|
$this->redirectionBuilder->expects($this->once())->method('buildShortUrlRedirect')->with(
|
||||||
->willReturn('the_built_long_url');
|
$shortUrl,
|
||||||
$buildResp = $this->redirectResponseHelper->buildRedirectResponse('the_built_long_url')->willReturn(
|
[],
|
||||||
new RedirectResponse(''),
|
$expectedExtraPath,
|
||||||
);
|
)->willReturn('the_built_long_url');
|
||||||
|
$this->redirectResponseHelper->expects($this->once())->method('buildRedirectResponse')->with(
|
||||||
|
'the_built_long_url',
|
||||||
|
)->willReturn(new RedirectResponse(''));
|
||||||
|
$this->requestTracker->expects($this->once())->method('trackIfApplicable')->with($shortUrl, $request);
|
||||||
|
|
||||||
$this->middleware($options)->process($request, $this->handler->reveal());
|
$this->middleware($options)->process($request, $this->handler);
|
||||||
|
|
||||||
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
|
|
||||||
$buildLongUrl->shouldHaveBeenCalledOnce();
|
|
||||||
$buildResp->shouldHaveBeenCalledOnce();
|
|
||||||
$this->requestTracker->trackIfApplicable($shortUrl, $request)->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideResolves(): iterable
|
public function provideResolves(): iterable
|
||||||
|
@ -188,10 +179,10 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||||
private function middleware(?UrlShortenerOptions $options = null): ExtraPathRedirectMiddleware
|
private function middleware(?UrlShortenerOptions $options = null): ExtraPathRedirectMiddleware
|
||||||
{
|
{
|
||||||
return new ExtraPathRedirectMiddleware(
|
return new ExtraPathRedirectMiddleware(
|
||||||
$this->resolver->reveal(),
|
$this->resolver,
|
||||||
$this->requestTracker->reveal(),
|
$this->requestTracker,
|
||||||
$this->redirectionBuilder->reveal(),
|
$this->redirectionBuilder,
|
||||||
$this->redirectResponseHelper->reveal(),
|
$this->redirectResponseHelper,
|
||||||
$options ?? new UrlShortenerOptions(appendExtraPath: true),
|
$options ?? new UrlShortenerOptions(appendExtraPath: true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Middleware;
|
||||||
use Laminas\Diactoros\Response;
|
use Laminas\Diactoros\Response;
|
||||||
use Laminas\Diactoros\ServerRequestFactory;
|
use Laminas\Diactoros\ServerRequestFactory;
|
||||||
use PHPUnit\Framework\Assert;
|
use PHPUnit\Framework\Assert;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
|
@ -21,13 +19,11 @@ use function Functional\const_function;
|
||||||
|
|
||||||
class TrimTrailingSlashMiddlewareTest extends TestCase
|
class TrimTrailingSlashMiddlewareTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
private MockObject $requestHandler;
|
||||||
|
|
||||||
private ObjectProphecy $requestHandler;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->requestHandler = $this->prophesize(RequestHandlerInterface::class);
|
$this->requestHandler = $this->createMock(RequestHandlerInterface::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,9 +36,11 @@ class TrimTrailingSlashMiddlewareTest extends TestCase
|
||||||
callable $assertions,
|
callable $assertions,
|
||||||
): void {
|
): void {
|
||||||
$arg = compose($assertions, const_function(true));
|
$arg = compose($assertions, const_function(true));
|
||||||
|
$this->requestHandler->expects($this->once())->method('handle')->with($this->callback($arg))->willReturn(
|
||||||
|
new Response(),
|
||||||
|
);
|
||||||
|
|
||||||
$this->requestHandler->handle(Argument::that($arg))->willReturn(new Response());
|
$this->middleware($trailingSlashEnabled)->process($inputRequest, $this->requestHandler);
|
||||||
$this->middleware($trailingSlashEnabled)->process($inputRequest, $this->requestHandler->reveal());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideRequests(): iterable
|
public function provideRequests(): iterable
|
||||||
|
|
|
@ -5,9 +5,8 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioTest\Shlink\Core\ShortUrl\Paginator\Adapter;
|
namespace ShlinkioTest\Shlink\Core\ShortUrl\Paginator\Adapter;
|
||||||
|
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter\ShortUrlRepositoryAdapter;
|
use Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter\ShortUrlRepositoryAdapter;
|
||||||
|
@ -18,13 +17,11 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
class ShortUrlRepositoryAdapterTest extends TestCase
|
class ShortUrlRepositoryAdapterTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
private MockObject $repo;
|
||||||
|
|
||||||
private ObjectProphecy $repo;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,13 +42,14 @@ class ShortUrlRepositoryAdapterTest extends TestCase
|
||||||
'endDate' => $endDate,
|
'endDate' => $endDate,
|
||||||
'orderBy' => $orderBy,
|
'orderBy' => $orderBy,
|
||||||
]);
|
]);
|
||||||
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $params, null);
|
$adapter = new ShortUrlRepositoryAdapter($this->repo, $params, null);
|
||||||
$orderBy = $params->orderBy();
|
$orderBy = $params->orderBy();
|
||||||
$dateRange = $params->dateRange();
|
$dateRange = $params->dateRange();
|
||||||
|
|
||||||
$this->repo->findList(
|
$this->repo->expects($this->once())->method('findList')->with(
|
||||||
new ShortUrlsListFiltering(10, 5, $orderBy, $searchTerm, $tags, TagsMode::ANY, $dateRange),
|
new ShortUrlsListFiltering(10, 5, $orderBy, $searchTerm, $tags, TagsMode::ANY, $dateRange),
|
||||||
)->shouldBeCalledOnce();
|
);
|
||||||
|
|
||||||
$adapter->getSlice(5, 10);
|
$adapter->getSlice(5, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,12 +70,12 @@ class ShortUrlRepositoryAdapterTest extends TestCase
|
||||||
'endDate' => $endDate,
|
'endDate' => $endDate,
|
||||||
]);
|
]);
|
||||||
$apiKey = ApiKey::create();
|
$apiKey = ApiKey::create();
|
||||||
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $params, $apiKey);
|
$adapter = new ShortUrlRepositoryAdapter($this->repo, $params, $apiKey);
|
||||||
$dateRange = $params->dateRange();
|
$dateRange = $params->dateRange();
|
||||||
|
|
||||||
$this->repo->countList(
|
$this->repo->expects($this->once())->method('countList')->with(
|
||||||
new ShortUrlsCountFiltering($searchTerm, $tags, TagsMode::ANY, $dateRange, $apiKey),
|
new ShortUrlsCountFiltering($searchTerm, $tags, TagsMode::ANY, $dateRange, $apiKey),
|
||||||
)->shouldBeCalledOnce();
|
);
|
||||||
$adapter->getNbResults();
|
$adapter->getNbResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Resolver;
|
||||||
|
|
||||||
use Doctrine\Common\EventManager;
|
use Doctrine\Common\EventManager;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Resolver\PersistenceShortUrlRelationResolver;
|
use Shlinkio\Shlink\Core\ShortUrl\Resolver\PersistenceShortUrlRelationResolver;
|
||||||
|
@ -20,26 +18,22 @@ use function count;
|
||||||
|
|
||||||
class PersistenceShortUrlRelationResolverTest extends TestCase
|
class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private PersistenceShortUrlRelationResolver $resolver;
|
private PersistenceShortUrlRelationResolver $resolver;
|
||||||
private ObjectProphecy $em;
|
private MockObject $em;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->em->getEventManager()->willReturn(new EventManager());
|
$this->em->method('getEventManager')->willReturn(new EventManager());
|
||||||
|
|
||||||
$this->resolver = new PersistenceShortUrlRelationResolver($this->em->reveal());
|
$this->resolver = new PersistenceShortUrlRelationResolver($this->em);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function returnsEmptyWhenNoDomainIsProvided(): void
|
public function returnsEmptyWhenNoDomainIsProvided(): void
|
||||||
{
|
{
|
||||||
$getRepository = $this->em->getRepository(Domain::class);
|
$this->em->expects($this->never())->method('getRepository')->with(Domain::class);
|
||||||
|
|
||||||
self::assertNull($this->resolver->resolveDomain(null));
|
self::assertNull($this->resolver->resolveDomain(null));
|
||||||
$getRepository->shouldNotHaveBeenCalled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,9 +42,9 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function findsOrCreatesDomainWhenValueIsProvided(?Domain $foundDomain, string $authority): void
|
public function findsOrCreatesDomainWhenValueIsProvided(?Domain $foundDomain, string $authority): void
|
||||||
{
|
{
|
||||||
$repo = $this->prophesize(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$findDomain = $repo->findOneBy(['authority' => $authority])->willReturn($foundDomain);
|
$repo->expects($this->once())->method('findOneBy')->with(['authority' => $authority])->willReturn($foundDomain);
|
||||||
$getRepository = $this->em->getRepository(Domain::class)->willReturn($repo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
|
|
||||||
$result = $this->resolver->resolveDomain($authority);
|
$result = $this->resolver->resolveDomain($authority);
|
||||||
|
|
||||||
|
@ -59,8 +53,6 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
}
|
}
|
||||||
self::assertInstanceOf(Domain::class, $result);
|
self::assertInstanceOf(Domain::class, $result);
|
||||||
self::assertEquals($authority, $result->getAuthority());
|
self::assertEquals($authority, $result->getAuthority());
|
||||||
$findDomain->shouldHaveBeenCalledOnce();
|
|
||||||
$getRepository->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideFoundDomains(): iterable
|
public function provideFoundDomains(): iterable
|
||||||
|
@ -79,21 +71,22 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
{
|
{
|
||||||
$expectedPersistedTags = count($expectedTags);
|
$expectedPersistedTags = count($expectedTags);
|
||||||
|
|
||||||
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
|
$tagRepo = $this->createMock(TagRepositoryInterface::class);
|
||||||
$findTag = $tagRepo->findOneBy(Argument::type('array'))->will(function (array $args): ?Tag {
|
$tagRepo->expects($this->exactly($expectedPersistedTags))->method('findOneBy')->with(
|
||||||
['name' => $name] = $args[0];
|
$this->isType('array'),
|
||||||
|
)->willReturnCallback(function (array $criteria): ?Tag {
|
||||||
|
['name' => $name] = $criteria;
|
||||||
return $name === 'foo' ? new Tag($name) : null;
|
return $name === 'foo' ? new Tag($name) : null;
|
||||||
});
|
});
|
||||||
$getRepo = $this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(Tag::class)->willReturn($tagRepo);
|
||||||
$persist = $this->em->persist(Argument::type(Tag::class));
|
$this->em->expects($this->exactly($expectedPersistedTags))->method('persist')->with(
|
||||||
|
$this->isInstanceOf(Tag::class),
|
||||||
|
);
|
||||||
|
|
||||||
$result = $this->resolver->resolveTags($tags);
|
$result = $this->resolver->resolveTags($tags);
|
||||||
|
|
||||||
self::assertCount($expectedPersistedTags, $result);
|
self::assertCount($expectedPersistedTags, $result);
|
||||||
self::assertEquals($expectedTags, $result->toArray());
|
self::assertEquals($expectedTags, $result->toArray());
|
||||||
$findTag->shouldHaveBeenCalledTimes($expectedPersistedTags);
|
|
||||||
$getRepo->shouldHaveBeenCalledOnce();
|
|
||||||
$persist->shouldHaveBeenCalledTimes($expectedPersistedTags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideTags(): iterable
|
public function provideTags(): iterable
|
||||||
|
@ -105,25 +98,20 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function returnsEmptyCollectionWhenProvidingEmptyListOfTags(): void
|
public function returnsEmptyCollectionWhenProvidingEmptyListOfTags(): void
|
||||||
{
|
{
|
||||||
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
|
$this->em->expects($this->never())->method('getRepository')->with(Tag::class);
|
||||||
$findTag = $tagRepo->findOneBy(Argument::type('array'))->willReturn(null);
|
$this->em->expects($this->never())->method('persist');
|
||||||
$getRepo = $this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
|
|
||||||
$persist = $this->em->persist(Argument::type(Tag::class));
|
|
||||||
|
|
||||||
$result = $this->resolver->resolveTags([]);
|
$result = $this->resolver->resolveTags([]);
|
||||||
|
|
||||||
self::assertEmpty($result);
|
self::assertEmpty($result);
|
||||||
$findTag->shouldNotHaveBeenCalled();
|
|
||||||
$getRepo->shouldNotHaveBeenCalled();
|
|
||||||
$persist->shouldNotHaveBeenCalled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function newDomainsAreMemoizedUntilStateIsCleared(): void
|
public function newDomainsAreMemoizedUntilStateIsCleared(): void
|
||||||
{
|
{
|
||||||
$repo = $this->prophesize(DomainRepositoryInterface::class);
|
$repo = $this->createMock(DomainRepositoryInterface::class);
|
||||||
$repo->findOneBy(Argument::type('array'))->willReturn(null);
|
$repo->expects($this->exactly(3))->method('findOneBy')->with($this->isType('array'))->willReturn(null);
|
||||||
$this->em->getRepository(Domain::class)->willReturn($repo->reveal());
|
$this->em->method('getRepository')->with(Domain::class)->willReturn($repo);
|
||||||
|
|
||||||
$authority = 'foo.com';
|
$authority = 'foo.com';
|
||||||
$domain1 = $this->resolver->resolveDomain($authority);
|
$domain1 = $this->resolver->resolveDomain($authority);
|
||||||
|
@ -140,11 +128,9 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function newTagsAreMemoizedUntilStateIsCleared(): void
|
public function newTagsAreMemoizedUntilStateIsCleared(): void
|
||||||
{
|
{
|
||||||
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
|
$tagRepo = $this->createMock(TagRepositoryInterface::class);
|
||||||
$tagRepo->findOneBy(Argument::type('array'))->willReturn(null);
|
$tagRepo->expects($this->exactly(6))->method('findOneBy')->with($this->isType('array'))->willReturn(null);
|
||||||
$this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
|
$this->em->method('getRepository')->with(Tag::class)->willReturn($tagRepo);
|
||||||
$this->em->persist(Argument::type(Tag::class))->will(function (): void {
|
|
||||||
});
|
|
||||||
|
|
||||||
$tags = ['foo', 'bar'];
|
$tags = ['foo', 'bar'];
|
||||||
[$foo1, $bar1] = $this->resolver->resolveTags($tags);
|
[$foo1, $bar1] = $this->resolver->resolveTags($tags);
|
||||||
|
|
|
@ -7,9 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
||||||
|
@ -27,15 +26,16 @@ use function range;
|
||||||
class ShortUrlResolverTest extends TestCase
|
class ShortUrlResolverTest extends TestCase
|
||||||
{
|
{
|
||||||
use ApiKeyHelpersTrait;
|
use ApiKeyHelpersTrait;
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private ShortUrlResolver $urlResolver;
|
private ShortUrlResolver $urlResolver;
|
||||||
private ObjectProphecy $em;
|
private MockObject $em;
|
||||||
|
private MockObject $repo;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->urlResolver = new ShortUrlResolver($this->em->reveal());
|
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
||||||
|
$this->urlResolver = new ShortUrlResolver($this->em);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,15 +48,14 @@ class ShortUrlResolverTest extends TestCase
|
||||||
$shortCode = $shortUrl->getShortCode();
|
$shortCode = $shortUrl->getShortCode();
|
||||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
||||||
|
|
||||||
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
$this->repo->expects($this->once())->method('findOne')->with($identifier, $apiKey?->spec())->willReturn(
|
||||||
$findOne = $repo->findOne($identifier, $apiKey?->spec())->willReturn($shortUrl);
|
$shortUrl,
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
);
|
||||||
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
|
|
||||||
$result = $this->urlResolver->resolveShortUrl($identifier, $apiKey);
|
$result = $this->urlResolver->resolveShortUrl($identifier, $apiKey);
|
||||||
|
|
||||||
self::assertSame($shortUrl, $result);
|
self::assertSame($shortUrl, $result);
|
||||||
$findOne->shouldHaveBeenCalledOnce();
|
|
||||||
$getRepo->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,13 +67,10 @@ class ShortUrlResolverTest extends TestCase
|
||||||
$shortCode = 'abc123';
|
$shortCode = 'abc123';
|
||||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
||||||
|
|
||||||
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
$this->repo->expects($this->once())->method('findOne')->with($identifier, $apiKey?->spec())->willReturn(null);
|
||||||
$findOne = $repo->findOne($identifier, $apiKey?->spec())->willReturn(null);
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal(), $apiKey);
|
|
||||||
|
|
||||||
$this->expectException(ShortUrlNotFoundException::class);
|
$this->expectException(ShortUrlNotFoundException::class);
|
||||||
$findOne->shouldBeCalledOnce();
|
|
||||||
$getRepo->shouldBeCalledOnce();
|
|
||||||
|
|
||||||
$this->urlResolver->resolveShortUrl($identifier, $apiKey);
|
$this->urlResolver->resolveShortUrl($identifier, $apiKey);
|
||||||
}
|
}
|
||||||
|
@ -85,17 +81,14 @@ class ShortUrlResolverTest extends TestCase
|
||||||
$shortUrl = ShortUrl::withLongUrl('expected_url');
|
$shortUrl = ShortUrl::withLongUrl('expected_url');
|
||||||
$shortCode = $shortUrl->getShortCode();
|
$shortCode = $shortUrl->getShortCode();
|
||||||
|
|
||||||
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
$this->repo->expects($this->once())->method('findOneWithDomainFallback')->with(
|
||||||
$findOneByShortCode = $repo->findOneWithDomainFallback(
|
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
|
|
||||||
$result = $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
|
$result = $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
|
||||||
|
|
||||||
self::assertSame($shortUrl, $result);
|
self::assertSame($shortUrl, $result);
|
||||||
$findOneByShortCode->shouldHaveBeenCalledOnce();
|
|
||||||
$getRepo->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,15 +99,12 @@ class ShortUrlResolverTest extends TestCase
|
||||||
{
|
{
|
||||||
$shortCode = $shortUrl->getShortCode();
|
$shortCode = $shortUrl->getShortCode();
|
||||||
|
|
||||||
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
$this->repo->expects($this->once())->method('findOneWithDomainFallback')->with(
|
||||||
$findOneByShortCode = $repo->findOneWithDomainFallback(
|
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
|
|
||||||
$this->expectException(ShortUrlNotFoundException::class);
|
$this->expectException(ShortUrlNotFoundException::class);
|
||||||
$findOneByShortCode->shouldBeCalledOnce();
|
|
||||||
$getRepo->shouldBeCalledOnce();
|
|
||||||
|
|
||||||
$this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
|
$this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
|
||||||
|
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelperInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelperInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
|
||||||
|
@ -27,26 +25,25 @@ use function count;
|
||||||
class ShortUrlServiceTest extends TestCase
|
class ShortUrlServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
use ApiKeyHelpersTrait;
|
use ApiKeyHelpersTrait;
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private ShortUrlService $service;
|
private ShortUrlService $service;
|
||||||
private ObjectProphecy $em;
|
private MockObject $em;
|
||||||
private ObjectProphecy $urlResolver;
|
private MockObject $urlResolver;
|
||||||
private ObjectProphecy $titleResolutionHelper;
|
private MockObject $titleResolutionHelper;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->em->persist(Argument::any())->willReturn(null);
|
$this->em->method('persist')->willReturn(null);
|
||||||
$this->em->flush()->willReturn(null);
|
$this->em->method('flush')->willReturn(null);
|
||||||
|
|
||||||
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
|
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
|
||||||
$this->titleResolutionHelper = $this->prophesize(ShortUrlTitleResolutionHelperInterface::class);
|
$this->titleResolutionHelper = $this->createMock(ShortUrlTitleResolutionHelperInterface::class);
|
||||||
|
|
||||||
$this->service = new ShortUrlService(
|
$this->service = new ShortUrlService(
|
||||||
$this->em->reveal(),
|
$this->em,
|
||||||
$this->urlResolver->reveal(),
|
$this->urlResolver,
|
||||||
$this->titleResolutionHelper->reveal(),
|
$this->titleResolutionHelper,
|
||||||
new SimpleShortUrlRelationResolver(),
|
new SimpleShortUrlRelationResolver(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -64,10 +61,10 @@ class ShortUrlServiceTest extends TestCase
|
||||||
ShortUrl::createEmpty(),
|
ShortUrl::createEmpty(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$repo = $this->prophesize(ShortUrlRepository::class);
|
$repo = $this->createMock(ShortUrlRepository::class);
|
||||||
$repo->findList(Argument::cetera())->willReturn($list)->shouldBeCalledOnce();
|
$repo->expects($this->once())->method('findList')->willReturn($list);
|
||||||
$repo->countList(Argument::cetera())->willReturn(count($list))->shouldBeCalledOnce();
|
$repo->expects($this->once())->method('countList')->willReturn(count($list));
|
||||||
$this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
|
||||||
|
|
||||||
$paginator = $this->service->listShortUrls(ShortUrlsParams::emptyInstance(), $apiKey);
|
$paginator = $this->service->listShortUrls(ShortUrlsParams::emptyInstance(), $apiKey);
|
||||||
|
|
||||||
|
@ -87,15 +84,15 @@ class ShortUrlServiceTest extends TestCase
|
||||||
$originalLongUrl = 'originalLongUrl';
|
$originalLongUrl = 'originalLongUrl';
|
||||||
$shortUrl = ShortUrl::withLongUrl($originalLongUrl);
|
$shortUrl = ShortUrl::withLongUrl($originalLongUrl);
|
||||||
|
|
||||||
$findShortUrl = $this->urlResolver->resolveShortUrl(
|
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
||||||
$apiKey,
|
$apiKey,
|
||||||
)->willReturn($shortUrl);
|
)->willReturn($shortUrl);
|
||||||
$flush = $this->em->flush()->willReturn(null);
|
|
||||||
|
|
||||||
$processTitle = $this->titleResolutionHelper->processTitleAndValidateUrl($shortUrlEdit)->willReturn(
|
$this->titleResolutionHelper->expects($this->exactly($expectedValidateCalls))
|
||||||
$shortUrlEdit,
|
->method('processTitleAndValidateUrl')
|
||||||
);
|
->with($shortUrlEdit)
|
||||||
|
->willReturn($shortUrlEdit);
|
||||||
|
|
||||||
$result = $this->service->updateShortUrl(
|
$result = $this->service->updateShortUrl(
|
||||||
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
|
||||||
|
@ -108,9 +105,6 @@ class ShortUrlServiceTest extends TestCase
|
||||||
self::assertEquals($shortUrlEdit->validUntil(), $shortUrl->getValidUntil());
|
self::assertEquals($shortUrlEdit->validUntil(), $shortUrl->getValidUntil());
|
||||||
self::assertEquals($shortUrlEdit->maxVisits(), $shortUrl->getMaxVisits());
|
self::assertEquals($shortUrlEdit->maxVisits(), $shortUrl->getMaxVisits());
|
||||||
self::assertEquals($shortUrlEdit->longUrl() ?? $originalLongUrl, $shortUrl->getLongUrl());
|
self::assertEquals($shortUrlEdit->longUrl() ?? $originalLongUrl, $shortUrl->getLongUrl());
|
||||||
$findShortUrl->shouldHaveBeenCalled();
|
|
||||||
$flush->shouldHaveBeenCalled();
|
|
||||||
$processTitle->shouldHaveBeenCalledTimes($expectedValidateCalls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideShortUrlEdits(): iterable
|
public function provideShortUrlEdits(): iterable
|
||||||
|
|
|
@ -5,11 +5,9 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioTest\Shlink\Core\ShortUrl;
|
namespace ShlinkioTest\Shlink\Core\ShortUrl;
|
||||||
|
|
||||||
use Cake\Chronos\Chronos;
|
use Cake\Chronos\Chronos;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
|
||||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||||
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
|
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
@ -22,42 +20,29 @@ use Shlinkio\Shlink\Core\ShortUrl\UrlShortener;
|
||||||
|
|
||||||
class UrlShortenerTest extends TestCase
|
class UrlShortenerTest extends TestCase
|
||||||
{
|
{
|
||||||
use ProphecyTrait;
|
|
||||||
|
|
||||||
private UrlShortener $urlShortener;
|
private UrlShortener $urlShortener;
|
||||||
private ObjectProphecy $em;
|
private MockObject $em;
|
||||||
private ObjectProphecy $titleResolutionHelper;
|
private MockObject $titleResolutionHelper;
|
||||||
private ObjectProphecy $shortCodeHelper;
|
private MockObject $shortCodeHelper;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->titleResolutionHelper = $this->prophesize(ShortUrlTitleResolutionHelperInterface::class);
|
$this->titleResolutionHelper = $this->createMock(ShortUrlTitleResolutionHelperInterface::class);
|
||||||
$this->titleResolutionHelper->processTitleAndValidateUrl(Argument::cetera())->willReturnArgument();
|
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
|
||||||
|
|
||||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
// FIXME Should use the interface, but it doe snot define wrapInTransaction explicitly
|
||||||
$this->em->persist(Argument::any())->will(function ($arguments): void {
|
$this->em = $this->createMock(EntityManager::class);
|
||||||
/** @var ShortUrl $shortUrl */
|
$this->em->method('persist')->willReturnCallback(fn (ShortUrl $shortUrl) => $shortUrl->setId('10'));
|
||||||
[$shortUrl] = $arguments;
|
$this->em->method('wrapInTransaction')->with($this->isType('callable'))->willReturnCallback(
|
||||||
$shortUrl->setId('10');
|
fn (callable $callback) => $callback(),
|
||||||
});
|
);
|
||||||
$this->em->wrapInTransaction(Argument::type('callable'))->will(function (array $args) {
|
|
||||||
/** @var callable $callback */
|
|
||||||
[$callback] = $args;
|
|
||||||
|
|
||||||
return $callback();
|
|
||||||
});
|
|
||||||
$repo = $this->prophesize(ShortUrlRepository::class);
|
|
||||||
$this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
|
||||||
|
|
||||||
$this->shortCodeHelper = $this->prophesize(ShortCodeUniquenessHelperInterface::class);
|
|
||||||
$this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(true);
|
|
||||||
|
|
||||||
$this->urlShortener = new UrlShortener(
|
$this->urlShortener = new UrlShortener(
|
||||||
$this->titleResolutionHelper->reveal(),
|
$this->titleResolutionHelper,
|
||||||
$this->em->reveal(),
|
$this->em,
|
||||||
new SimpleShortUrlRelationResolver(),
|
new SimpleShortUrlRelationResolver(),
|
||||||
$this->shortCodeHelper->reveal(),
|
$this->shortCodeHelper,
|
||||||
$this->prophesize(EventDispatcherInterface::class)->reveal(),
|
$this->createMock(EventDispatcherInterface::class),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,23 +51,31 @@ class UrlShortenerTest extends TestCase
|
||||||
{
|
{
|
||||||
$longUrl = 'http://foobar.com/12345/hello?foo=bar';
|
$longUrl = 'http://foobar.com/12345/hello?foo=bar';
|
||||||
$meta = ShortUrlCreation::fromRawData(['longUrl' => $longUrl]);
|
$meta = ShortUrlCreation::fromRawData(['longUrl' => $longUrl]);
|
||||||
|
$this->titleResolutionHelper->expects($this->once())->method('processTitleAndValidateUrl')->with(
|
||||||
|
$meta,
|
||||||
|
)->willReturnArgument(0);
|
||||||
|
$this->shortCodeHelper->method('ensureShortCodeUniqueness')->willReturn(true);
|
||||||
|
|
||||||
$shortUrl = $this->urlShortener->shorten($meta);
|
$shortUrl = $this->urlShortener->shorten($meta);
|
||||||
|
|
||||||
self::assertEquals($longUrl, $shortUrl->getLongUrl());
|
self::assertEquals($longUrl, $shortUrl->getLongUrl());
|
||||||
$this->titleResolutionHelper->processTitleAndValidateUrl($meta)->shouldHaveBeenCalledOnce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function exceptionIsThrownWhenNonUniqueSlugIsProvided(): void
|
public function exceptionIsThrownWhenNonUniqueSlugIsProvided(): void
|
||||||
{
|
{
|
||||||
$ensureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(false);
|
$meta = ShortUrlCreation::fromRawData(
|
||||||
|
['customSlug' => 'custom-slug', 'longUrl' => 'http://foobar.com/12345/hello?foo=bar'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->shortCodeHelper->expects($this->once())->method('ensureShortCodeUniqueness')->willReturn(false);
|
||||||
|
$this->titleResolutionHelper->expects($this->once())->method('processTitleAndValidateUrl')->with(
|
||||||
|
$meta,
|
||||||
|
)->willReturnArgument(0);
|
||||||
|
|
||||||
$ensureUniqueness->shouldBeCalledOnce();
|
|
||||||
$this->expectException(NonUniqueSlugException::class);
|
$this->expectException(NonUniqueSlugException::class);
|
||||||
|
|
||||||
$this->urlShortener->shorten(ShortUrlCreation::fromRawData(
|
$this->urlShortener->shorten($meta);
|
||||||
['customSlug' => 'custom-slug', 'longUrl' => 'http://foobar.com/12345/hello?foo=bar'],
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,16 +84,14 @@ class UrlShortenerTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function existingShortUrlIsReturnedWhenRequested(ShortUrlCreation $meta, ShortUrl $expected): void
|
public function existingShortUrlIsReturnedWhenRequested(ShortUrlCreation $meta, ShortUrl $expected): void
|
||||||
{
|
{
|
||||||
$repo = $this->prophesize(ShortUrlRepository::class);
|
$repo = $this->createMock(ShortUrlRepository::class);
|
||||||
$findExisting = $repo->findOneMatching(Argument::cetera())->willReturn($expected);
|
$repo->expects($this->once())->method('findOneMatching')->willReturn($expected);
|
||||||
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
|
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
|
||||||
|
$this->titleResolutionHelper->expects($this->never())->method('processTitleAndValidateUrl');
|
||||||
|
$this->shortCodeHelper->method('ensureShortCodeUniqueness')->willReturn(true);
|
||||||
|
|
||||||
$result = $this->urlShortener->shorten($meta);
|
$result = $this->urlShortener->shorten($meta);
|
||||||
|
|
||||||
$findExisting->shouldHaveBeenCalledOnce();
|
|
||||||
$getRepo->shouldHaveBeenCalledOnce();
|
|
||||||
$this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
$this->titleResolutionHelper->processTitleAndValidateUrl(Argument::cetera())->shouldNotHaveBeenCalled();
|
|
||||||
self::assertSame($expected, $result);
|
self::assertSame($expected, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue