Merge pull request #1585 from acelaya-forks/feature/phpunit-mocks

Feature/phpunit mocks
This commit is contained in:
Alejandro Celaya 2022-10-23 20:19:22 +02:00 committed by GitHub
commit 7ceae7af87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 475 additions and 674 deletions

View file

@ -14,7 +14,6 @@ jobs:
strategy:
matrix:
php-version: ['8.1', '8.2']
continue-on-error: ${{ matrix.php-version == '8.2' }}
env:
LC_ALL: C
steps:

View file

@ -14,7 +14,6 @@ jobs:
strategy:
matrix:
php-version: ['8.1', '8.2']
continue-on-error: ${{ matrix.php-version == '8.2' }}
steps:
- uses: actions/checkout@v3
- uses: './.github/actions/ci-setup'

View file

@ -14,7 +14,6 @@ jobs:
strategy:
matrix:
php-version: ['8.1', '8.2']
continue-on-error: ${{ matrix.php-version == '8.2' }}
steps:
- uses: actions/checkout@v3
- name: Start postgres database server

View file

@ -44,7 +44,6 @@ jobs:
strategy:
matrix:
php-version: ['8.1', '8.2']
continue-on-error: ${{ matrix.php-version == '8.2' }}
steps:
- uses: actions/checkout@v3
- run: docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d shlink_db_postgres

View file

@ -36,11 +36,9 @@ class RoleResolverTest extends TestCase
array $expectedRoles,
int $expectedDomainCalls,
): void {
$this->domainService
->expects($this->exactly($expectedDomainCalls))
->method('getOrCreate')
->with($this->equalTo('example.com'))
->willReturn(Domain::withAuthority('example.com')->setId('1'));
$this->domainService->expects($this->exactly($expectedDomainCalls))->method('getOrCreate')->with(
'example.com',
)->willReturn(Domain::withAuthority('example.com')->setId('1'));
$result = $this->resolver->determineRoles($input);

View file

@ -29,7 +29,7 @@ class DisableKeyCommandTest extends TestCase
public function providedApiKeyIsDisabled(): void
{
$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([
'apiKey' => $apiKey,
@ -44,9 +44,9 @@ class DisableKeyCommandTest extends TestCase
{
$apiKey = 'abcd1234';
$expectedMessage = 'API key "abcd1234" does not exist.';
$this->apiKeyService->expects($this->once())->method('disable')->with(
$this->equalTo($apiKey),
)->willThrowException(new InvalidArgumentException($expectedMessage));
$this->apiKeyService->expects($this->once())->method('disable')->with($apiKey)->willThrowException(
new InvalidArgumentException($expectedMessage),
);
$this->commandTester->execute([
'apiKey' => $apiKey,

View file

@ -35,9 +35,7 @@ class ListKeysCommandTest extends TestCase
*/
public function returnsExpectedOutput(array $keys, bool $enabledOnly, string $expected): void
{
$this->apiKeyService->expects($this->once())->method('listKeys')->with(
$this->equalTo($enabledOnly),
)->willReturn($keys);
$this->apiKeyService->expects($this->once())->method('listKeys')->with($enabledOnly)->willReturn($keys);
$this->commandTester->execute(['--enabled-only' => $enabledOnly]);
$output = $this->commandTester->getDisplay();

View file

@ -87,7 +87,7 @@ class CreateDatabaseCommandTest extends TestCase
$shlinkDatabase = 'shlink_database';
$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('createDatabase')->with($this->equalTo($shlinkDatabase));
$this->schemaManager->expects($this->once())->method('createDatabase')->with($shlinkDatabase);
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn(
['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->once())->method('listTableNames')->willReturn($tables);
$this->processHelper->expects($this->once())->method('run')->with(
$this->isInstanceOf(OutputInterface::class),
$this->equalTo([
'/usr/local/bin/php',
CreateDatabaseCommand::DOCTRINE_SCRIPT,
CreateDatabaseCommand::DOCTRINE_CREATE_SCHEMA_COMMAND,
'--no-interaction',
]),
);
$this->processHelper->expects($this->once())->method('run')->with($this->isInstanceOf(OutputInterface::class), [
'/usr/local/bin/php',
CreateDatabaseCommand::DOCTRINE_SCRIPT,
CreateDatabaseCommand::DOCTRINE_CREATE_SCHEMA_COMMAND,
'--no-interaction',
]);
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
$this->commandTester->execute([]);

View file

@ -41,15 +41,12 @@ class MigrateDatabaseCommandTest extends TestCase
/** @test */
public function migrationsCommandIsRunWithProperVerbosity(): void
{
$this->processHelper->expects($this->once())->method('run')->with(
$this->isInstanceOf(OutputInterface::class),
$this->equalTo([
'/usr/local/bin/php',
MigrateDatabaseCommand::DOCTRINE_MIGRATIONS_SCRIPT,
MigrateDatabaseCommand::DOCTRINE_MIGRATE_COMMAND,
'--no-interaction',
]),
);
$this->processHelper->expects($this->once())->method('run')->with($this->isInstanceOf(OutputInterface::class), [
'/usr/local/bin/php',
MigrateDatabaseCommand::DOCTRINE_MIGRATIONS_SCRIPT,
MigrateDatabaseCommand::DOCTRINE_MIGRATE_COMMAND,
'--no-interaction',
]);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();

View file

@ -37,12 +37,12 @@ class DomainRedirectsCommandTest extends TestCase
public function onlyPlainQuestionsAreAskedForNewDomainsAndDomainsWithNoRedirects(?Domain $domain): void
{
$domainAuthority = 'my-domain.com';
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
$domain,
);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withRedirects('foo.com', null, 'baz.com')),
$domainAuthority,
NotFoundRedirects::withRedirects('foo.com', null, 'baz.com'),
)->willReturn(Domain::withAuthority(''));
$this->domainService->expects($this->never())->method('listDomains');
@ -73,12 +73,12 @@ class DomainRedirectsCommandTest extends TestCase
$domain = Domain::withAuthority($domainAuthority);
$domain->configureNotFoundRedirects(NotFoundRedirects::withRedirects('foo.com', 'bar.com', 'baz.com'));
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
$domain,
);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com')),
$domainAuthority,
NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com'),
)->willReturn($domain);
$this->domainService->expects($this->never())->method('listDomains');
@ -102,12 +102,12 @@ class DomainRedirectsCommandTest extends TestCase
$domain = Domain::withAuthority($domainAuthority);
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([]);
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
$domain,
);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
)->willReturn($domain);
$this->commandTester->setInputs([$domainAuthority, '', '', '']);
@ -128,12 +128,12 @@ class DomainRedirectsCommandTest extends TestCase
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
DomainItem::forNonDefaultDomain(Domain::withAuthority($domainAuthority)),
]);
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
$domain,
);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
)->willReturn($domain);
$this->commandTester->setInputs(['1', '', '', '']);
@ -157,12 +157,12 @@ class DomainRedirectsCommandTest extends TestCase
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-two.com')),
]);
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('findByAuthority')->with($domainAuthority)->willReturn(
$domain,
);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
)->willReturn($domain);
$this->commandTester->setInputs(['2', $domainAuthority, '', '', '']);

View file

@ -46,10 +46,10 @@ class GetDomainVisitsCommandTest extends TestCase
);
$domain = 'doma.in';
$this->visitsHelper->expects($this->once())->method('visitsForDomain')->with(
$this->equalTo($domain),
$domain,
$this->anything(),
)->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',
);

View file

@ -47,7 +47,7 @@ class CreateShortUrlCommandTest extends TestCase
{
$shortUrl = ShortUrl::createEmpty();
$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',
);
@ -103,7 +103,7 @@ class CreateShortUrlCommandTest extends TestCase
return true;
}),
)->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',
);

View file

@ -35,7 +35,7 @@ class DeleteShortUrlCommandTest extends TestCase
{
$shortCode = 'abc123';
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
$this->isFalse(),
);
@ -54,7 +54,7 @@ class DeleteShortUrlCommandTest extends TestCase
$shortCode = 'abc123';
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo($identifier),
$identifier,
$this->isFalse(),
)->willThrowException(Exception\ShortUrlNotFoundException::fromNotFound($identifier));
@ -76,7 +76,7 @@ class DeleteShortUrlCommandTest extends TestCase
$shortCode = 'abc123';
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$this->service->expects($this->exactly($expectedDeleteCalls))->method('deleteByShortCode')->with(
$this->equalTo($identifier),
$identifier,
$this->isType('bool'),
)->willReturnCallback(function ($_, bool $ignoreThreshold) use ($shortCode): void {
if (!$ignoreThreshold) {
@ -110,7 +110,7 @@ class DeleteShortUrlCommandTest extends TestCase
{
$shortCode = 'abc123';
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
$this->isFalse(),
)->willThrowException(Exception\DeleteShortUrlException::fromVisitsThreshold(
10,

View file

@ -44,8 +44,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
{
$shortCode = 'abc123';
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(DateRange::allTime())),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(DateRange::allTime()),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute(['shortCode' => $shortCode]);
@ -58,8 +58,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
$startDate = '2016-01-01';
$endDate = '2016-02-01';
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate)))),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate))),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute([
@ -75,8 +75,8 @@ class GetShortUrlVisitsCommandTest extends TestCase
$shortCode = 'abc123';
$startDate = 'foo';
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(DateRange::allTime())),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(DateRange::allTime()),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute([
@ -99,7 +99,7 @@ class GetShortUrlVisitsCommandTest extends TestCase
);
$shortCode = 'abc123';
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
$this->anything(),
)->willReturn(new Paginator(new ArrayAdapter([$visit])));

View file

@ -73,7 +73,7 @@ class ListShortUrlsCommandTest extends TestCase
}
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::emptyInstance()),
ShortUrlsParams::emptyInstance(),
)->willReturn(new Paginator(new ArrayAdapter($data)));
$this->commandTester->setInputs(['n']);
@ -94,7 +94,7 @@ class ListShortUrlsCommandTest extends TestCase
{
$page = 5;
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData(['page' => $page])),
ShortUrlsParams::fromRawData(['page' => $page]),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->setInputs(['y']);
@ -112,7 +112,7 @@ class ListShortUrlsCommandTest extends TestCase
ApiKey $apiKey,
): void {
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::emptyInstance()),
ShortUrlsParams::emptyInstance(),
)->willReturn(new Paginator(new ArrayAdapter([
ShortUrl::fromMeta(ShortUrlCreation::fromRawData([
'longUrl' => 'foo.com',
@ -187,16 +187,14 @@ class ListShortUrlsCommandTest extends TestCase
?string $startDate = null,
?string $endDate = null,
): void {
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData([
'page' => $page,
'searchTerm' => $searchTerm,
'tags' => $tags,
'tagsMode' => $tagsMode,
'startDate' => $startDate !== null ? Chronos::parse($startDate)->toAtomString() : null,
'endDate' => $endDate !== null ? Chronos::parse($endDate)->toAtomString() : null,
])),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
'page' => $page,
'searchTerm' => $searchTerm,
'tags' => $tags,
'tagsMode' => $tagsMode,
'startDate' => $startDate !== null ? Chronos::parse($startDate)->toAtomString() : null,
'endDate' => $endDate !== null ? Chronos::parse($endDate)->toAtomString() : null,
]))->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->setInputs(['n']);
$this->commandTester->execute($commandArgs);
@ -249,11 +247,9 @@ class ListShortUrlsCommandTest extends TestCase
*/
public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void
{
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData([
'orderBy' => $expectedOrderBy,
])),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
'orderBy' => $expectedOrderBy,
]))->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->setInputs(['n']);
$this->commandTester->execute($commandArgs);
@ -271,18 +267,16 @@ class ListShortUrlsCommandTest extends TestCase
/** @test */
public function requestingAllElementsWillSetItemsPerPage(): void
{
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData([
'page' => 1,
'searchTerm' => null,
'tags' => [],
'tagsMode' => TagsMode::ANY->value,
'startDate' => null,
'endDate' => null,
'orderBy' => null,
'itemsPerPage' => Paginator::ALL_ITEMS,
])),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([
'page' => 1,
'searchTerm' => null,
'tags' => [],
'tagsMode' => TagsMode::ANY->value,
'startDate' => null,
'endDate' => null,
'orderBy' => null,
'itemsPerPage' => Paginator::ALL_ITEMS,
]))->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute(['--all' => true]);
}

View file

@ -38,7 +38,7 @@ class ResolveUrlCommandTest extends TestCase
$expectedUrl = 'http://domain.com/foo/bar';
$shortUrl = ShortUrl::withLongUrl($expectedUrl);
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
)->willReturn($shortUrl);
$this->commandTester->execute(['shortCode' => $shortCode]);
@ -52,9 +52,9 @@ class ResolveUrlCommandTest extends TestCase
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123');
$shortCode = $identifier->shortCode;
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
$this->equalTo($identifier),
)->willThrowException(ShortUrlNotFoundException::fromNotFound($identifier));
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with($identifier)->willThrowException(
ShortUrlNotFoundException::fromNotFound($identifier),
);
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();

View file

@ -37,7 +37,7 @@ class DeleteTagsCommandTest extends TestCase
public function serviceIsInvokedOnSuccess(): void
{
$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([
'--name' => $tagNames,

View file

@ -45,13 +45,10 @@ class GetTagVisitsCommandTest extends TestCase
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$tag = 'abc123';
$this->visitsHelper->expects($this->once())->method('visitsForTag')->with(
$this->equalTo($tag),
$this->anything(),
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
'the_short_url',
$this->visitsHelper->expects($this->once())->method('visitsForTag')->with($tag, $this->anything())->willReturn(
new Paginator(new ArrayAdapter([$visit])),
);
$this->stringifier->expects($this->once())->method('stringify')->with($shortUrl)->willReturn('the_short_url');
$this->commandTester->execute(['tag' => $tag]);
$output = $this->commandTester->getDisplay();

View file

@ -33,7 +33,7 @@ class RenameTagCommandTest extends TestCase
$oldName = 'foo';
$newName = 'bar';
$this->tagService->expects($this->once())->method('renameTag')->with(
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
TagRenaming::fromNames($oldName, $newName),
)->willThrowException(TagNotFoundException::fromTag('foo'));
$this->commandTester->execute([
@ -51,7 +51,7 @@ class RenameTagCommandTest extends TestCase
$oldName = 'foo';
$newName = 'bar';
$this->tagService->expects($this->once())->method('renameTag')->with(
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
TagRenaming::fromNames($oldName, $newName),
)->willReturn(new Tag($newName));
$this->commandTester->execute([

View file

@ -47,9 +47,7 @@ class GetNonOrphanVisitsCommandTest extends TestCase
$this->visitsHelper->expects($this->once())->method('nonOrphanVisits')->withAnyParameters()->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([]);
$output = $this->commandTester->getDisplay();

View file

@ -26,7 +26,7 @@ class ProcessRunnerTest extends TestCase
$this->helper = $this->createMock(ProcessHelper::class);
$this->formatter = $this->createMock(DebugFormatterHelper::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->process = $this->createMock(Process::class);
$this->output = $this->createMock(OutputInterface::class);

View file

@ -34,16 +34,10 @@ class ShlinkTableTest extends TestCase
$this->baseTable->expects($this->once())->method('setStyle')->with(
$this->isInstanceOf(TableStyle::class),
)->willReturnSelf();
$this->baseTable->expects($this->once())->method('setHeaders')->with(
$this->equalTo($headers),
)->willReturnSelf();
$this->baseTable->expects($this->once())->method('setRows')->with($this->equalTo($rows))->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('setHeaders')->with($headers)->willReturnSelf();
$this->baseTable->expects($this->once())->method('setRows')->with($rows)->willReturnSelf();
$this->baseTable->expects($this->once())->method('setFooterTitle')->with($footerTitle)->willReturnSelf();
$this->baseTable->expects($this->once())->method('setHeaderTitle')->with($headerTitle)->willReturnSelf();
$this->baseTable->expects($this->once())->method('render')->with()->willReturnSelf();
$this->shlinkTable->render($headers, $rows, $footerTitle, $headerTitle);

View file

@ -21,8 +21,9 @@ class PersistenceShortUrlRelationResolver implements ShortUrlRelationResolverInt
/** @var array<string, Tag> */
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);
}
@ -61,7 +62,7 @@ class PersistenceShortUrlRelationResolver implements ShortUrlRelationResolverInt
return new Collections\ArrayCollection(map($tags, function (string $tagName) use ($repo): Tag {
// 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);
return $tag;

View file

@ -34,7 +34,7 @@ class PixelActionTest extends TestCase
{
$shortCode = 'abc123';
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
)->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar'));
$this->requestTracker->expects($this->once())->method('trackIfApplicable')->withAnyParameters();

View file

@ -42,7 +42,7 @@ class QrCodeActionTest extends TestCase
{
$shortCode = 'abc123';
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
$delegate = $this->createMock(RequestHandlerInterface::class);
$delegate->expects($this->once())->method('handle')->withAnyParameters()->willReturn(new Response());
@ -55,7 +55,7 @@ class QrCodeActionTest extends TestCase
{
$shortCode = 'abc123';
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
)->willReturn(ShortUrl::createEmpty());
$delegate = $this->createMock(RequestHandlerInterface::class);
$delegate->expects($this->never())->method('handle');
@ -77,7 +77,7 @@ class QrCodeActionTest extends TestCase
): void {
$code = 'abc123';
$this->urlResolver->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
)->willReturn(ShortUrl::createEmpty());
$delegate = $this->createMock(RequestHandlerInterface::class);
$req = (new ServerRequest())->withAttribute('shortCode', $code)->withQueryParams($query);
@ -110,7 +110,7 @@ class QrCodeActionTest extends TestCase
): void {
$code = 'abc123';
$this->urlResolver->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
)->willReturn(ShortUrl::createEmpty());
$delegate = $this->createMock(RequestHandlerInterface::class);
@ -201,7 +201,7 @@ class QrCodeActionTest extends TestCase
->withAttribute('shortCode', $code);
$this->urlResolver->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($code, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($code, ''),
)->willReturn(ShortUrl::withLongUrl('https://shlink.io'));
$delegate = $this->createMock(RequestHandlerInterface::class);

View file

@ -50,12 +50,12 @@ class RedirectActionTest extends TestCase
$shortCode = 'abc123';
$shortUrl = ShortUrl::withLongUrl(self::LONG_URL);
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
)->willReturn($shortUrl);
$this->requestTracker->expects($this->once())->method('trackIfApplicable');
$expectedResp = new Response\RedirectResponse(self::LONG_URL);
$this->redirectRespHelper->expects($this->once())->method('buildRedirectResponse')->with(
$this->equalTo(self::LONG_URL),
self::LONG_URL,
)->willReturn($expectedResp);
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
@ -69,7 +69,7 @@ class RedirectActionTest extends TestCase
{
$shortCode = 'abc123';
$this->urlResolver->expects($this->once())->method('resolveEnabledShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')),
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''),
)->willThrowException(ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain('')));
$this->requestTracker->expects($this->never())->method('trackIfApplicable');

View file

@ -43,9 +43,9 @@ class NotFoundRedirectResolverTest extends TestCase
string $expectedRedirectTo,
): void {
$expectedResp = new Response();
$this->helper->expects($this->once())->method('buildRedirectResponse')->with(
$this->equalTo($expectedRedirectTo),
)->willReturn($expectedResp);
$this->helper->expects($this->once())->method('buildRedirectResponse')->with($expectedRedirectTo)->willReturn(
$expectedResp,
);
$resp = $this->resolver->resolveRedirectResponse($notFoundType, $redirectConfig, $uri);

View file

@ -27,9 +27,7 @@ class CrawlingHelperTest extends TestCase
{
$repo = $this->createMock(ShortUrlRepositoryInterface::class);
$repo->expects($this->once())->method('findCrawlableShortCodes')->willReturn([]);
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(ShortUrl::class))->willReturn(
$repo,
);
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
$result = $this->helper->listCrawlableShortCodes();
foreach ($result as $shortCode) {

View file

@ -36,10 +36,8 @@ class DomainServiceTest extends TestCase
public function listDomainsDelegatesIntoRepository(array $domains, array $expectedResult, ?ApiKey $apiKey): void
{
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->expects($this->once())->method('findDomains')->with($this->equalTo($apiKey))->willReturn($domains);
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
$repo,
);
$repo->expects($this->once())->method('findDomains')->with($apiKey)->willReturn($domains);
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
$result = $this->domainService->listDomains($apiKey);
@ -105,10 +103,7 @@ class DomainServiceTest extends TestCase
/** @test */
public function getDomainThrowsExceptionWhenDomainIsNotFound(): void
{
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Domain::class),
$this->equalTo('123'),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(Domain::class, '123')->willReturn(null);
$this->expectException(DomainNotFoundException::class);
@ -119,10 +114,7 @@ class DomainServiceTest extends TestCase
public function getDomainReturnsEntityWhenFound(): void
{
$domain = Domain::withAuthority('');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Domain::class),
$this->equalTo('123'),
)->willReturn($domain);
$this->em->expects($this->once())->method('find')->with(Domain::class, '123')->willReturn($domain);
$result = $this->domainService->getDomain('123');
@ -137,15 +129,11 @@ class DomainServiceTest extends TestCase
{
$authority = 'example.com';
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn(
$foundDomain,
);
$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('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('flush');
$result = $this->domainService->getOrCreate($authority, $apiKey);
@ -162,12 +150,8 @@ class DomainServiceTest extends TestCase
$domain = Domain::withAuthority($authority)->setId('1');
$apiKey = ApiKey::fromMeta(ApiKeyMeta::withRoles(RoleDefinition::forDomain($domain)));
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
null,
);
$this->em->expects($this->once())->method('getRepository')->with($this->equalTo(Domain::class))->willReturn(
$repo,
);
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn(null);
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
$this->em->expects($this->never())->method('persist');
$this->em->expects($this->never())->method('flush');
@ -184,15 +168,9 @@ class DomainServiceTest extends TestCase
{
$authority = 'example.com';
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->method('findOneByAuthority')->with($this->equalTo($authority), $this->equalTo($apiKey))->willReturn(
$foundDomain,
);
$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),
);
$repo->method('findOneByAuthority')->with($authority, $apiKey)->willReturn($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('flush');
$result = $this->domainService->configureNotFoundRedirects($authority, NotFoundRedirects::withRedirects(

View file

@ -51,9 +51,7 @@ class NotFoundRedirectHandlerTest extends TestCase
$expectedResp = new Response();
$setUp($this->domainService, $this->resolver);
$this->next->expects($this->once())->method('handle')->with($this->equalTo($this->req))->willReturn(
$expectedResp,
);
$this->next->expects($this->once())->method('handle')->with($this->req)->willReturn($expectedResp);
$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->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
$this->isInstanceOf(NotFoundType::class),
$this->equalTo($this->redirectOptions),
$this->redirectOptions,
$this->isInstanceOf(UriInterface::class),
)->willReturn($expectedResp);
$this->next->expects($this->never())->method('handle');
@ -126,7 +124,7 @@ class NotFoundRedirectHandlerTest extends TestCase
);
$this->resolver->expects($this->once())->method('resolveRedirectResponse')->with(
$this->isInstanceOf(NotFoundType::class),
$this->equalTo($domain),
$domain,
$this->isInstanceOf(UriInterface::class),
)->willReturn($expectedResp);
$this->next->expects($this->never())->method('handle');

View file

@ -35,10 +35,8 @@ class NotFoundTrackerMiddlewareTest extends TestCase
/** @test */
public function delegatesIntoRequestTracker(): void
{
$this->handler->expects($this->once())->method('handle')->with($this->equalTo($this->request));
$this->requestTracker->expects($this->once())->method('trackNotFoundIfApplicable')->with(
$this->equalTo($this->request),
);
$this->handler->expects($this->once())->method('handle')->with($this->request);
$this->requestTracker->expects($this->once())->method('trackNotFoundIfApplicable')->with($this->request);
$this->middleware->process($this->request, $this->handler);
}

View file

@ -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),
);

View file

@ -31,7 +31,7 @@ class LocateUnlocatedVisitsTest extends TestCase
/** @test */
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());
}
@ -41,9 +41,9 @@ class LocateUnlocatedVisitsTest extends TestCase
$visit = Visit::forBasePath(Visitor::emptyInstance());
$location = Location::emptyInstance();
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->with(
$this->equalTo($visit),
)->willReturn($location);
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->with($visit)->willReturn(
$location,
);
$result = $this->listener->geolocateVisit($visit);

View file

@ -53,18 +53,13 @@ class LocateVisitTest extends TestCase
public function invalidVisitLogsWarning(): void
{
$event = new UrlVisited('123');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(null);
$this->em->expects($this->never())->method('flush');
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to locate visit with id "{visitId}", but it does not exist.'),
$this->equalTo(['visitId' => 123]),
);
$this->eventDispatcher->expects($this->never())->method('dispatch')->with(
$this->equalTo(new VisitLocated('123')),
'Tried to locate visit with id "{visitId}", but it does not exist.',
['visitId' => 123],
);
$this->eventDispatcher->expects($this->never())->method('dispatch')->with(new VisitLocated('123'));
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
($this->locateVisit)($event);
@ -74,19 +69,16 @@ class LocateVisitTest extends TestCase
public function nonExistingGeoLiteDbLogsWarning(): void
{
$event = new UrlVisited('123');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
);
$this->em->expects($this->never())->method('flush');
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(false);
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.'),
$this->equalTo(['visitId' => 123]),
);
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
$this->equalTo(new VisitLocated('123')),
'Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.',
['visitId' => 123],
);
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
($this->locateVisit)($event);
@ -96,22 +88,19 @@ class LocateVisitTest extends TestCase
public function invalidAddressLogsWarning(): void
{
$event = new UrlVisited('123');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
);
$this->em->expects($this->never())->method('flush');
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
$this->ipLocationResolver->expects(
$this->once(),
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(WrongIpException::fromIpAddress(''));
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}'),
'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}',
$this->isType('array'),
);
$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->locateVisit)($event);
}
@ -120,22 +109,19 @@ class LocateVisitTest extends TestCase
public function unhandledExceptionLogsError(): void
{
$event = new UrlVisited('123');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')));
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn(
Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')),
);
$this->em->expects($this->never())->method('flush');
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
$this->ipLocationResolver->expects(
$this->once(),
)->method('resolveIpLocation')->withAnyParameters()->willThrowException(new OutOfRangeException());
$this->logger->expects($this->once())->method('error')->with(
$this->equalTo('An unexpected error occurred while trying to locate visit with id "{visitId}". {e}'),
'An unexpected error occurred while trying to locate visit with id "{visitId}". {e}',
$this->isType('array'),
);
$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->locateVisit)($event);
}
@ -147,17 +133,12 @@ class LocateVisitTest extends TestCase
public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void
{
$event = new UrlVisited('123');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn($visit);
$this->em->expects($this->once())->method('flush');
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
$this->ipLocationResolver->expects($this->never())->method('resolveIpLocation');
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
$this->equalTo(new VisitLocated('123')),
);
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
$this->logger->expects($this->never())->method('warning');
($this->locateVisit)($event);
@ -184,19 +165,14 @@ class LocateVisitTest extends TestCase
$location = new Location('', '', '', '', 0.0, 0.0, '');
$event = UrlVisited::withOriginalIpAddress('123', $originalIpAddress);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('123'),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, '123')->willReturn($visit);
$this->em->expects($this->once())->method('flush');
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true);
$this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with(
$this->equalTo($ipAddr),
)->willReturn($location);
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(
$this->equalTo(new VisitLocated('123')),
$this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with($ipAddr)->willReturn(
$location,
);
$this->eventDispatcher->expects($this->once())->method('dispatch')->with(new VisitLocated('123'));
$this->logger->expects($this->never())->method('warning');
($this->locateVisit)($event);

View file

@ -42,15 +42,12 @@ class NotifyNewShortUrlToMercureTest extends TestCase
/** @test */
public function messageIsLoggedWhenShortUrlIsNotFound(): void
{
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo('123'),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn(null);
$this->helper->expects($this->never())->method('publishUpdate');
$this->updatesGenerator->expects($this->never())->method('newShortUrlUpdate');
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.'),
$this->equalTo(['shortUrlId' => '123', 'name' => 'Mercure']),
'Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.',
['shortUrlId' => '123', 'name' => 'Mercure'],
);
$this->logger->expects($this->never())->method('debug');
@ -63,14 +60,11 @@ class NotifyNewShortUrlToMercureTest extends TestCase
$shortUrl = ShortUrl::withLongUrl('');
$update = Update::forTopicAndPayload('', []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo('123'),
)->willReturn($shortUrl);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
$this->equalTo($shortUrl),
)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with($this->equalTo($update));
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn($shortUrl);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with($shortUrl)->willReturn(
$update,
);
$this->helper->expects($this->once())->method('publishUpdate')->with($update);
$this->logger->expects($this->never())->method('warning');
$this->logger->expects($this->never())->method('debug');
@ -85,19 +79,17 @@ class NotifyNewShortUrlToMercureTest extends TestCase
$e = new Exception('Error');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo('123'),
ShortUrl::class,
'123',
)->willReturn($shortUrl);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
$this->equalTo($shortUrl),
)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with(
$this->equalTo($update),
)->willThrowException($e);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with($shortUrl)->willReturn(
$update,
);
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
$this->logger->expects($this->never())->method('warning');
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
'Error while trying to notify {name} with new short URL. {e}',
['e' => $e, 'name' => 'Mercure'],
);
($this->listener)(new ShortUrlCreated('123'));

View file

@ -41,13 +41,10 @@ class NotifyVisitToMercureTest extends TestCase
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
{
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(null);
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to notify {name} for visit with id "{visitId}", but it does not exist.'),
$this->equalTo(['visitId' => $visitId, 'name' => 'Mercure']),
'Tried to notify {name} for visit with id "{visitId}", but it does not exist.',
['visitId' => $visitId, 'name' => 'Mercure'],
);
$this->logger->expects($this->never())->method('debug');
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
@ -65,20 +62,15 @@ class NotifyVisitToMercureTest extends TestCase
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance());
$update = Update::forTopicAndPayload('', []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
$this->logger->expects($this->never())->method('warning');
$this->logger->expects($this->never())->method('debug');
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with(
$this->equalTo($visit),
)->willReturn($update);
$this->updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->with($visit)->willReturn(
$update,
);
$this->updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with(
$this->equalTo($visit),
)->willReturn($update);
$this->helper->expects($this->exactly(2))->method('publishUpdate')->with($this->equalTo($update));
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update);
$this->helper->expects($this->exactly(2))->method('publishUpdate')->with($update);
($this->listener)(new VisitLocated($visitId));
}
@ -91,25 +83,18 @@ class NotifyVisitToMercureTest extends TestCase
$update = Update::forTopicAndPayload('', []);
$e = new RuntimeException('Error');
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
$this->logger->expects($this->never())->method('warning');
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
$this->equalTo(['e' => $e, 'name' => 'Mercure']),
'Error while trying to notify {name} with new visit. {e}',
['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->once())->method('newVisitUpdate')->with(
$this->equalTo($visit),
)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with(
$this->equalTo($update),
)->willThrowException($e);
$this->updatesGenerator->expects($this->once())->method('newVisitUpdate')->with($visit)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
($this->listener)(new VisitLocated($visitId));
}
@ -123,18 +108,15 @@ class NotifyVisitToMercureTest extends TestCase
$visitId = '123';
$update = Update::forTopicAndPayload('', []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
$this->logger->expects($this->never())->method('warning');
$this->logger->expects($this->never())->method('debug');
$this->updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
$this->equalTo($visit),
)->willReturn($update);
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with($visit)->willReturn(
$update,
);
$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));
}

View file

@ -52,14 +52,11 @@ class NotifyVisitToWebHooksTest extends TestCase
/** @test */
public function invalidVisitDoesNotPerformAnyRequest(): void
{
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('1'),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn(null);
$this->httpClient->expects($this->never())->method('requestAsync');
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to notify webhooks for visit with id "{visitId}", but it does not exist.'),
$this->equalTo(['visitId' => '1']),
'Tried to notify webhooks for visit with id "{visitId}", but it does not exist.',
['visitId' => '1'],
);
$this->createListener(['foo', 'bar'])(new VisitLocated('1'));
@ -68,10 +65,9 @@ class NotifyVisitToWebHooksTest extends TestCase
/** @test */
public function orphanVisitDoesNotPerformAnyRequestWhenDisabled(): void
{
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('1'),
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn(
Visit::forBasePath(Visitor::emptyInstance()),
);
$this->httpClient->expects($this->never())->method('requestAsync');
$this->logger->expects($this->never())->method('warning');
@ -87,12 +83,9 @@ class NotifyVisitToWebHooksTest extends TestCase
$webhooks = ['foo', 'invalid', 'bar', 'baz'];
$invalidWebhooks = ['invalid', 'baz'];
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo('1'),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn($visit);
$this->httpClient->expects($this->exactly(count($webhooks)))->method('requestAsync')->with(
$this->equalTo(RequestMethodInterface::METHOD_POST),
RequestMethodInterface::METHOD_POST,
$this->istype('string'),
$this->callback(function (array $requestOptions) use ($expectedResponseKeys) {
Assert::assertArrayHasKey(RequestOptions::HEADERS, $requestOptions);
@ -114,7 +107,7 @@ class NotifyVisitToWebHooksTest extends TestCase
return $shouldReject ? new RejectedPromise(new Exception('')) : new FulfilledPromise('');
});
$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 {
Assert::assertArrayHasKey('webhook', $extra);
Assert::assertArrayHasKey('visitId', $extra);

View file

@ -51,13 +51,10 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
public function notificationsAreNotSentWhenShortUrlCannotBeFound(): void
{
$shortUrlId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo($shortUrlId),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(null);
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.'),
$this->equalTo(['shortUrlId' => $shortUrlId, 'name' => 'RabbitMQ']),
'Tried to notify {name} for new short URL with id "{shortUrlId}", but it does not exist.',
['shortUrlId' => $shortUrlId, 'name' => 'RabbitMQ'],
);
$this->logger->expects($this->never())->method('debug');
$this->helper->expects($this->never())->method('publishUpdate');
@ -70,14 +67,13 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
{
$shortUrlId = '123';
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo($shortUrlId),
)->willReturn(ShortUrl::withLongUrl(''));
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
ShortUrl::withLongUrl(''),
);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
$this->isInstanceOf(ShortUrl::class),
)->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->listener())(new ShortUrlCreated($shortUrlId));
@ -91,19 +87,16 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
{
$shortUrlId = '123';
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo($shortUrlId),
)->willReturn(ShortUrl::withLongUrl(''));
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
ShortUrl::withLongUrl(''),
);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
$this->isInstanceOf(ShortUrl::class),
)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with(
$this->equalTo($update),
)->willThrowException($e);
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
$this->equalTo(['e' => $e, 'name' => 'RabbitMQ']),
'Error while trying to notify {name} with new short URL. {e}',
['e' => $e, 'name' => 'RabbitMQ'],
);
($this->listener())(new ShortUrlCreated($shortUrlId));

View file

@ -59,13 +59,10 @@ class NotifyVisitToRabbitMqTest extends TestCase
public function notificationsAreNotSentWhenVisitCannotBeFound(): void
{
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn(null);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(null);
$this->logger->expects($this->once())->method('warning')->with(
$this->equalTo('Tried to notify {name} for visit with id "{visitId}", but it does not exist.'),
$this->equalTo(['visitId' => $visitId, 'name' => 'RabbitMQ']),
'Tried to notify {name} for visit with id "{visitId}", but it does not exist.',
['visitId' => $visitId, 'name' => 'RabbitMQ'],
);
$this->logger->expects($this->never())->method('debug');
$this->helper->expects($this->never())->method('publishUpdate');
@ -80,10 +77,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
public function expectedChannelsAreNotifiedBasedOnTheVisitType(Visit $visit, array $expectedChannels): void
{
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
each($expectedChannels, function (string $method): void {
$this->updatesGenerator->expects($this->once())->method($method)->with(
$this->isInstanceOf(Visit::class),
@ -121,17 +115,16 @@ class NotifyVisitToRabbitMqTest extends TestCase
public function printsDebugMessageInCaseOfError(Throwable $e): void
{
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(
Visit::forBasePath(Visitor::emptyInstance()),
);
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
$this->isInstanceOf(Visit::class),
)->willReturn(Update::forTopicAndPayload('', []));
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
$this->equalTo(['e' => $e, 'name' => 'RabbitMQ']),
'Error while trying to notify {name} with new visit. {e}',
['e' => $e, 'name' => 'RabbitMQ'],
);
($this->listener())(new VisitLocated($visitId));
@ -155,10 +148,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
callable $expect,
): void {
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn($visit);
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn($visit);
$setup($this->updatesGenerator);
$expect($this->helper, $this->updatesGenerator);

View file

@ -54,19 +54,16 @@ class NotifyNewShortUrlToRedisTest extends TestCase
{
$shortUrlId = '123';
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(ShortUrl::class),
$this->equalTo($shortUrlId),
)->willReturn(ShortUrl::withLongUrl(''));
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
ShortUrl::withLongUrl(''),
);
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
$this->isInstanceOf(ShortUrl::class),
)->willReturn($update);
$this->helper->expects($this->once())->method('publishUpdate')->with(
$this->equalTo($update),
)->willThrowException($e);
$this->helper->expects($this->once())->method('publishUpdate')->with($update)->willThrowException($e);
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new short URL. {e}'),
$this->equalTo(['e' => $e, 'name' => 'Redis pub/sub']),
'Error while trying to notify {name} with new short URL. {e}',
['e' => $e, 'name' => 'Redis pub/sub'],
);
$this->createListener()(new ShortUrlCreated($shortUrlId));

View file

@ -53,17 +53,16 @@ class NotifyVisitToRedisTest extends TestCase
public function printsDebugMessageInCaseOfError(Throwable $e): void
{
$visitId = '123';
$this->em->expects($this->once())->method('find')->with(
$this->equalTo(Visit::class),
$this->equalTo($visitId),
)->willReturn(Visit::forBasePath(Visitor::emptyInstance()));
$this->em->expects($this->once())->method('find')->with(Visit::class, $visitId)->willReturn(
Visit::forBasePath(Visitor::emptyInstance()),
);
$this->updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->with(
$this->isInstanceOf(Visit::class),
)->willReturn(Update::forTopicAndPayload('', []));
$this->helper->expects($this->once())->method('publishUpdate')->withAnyParameters()->willThrowException($e);
$this->logger->expects($this->once())->method('debug')->with(
$this->equalTo('Error while trying to notify {name} with new visit. {e}'),
$this->equalTo(['e' => $e, 'name' => 'Redis pub/sub']),
'Error while trying to notify {name} with new visit. {e}',
['e' => $e, 'name' => 'Redis pub/sub'],
);
$this->createListener()(new VisitLocated($visitId));

View file

@ -39,8 +39,8 @@ class UpdateGeoLiteDbTest extends TestCase
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willThrowException($e);
$this->logger->expects($this->once())->method('error')->with(
$this->equalTo('GeoLite2 database download failed. {e}'),
$this->equalTo(['e' => $e]),
'GeoLite2 database download failed. {e}',
['e' => $e],
);
$this->logger->expects($this->never())->method('notice');
$this->eventDispatcher->expects($this->never())->method('dispatch');
@ -60,7 +60,7 @@ class UpdateGeoLiteDbTest extends TestCase
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->eventDispatcher->expects($this->never())->method('dispatch');
@ -94,7 +94,7 @@ class UpdateGeoLiteDbTest extends TestCase
},
);
$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->eventDispatcher->expects($this->never())->method('dispatch');
@ -123,7 +123,7 @@ class UpdateGeoLiteDbTest extends TestCase
): void {
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturn($result);
$this->eventDispatcher->expects($this->exactly($expectedDispatches))->method('dispatch')->with(
$this->equalTo(new GeoLiteDbCreated()),
new GeoLiteDbCreated(),
);
($this->listener)();

View file

@ -41,7 +41,7 @@ class ImportedLinksProcessorTest extends TestCase
{
$this->em = $this->createMock(EntityManagerInterface::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);
$batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);

View file

@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException;
use Shlinkio\Shlink\Core\Options\DeleteShortUrlsOptions;
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlService;
@ -25,10 +23,8 @@ use function sprintf;
class DeleteShortUrlServiceTest extends TestCase
{
use ProphecyTrait;
private ObjectProphecy $em;
private ObjectProphecy $urlResolver;
private MockObject $em;
private MockObject $urlResolver;
private string $shortCode;
protected function setUp(): void
@ -38,10 +34,10 @@ class DeleteShortUrlServiceTest extends TestCase
));
$this->shortCode = $shortUrl->getShortCode();
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->em = $this->createMock(EntityManagerInterface::class);
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
$this->urlResolver->resolveShortUrl(Argument::cetera())->willReturn($shortUrl);
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
$this->urlResolver->method('resolveShortUrl')->willReturn($shortUrl);
}
/** @test */
@ -63,13 +59,12 @@ class DeleteShortUrlServiceTest extends TestCase
{
$service = $this->createService();
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
null,
);
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode), true);
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();
}
/** @test */
@ -77,13 +72,12 @@ class DeleteShortUrlServiceTest extends TestCase
{
$service = $this->createService(false);
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
null,
);
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();
}
/** @test */
@ -91,20 +85,19 @@ class DeleteShortUrlServiceTest extends TestCase
{
$service = $this->createService(true, 100);
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
$flush = $this->em->flush()->willReturn(null);
$this->em->expects($this->once())->method('remove')->with($this->isInstanceOf(ShortUrl::class))->willReturn(
null,
);
$this->em->expects($this->once())->method('flush')->with()->willReturn(null);
$service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode));
$remove->shouldHaveBeenCalledOnce();
$flush->shouldHaveBeenCalledOnce();
}
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,
$checkVisitsThreshold,
), $this->urlResolver->reveal());
), $this->urlResolver);
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortCodeUniquenessHelper;
@ -16,19 +15,17 @@ use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlRepository;
class ShortCodeUniquenessHelperTest extends TestCase
{
use ProphecyTrait;
private ShortCodeUniquenessHelper $helper;
private ObjectProphecy $em;
private ObjectProphecy $shortUrl;
private MockObject $em;
private MockObject $shortUrl;
protected function setUp(): void
{
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->helper = new ShortCodeUniquenessHelper($this->em->reveal());
$this->em = $this->createMock(EntityManagerInterface::class);
$this->helper = new ShortCodeUniquenessHelper($this->em);
$this->shortUrl = $this->prophesize(ShortUrl::class);
$this->shortUrl->getShortCode()->willReturn('abc123');
$this->shortUrl = $this->createMock(ShortUrl::class);
$this->shortUrl->method('getShortCode')->willReturn('abc123');
}
/**
@ -39,22 +36,22 @@ class ShortCodeUniquenessHelperTest extends TestCase
{
$callIndex = 0;
$expectedCalls = 3;
$repo = $this->prophesize(ShortUrlRepository::class);
$shortCodeIsInUse = $repo->shortCodeIsInUseWithLock(
$repo = $this->createMock(ShortUrlRepository::class);
$repo->expects($this->exactly($expectedCalls))->method('shortCodeIsInUseWithLock')->with(
ShortUrlIdentifier::fromShortCodeAndDomain('abc123', $expectedAuthority),
)->will(function () use (&$callIndex, $expectedCalls) {
)->willReturnCallback(function () use (&$callIndex, $expectedCalls) {
$callIndex++;
return $callIndex < $expectedCalls;
});
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$this->shortUrl->getDomain()->willReturn($domain);
$this->em->expects($this->exactly($expectedCalls))->method('getRepository')->with(ShortUrl::class)->willReturn(
$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);
$this->shortUrl->regenerateShortCode()->shouldHaveBeenCalledTimes($expectedCalls - 1);
$getRepo->shouldBeCalledTimes($expectedCalls);
$shortCodeIsInUse->shouldBeCalledTimes($expectedCalls);
}
public function provideDomains(): iterable
@ -66,18 +63,16 @@ class ShortCodeUniquenessHelperTest extends TestCase
/** @test */
public function inUseSlugReturnsError(): void
{
$repo = $this->prophesize(ShortUrlRepository::class);
$shortCodeIsInUse = $repo->shortCodeIsInUseWithLock(
$repo = $this->createMock(ShortUrlRepository::class);
$repo->expects($this->once())->method('shortCodeIsInUseWithLock')->with(
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
)->willReturn(true);
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$this->shortUrl->getDomain()->willReturn(null);
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
$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);
$this->shortUrl->regenerateShortCode()->shouldNotHaveBeenCalled();
$getRepo->shouldBeCalledOnce();
$shortCodeIsInUse->shouldBeCalledOnce();
}
}

View file

@ -4,24 +4,21 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelper;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\Util\UrlValidatorInterface;
class ShortUrlTitleResolutionHelperTest extends TestCase
{
use ProphecyTrait;
private ShortUrlTitleResolutionHelper $helper;
private ObjectProphecy $urlValidator;
private MockObject $urlValidator;
protected function setUp(): void
{
$this->urlValidator = $this->prophesize(UrlValidatorInterface::class);
$this->helper = new ShortUrlTitleResolutionHelper($this->urlValidator->reveal());
$this->urlValidator = $this->createMock(UrlValidatorInterface::class);
$this->helper = new ShortUrlTitleResolutionHelper($this->urlValidator);
}
/**
@ -31,14 +28,18 @@ class ShortUrlTitleResolutionHelperTest extends TestCase
public function urlIsProperlyShortened(?string $title, int $validateWithTitleCallsNum, int $validateCallsNum): void
{
$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(
ShortUrlCreation::fromRawData(['longUrl' => $longUrl, 'title' => $title]),
);
$this->urlValidator->validateUrlWithTitle($longUrl, false)->shouldHaveBeenCalledTimes(
$validateWithTitleCallsNum,
);
$this->urlValidator->validateUrl($longUrl, false)->shouldHaveBeenCalledTimes($validateCallsNum);
}
public function provideTitles(): iterable

View file

@ -9,10 +9,8 @@ use Laminas\Diactoros\ServerRequestFactory;
use Laminas\Diactoros\Uri;
use Mezzio\Router\Route;
use Mezzio\Router\RouteResult;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
@ -32,22 +30,20 @@ use function str_starts_with;
class ExtraPathRedirectMiddlewareTest extends TestCase
{
use ProphecyTrait;
private ObjectProphecy $resolver;
private ObjectProphecy $requestTracker;
private ObjectProphecy $redirectionBuilder;
private ObjectProphecy $redirectResponseHelper;
private ObjectProphecy $handler;
private MockObject $resolver;
private MockObject $requestTracker;
private MockObject $redirectionBuilder;
private MockObject $redirectResponseHelper;
private MockObject $handler;
protected function setUp(): void
{
$this->resolver = $this->prophesize(ShortUrlResolverInterface::class);
$this->requestTracker = $this->prophesize(RequestTrackerInterface::class);
$this->redirectionBuilder = $this->prophesize(ShortUrlRedirectionBuilderInterface::class);
$this->redirectResponseHelper = $this->prophesize(RedirectResponseHelperInterface::class);
$this->handler = $this->prophesize(RequestHandlerInterface::class);
$this->handler->handle(Argument::cetera())->willReturn(new RedirectResponse(''));
$this->resolver = $this->createMock(ShortUrlResolverInterface::class);
$this->requestTracker = $this->createMock(RequestTrackerInterface::class);
$this->redirectionBuilder = $this->createMock(ShortUrlRedirectionBuilderInterface::class);
$this->redirectResponseHelper = $this->createMock(RedirectResponseHelperInterface::class);
$this->handler = $this->createMock(RequestHandlerInterface::class);
$this->handler->method('handle')->willReturn(new RedirectResponse(''));
}
/**
@ -63,14 +59,13 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
appendExtraPath: $appendExtraPath,
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->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();
$this->middleware($options)->process($request, $this->handler);
}
public function provideNonRedirectingRequests(): iterable
@ -89,7 +84,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
RouteResult::class,
RouteResult::fromRoute(new Route(
'/foo',
$this->prophesize(MiddlewareInterface::class)->reveal(),
$this->createMock(MiddlewareInterface::class),
['GET'],
RedirectAction::class,
)),
@ -115,22 +110,20 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
): void {
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
$type = $this->prophesize(NotFoundType::class);
$type->isRegularNotFound()->willReturn(true);
$type->isInvalidShortUrl()->willReturn(true);
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
$type = $this->createMock(NotFoundType::class);
$type->method('isRegularNotFound')->willReturn(true);
$type->method('isInvalidShortUrl')->willReturn(true);
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type)
->withUri(new Uri('/shortCode/bar/baz'));
$resolve = $this->resolver->resolveEnabledShortUrl(
Argument::that(fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode')),
)->willThrow(ShortUrlNotFoundException::class);
$this->resolver->expects($this->exactly($expectedResolveCalls))->method('resolveEnabledShortUrl')->with(
$this->callback(fn (ShortUrlIdentifier $id) => str_starts_with($id->shortCode, 'shortCode')),
)->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());
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
$this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotHaveBeenCalled();
$this->redirectionBuilder->buildShortUrlRedirect(Argument::cetera())->shouldNotHaveBeenCalled();
$this->redirectResponseHelper->buildRedirectResponse(Argument::cetera())->shouldNotHaveBeenCalled();
$this->middleware($options)->process($request, $this->handler);
}
/**
@ -144,18 +137,17 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
): void {
$options = new UrlShortenerOptions(appendExtraPath: true, multiSegmentSlugsEnabled: $multiSegmentEnabled);
$type = $this->prophesize(NotFoundType::class);
$type->isRegularNotFound()->willReturn(true);
$type->isInvalidShortUrl()->willReturn(true);
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
$type = $this->createMock(NotFoundType::class);
$type->method('isRegularNotFound')->willReturn(true);
$type->method('isInvalidShortUrl')->willReturn(true);
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type)
->withUri(new Uri('https://doma.in/shortCode/bar/baz'));
$shortUrl = ShortUrl::withLongUrl('');
$identifier = Argument::that(
fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode'),
);
$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 {
if ($expectedResolveCalls === $currentIteration) {
return $shortUrl;
@ -165,18 +157,17 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
throw ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortUrl($shortUrl));
},
);
$buildLongUrl = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, [], $expectedExtraPath)
->willReturn('the_built_long_url');
$buildResp = $this->redirectResponseHelper->buildRedirectResponse('the_built_long_url')->willReturn(
new RedirectResponse(''),
);
$this->redirectionBuilder->expects($this->once())->method('buildShortUrlRedirect')->with(
$shortUrl,
[],
$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());
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
$buildLongUrl->shouldHaveBeenCalledOnce();
$buildResp->shouldHaveBeenCalledOnce();
$this->requestTracker->trackIfApplicable($shortUrl, $request)->shouldHaveBeenCalledOnce();
$this->middleware($options)->process($request, $this->handler);
}
public function provideResolves(): iterable
@ -188,10 +179,10 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
private function middleware(?UrlShortenerOptions $options = null): ExtraPathRedirectMiddleware
{
return new ExtraPathRedirectMiddleware(
$this->resolver->reveal(),
$this->requestTracker->reveal(),
$this->redirectionBuilder->reveal(),
$this->redirectResponseHelper->reveal(),
$this->resolver,
$this->requestTracker,
$this->redirectionBuilder,
$this->redirectResponseHelper,
$options ?? new UrlShortenerOptions(appendExtraPath: true),
);
}

View file

@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Middleware;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
@ -21,13 +19,11 @@ use function Functional\const_function;
class TrimTrailingSlashMiddlewareTest extends TestCase
{
use ProphecyTrait;
private ObjectProphecy $requestHandler;
private MockObject $requestHandler;
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,
): void {
$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->reveal());
$this->middleware($trailingSlashEnabled)->process($inputRequest, $this->requestHandler);
}
public function provideRequests(): iterable

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ShortUrl\Paginator\Adapter;
use Cake\Chronos\Chronos;
use PHPUnit\Framework\MockObject\MockObject;
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\TagsMode;
use Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter\ShortUrlRepositoryAdapter;
@ -18,13 +17,11 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey;
class ShortUrlRepositoryAdapterTest extends TestCase
{
use ProphecyTrait;
private ObjectProphecy $repo;
private MockObject $repo;
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,
'orderBy' => $orderBy,
]);
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $params, null);
$adapter = new ShortUrlRepositoryAdapter($this->repo, $params, null);
$orderBy = $params->orderBy();
$dateRange = $params->dateRange();
$this->repo->findList(
$this->repo->expects($this->once())->method('findList')->with(
new ShortUrlsListFiltering(10, 5, $orderBy, $searchTerm, $tags, TagsMode::ANY, $dateRange),
)->shouldBeCalledOnce();
);
$adapter->getSlice(5, 10);
}
@ -72,12 +70,12 @@ class ShortUrlRepositoryAdapterTest extends TestCase
'endDate' => $endDate,
]);
$apiKey = ApiKey::create();
$adapter = new ShortUrlRepositoryAdapter($this->repo->reveal(), $params, $apiKey);
$adapter = new ShortUrlRepositoryAdapter($this->repo, $params, $apiKey);
$dateRange = $params->dateRange();
$this->repo->countList(
$this->repo->expects($this->once())->method('countList')->with(
new ShortUrlsCountFiltering($searchTerm, $tags, TagsMode::ANY, $dateRange, $apiKey),
)->shouldBeCalledOnce();
);
$adapter->getNbResults();
}

View file

@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Resolver;
use Doctrine\Common\EventManager;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\Domain\Repository\DomainRepositoryInterface;
use Shlinkio\Shlink\Core\ShortUrl\Resolver\PersistenceShortUrlRelationResolver;
@ -20,26 +18,22 @@ use function count;
class PersistenceShortUrlRelationResolverTest extends TestCase
{
use ProphecyTrait;
private PersistenceShortUrlRelationResolver $resolver;
private ObjectProphecy $em;
private MockObject $em;
protected function setUp(): void
{
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->em->getEventManager()->willReturn(new EventManager());
$this->em = $this->createMock(EntityManagerInterface::class);
$this->em->method('getEventManager')->willReturn(new EventManager());
$this->resolver = new PersistenceShortUrlRelationResolver($this->em->reveal());
$this->resolver = new PersistenceShortUrlRelationResolver($this->em);
}
/** @test */
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));
$getRepository->shouldNotHaveBeenCalled();
}
/**
@ -48,9 +42,9 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
*/
public function findsOrCreatesDomainWhenValueIsProvided(?Domain $foundDomain, string $authority): void
{
$repo = $this->prophesize(DomainRepositoryInterface::class);
$findDomain = $repo->findOneBy(['authority' => $authority])->willReturn($foundDomain);
$getRepository = $this->em->getRepository(Domain::class)->willReturn($repo->reveal());
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->expects($this->once())->method('findOneBy')->with(['authority' => $authority])->willReturn($foundDomain);
$this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo);
$result = $this->resolver->resolveDomain($authority);
@ -59,8 +53,6 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
}
self::assertInstanceOf(Domain::class, $result);
self::assertEquals($authority, $result->getAuthority());
$findDomain->shouldHaveBeenCalledOnce();
$getRepository->shouldHaveBeenCalledOnce();
}
public function provideFoundDomains(): iterable
@ -79,21 +71,22 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
{
$expectedPersistedTags = count($expectedTags);
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
$findTag = $tagRepo->findOneBy(Argument::type('array'))->will(function (array $args): ?Tag {
['name' => $name] = $args[0];
$tagRepo = $this->createMock(TagRepositoryInterface::class);
$tagRepo->expects($this->exactly($expectedPersistedTags))->method('findOneBy')->with(
$this->isType('array'),
)->willReturnCallback(function (array $criteria): ?Tag {
['name' => $name] = $criteria;
return $name === 'foo' ? new Tag($name) : null;
});
$getRepo = $this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
$persist = $this->em->persist(Argument::type(Tag::class));
$this->em->expects($this->once())->method('getRepository')->with(Tag::class)->willReturn($tagRepo);
$this->em->expects($this->exactly($expectedPersistedTags))->method('persist')->with(
$this->isInstanceOf(Tag::class),
);
$result = $this->resolver->resolveTags($tags);
self::assertCount($expectedPersistedTags, $result);
self::assertEquals($expectedTags, $result->toArray());
$findTag->shouldHaveBeenCalledTimes($expectedPersistedTags);
$getRepo->shouldHaveBeenCalledOnce();
$persist->shouldHaveBeenCalledTimes($expectedPersistedTags);
}
public function provideTags(): iterable
@ -105,25 +98,20 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
/** @test */
public function returnsEmptyCollectionWhenProvidingEmptyListOfTags(): void
{
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
$findTag = $tagRepo->findOneBy(Argument::type('array'))->willReturn(null);
$getRepo = $this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
$persist = $this->em->persist(Argument::type(Tag::class));
$this->em->expects($this->never())->method('getRepository')->with(Tag::class);
$this->em->expects($this->never())->method('persist');
$result = $this->resolver->resolveTags([]);
self::assertEmpty($result);
$findTag->shouldNotHaveBeenCalled();
$getRepo->shouldNotHaveBeenCalled();
$persist->shouldNotHaveBeenCalled();
}
/** @test */
public function newDomainsAreMemoizedUntilStateIsCleared(): void
{
$repo = $this->prophesize(DomainRepositoryInterface::class);
$repo->findOneBy(Argument::type('array'))->willReturn(null);
$this->em->getRepository(Domain::class)->willReturn($repo->reveal());
$repo = $this->createMock(DomainRepositoryInterface::class);
$repo->expects($this->exactly(3))->method('findOneBy')->with($this->isType('array'))->willReturn(null);
$this->em->method('getRepository')->with(Domain::class)->willReturn($repo);
$authority = 'foo.com';
$domain1 = $this->resolver->resolveDomain($authority);
@ -140,11 +128,9 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
/** @test */
public function newTagsAreMemoizedUntilStateIsCleared(): void
{
$tagRepo = $this->prophesize(TagRepositoryInterface::class);
$tagRepo->findOneBy(Argument::type('array'))->willReturn(null);
$this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
$this->em->persist(Argument::type(Tag::class))->will(function (): void {
});
$tagRepo = $this->createMock(TagRepositoryInterface::class);
$tagRepo->expects($this->exactly(6))->method('findOneBy')->with($this->isType('array'))->willReturn(null);
$this->em->method('getRepository')->with(Tag::class)->willReturn($tagRepo);
$tags = ['foo', 'bar'];
[$foo1, $bar1] = $this->resolver->resolveTags($tags);

View file

@ -7,9 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
use Cake\Chronos\Chronos;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
@ -27,15 +26,16 @@ use function range;
class ShortUrlResolverTest extends TestCase
{
use ApiKeyHelpersTrait;
use ProphecyTrait;
private ShortUrlResolver $urlResolver;
private ObjectProphecy $em;
private MockObject $em;
private MockObject $repo;
protected function setUp(): void
{
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->urlResolver = new ShortUrlResolver($this->em->reveal());
$this->em = $this->createMock(EntityManagerInterface::class);
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
$this->urlResolver = new ShortUrlResolver($this->em);
}
/**
@ -48,15 +48,14 @@ class ShortUrlResolverTest extends TestCase
$shortCode = $shortUrl->getShortCode();
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
$findOne = $repo->findOne($identifier, $apiKey?->spec())->willReturn($shortUrl);
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$this->repo->expects($this->once())->method('findOne')->with($identifier, $apiKey?->spec())->willReturn(
$shortUrl,
);
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
$result = $this->urlResolver->resolveShortUrl($identifier, $apiKey);
self::assertSame($shortUrl, $result);
$findOne->shouldHaveBeenCalledOnce();
$getRepo->shouldHaveBeenCalledOnce();
}
/**
@ -68,13 +67,10 @@ class ShortUrlResolverTest extends TestCase
$shortCode = 'abc123';
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
$findOne = $repo->findOne($identifier, $apiKey?->spec())->willReturn(null);
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal(), $apiKey);
$this->repo->expects($this->once())->method('findOne')->with($identifier, $apiKey?->spec())->willReturn(null);
$this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
$this->expectException(ShortUrlNotFoundException::class);
$findOne->shouldBeCalledOnce();
$getRepo->shouldBeCalledOnce();
$this->urlResolver->resolveShortUrl($identifier, $apiKey);
}
@ -85,17 +81,14 @@ class ShortUrlResolverTest extends TestCase
$shortUrl = ShortUrl::withLongUrl('expected_url');
$shortCode = $shortUrl->getShortCode();
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
$findOneByShortCode = $repo->findOneWithDomainFallback(
$this->repo->expects($this->once())->method('findOneWithDomainFallback')->with(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
)->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));
self::assertSame($shortUrl, $result);
$findOneByShortCode->shouldHaveBeenCalledOnce();
$getRepo->shouldHaveBeenCalledOnce();
}
/**
@ -106,15 +99,12 @@ class ShortUrlResolverTest extends TestCase
{
$shortCode = $shortUrl->getShortCode();
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
$findOneByShortCode = $repo->findOneWithDomainFallback(
$this->repo->expects($this->once())->method('findOneWithDomainFallback')->with(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
)->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);
$findOneByShortCode->shouldBeCalledOnce();
$getRepo->shouldBeCalledOnce();
$this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
}

View file

@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelperInterface;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
@ -27,26 +25,25 @@ use function count;
class ShortUrlServiceTest extends TestCase
{
use ApiKeyHelpersTrait;
use ProphecyTrait;
private ShortUrlService $service;
private ObjectProphecy $em;
private ObjectProphecy $urlResolver;
private ObjectProphecy $titleResolutionHelper;
private MockObject $em;
private MockObject $urlResolver;
private MockObject $titleResolutionHelper;
protected function setUp(): void
{
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->em->persist(Argument::any())->willReturn(null);
$this->em->flush()->willReturn(null);
$this->em = $this->createMock(EntityManagerInterface::class);
$this->em->method('persist')->willReturn(null);
$this->em->method('flush')->willReturn(null);
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
$this->titleResolutionHelper = $this->prophesize(ShortUrlTitleResolutionHelperInterface::class);
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
$this->titleResolutionHelper = $this->createMock(ShortUrlTitleResolutionHelperInterface::class);
$this->service = new ShortUrlService(
$this->em->reveal(),
$this->urlResolver->reveal(),
$this->titleResolutionHelper->reveal(),
$this->em,
$this->urlResolver,
$this->titleResolutionHelper,
new SimpleShortUrlRelationResolver(),
);
}
@ -64,10 +61,10 @@ class ShortUrlServiceTest extends TestCase
ShortUrl::createEmpty(),
];
$repo = $this->prophesize(ShortUrlRepository::class);
$repo->findList(Argument::cetera())->willReturn($list)->shouldBeCalledOnce();
$repo->countList(Argument::cetera())->willReturn(count($list))->shouldBeCalledOnce();
$this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$repo = $this->createMock(ShortUrlRepository::class);
$repo->expects($this->once())->method('findList')->willReturn($list);
$repo->expects($this->once())->method('countList')->willReturn(count($list));
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($repo);
$paginator = $this->service->listShortUrls(ShortUrlsParams::emptyInstance(), $apiKey);
@ -87,15 +84,15 @@ class ShortUrlServiceTest extends TestCase
$originalLongUrl = 'originalLongUrl';
$shortUrl = ShortUrl::withLongUrl($originalLongUrl);
$findShortUrl = $this->urlResolver->resolveShortUrl(
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
$apiKey,
)->willReturn($shortUrl);
$flush = $this->em->flush()->willReturn(null);
$processTitle = $this->titleResolutionHelper->processTitleAndValidateUrl($shortUrlEdit)->willReturn(
$shortUrlEdit,
);
$this->titleResolutionHelper->expects($this->exactly($expectedValidateCalls))
->method('processTitleAndValidateUrl')
->with($shortUrlEdit)
->willReturn($shortUrlEdit);
$result = $this->service->updateShortUrl(
ShortUrlIdentifier::fromShortCodeAndDomain('abc123'),
@ -108,9 +105,6 @@ class ShortUrlServiceTest extends TestCase
self::assertEquals($shortUrlEdit->validUntil(), $shortUrl->getValidUntil());
self::assertEquals($shortUrlEdit->maxVisits(), $shortUrl->getMaxVisits());
self::assertEquals($shortUrlEdit->longUrl() ?? $originalLongUrl, $shortUrl->getLongUrl());
$findShortUrl->shouldHaveBeenCalled();
$flush->shouldHaveBeenCalled();
$processTitle->shouldHaveBeenCalledTimes($expectedValidateCalls);
}
public function provideShortUrlEdits(): iterable

View file

@ -5,11 +5,9 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ShortUrl;
use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\EventDispatcher\EventDispatcherInterface;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -22,42 +20,29 @@ use Shlinkio\Shlink\Core\ShortUrl\UrlShortener;
class UrlShortenerTest extends TestCase
{
use ProphecyTrait;
private UrlShortener $urlShortener;
private ObjectProphecy $em;
private ObjectProphecy $titleResolutionHelper;
private ObjectProphecy $shortCodeHelper;
private MockObject $em;
private MockObject $titleResolutionHelper;
private MockObject $shortCodeHelper;
protected function setUp(): void
{
$this->titleResolutionHelper = $this->prophesize(ShortUrlTitleResolutionHelperInterface::class);
$this->titleResolutionHelper->processTitleAndValidateUrl(Argument::cetera())->willReturnArgument();
$this->titleResolutionHelper = $this->createMock(ShortUrlTitleResolutionHelperInterface::class);
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->em->persist(Argument::any())->will(function ($arguments): void {
/** @var ShortUrl $shortUrl */
[$shortUrl] = $arguments;
$shortUrl->setId('10');
});
$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);
// FIXME Should use the interface, but it doe snot define wrapInTransaction explicitly
$this->em = $this->createMock(EntityManager::class);
$this->em->method('persist')->willReturnCallback(fn (ShortUrl $shortUrl) => $shortUrl->setId('10'));
$this->em->method('wrapInTransaction')->with($this->isType('callable'))->willReturnCallback(
fn (callable $callback) => $callback(),
);
$this->urlShortener = new UrlShortener(
$this->titleResolutionHelper->reveal(),
$this->em->reveal(),
$this->titleResolutionHelper,
$this->em,
new SimpleShortUrlRelationResolver(),
$this->shortCodeHelper->reveal(),
$this->prophesize(EventDispatcherInterface::class)->reveal(),
$this->shortCodeHelper,
$this->createMock(EventDispatcherInterface::class),
);
}
@ -66,23 +51,31 @@ class UrlShortenerTest extends TestCase
{
$longUrl = 'http://foobar.com/12345/hello?foo=bar';
$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);
self::assertEquals($longUrl, $shortUrl->getLongUrl());
$this->titleResolutionHelper->processTitleAndValidateUrl($meta)->shouldHaveBeenCalledOnce();
}
/** @test */
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->urlShortener->shorten(ShortUrlCreation::fromRawData(
['customSlug' => 'custom-slug', 'longUrl' => 'http://foobar.com/12345/hello?foo=bar'],
));
$this->urlShortener->shorten($meta);
}
/**
@ -91,16 +84,14 @@ class UrlShortenerTest extends TestCase
*/
public function existingShortUrlIsReturnedWhenRequested(ShortUrlCreation $meta, ShortUrl $expected): void
{
$repo = $this->prophesize(ShortUrlRepository::class);
$findExisting = $repo->findOneMatching(Argument::cetera())->willReturn($expected);
$getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$repo = $this->createMock(ShortUrlRepository::class);
$repo->expects($this->once())->method('findOneMatching')->willReturn($expected);
$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);
$findExisting->shouldHaveBeenCalledOnce();
$getRepo->shouldHaveBeenCalledOnce();
$this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled();
$this->titleResolutionHelper->processTitleAndValidateUrl(Argument::cetera())->shouldNotHaveBeenCalled();
self::assertSame($expected, $result);
}