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

Feature/phpunit mocks
This commit is contained in:
Alejandro Celaya 2022-10-22 15:14:57 +02:00 committed by GitHub
commit d58f89aa26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 537 additions and 635 deletions

View file

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
@ -14,21 +13,17 @@ use Symfony\Component\Console\Tester\CommandTester;
trait CliTestUtilsTrait
{
use ProphecyTrait;
/**
* @return ObjectProphecy|Command
* @return MockObject & Command
*/
private function createCommandMock(string $name): ObjectProphecy
private function createCommandMock(string $name): MockObject
{
$command = $this->prophesize(Command::class);
$command->getName()->willReturn($name);
$command->getDefinition()->willReturn($name);
$command->isEnabled()->willReturn(true);
$command->getAliases()->willReturn([]);
$command->getDefinition()->willReturn(new InputDefinition());
$command->setApplication(Argument::type(Application::class))->willReturn(function (): void {
});
$command = $this->createMock(Command::class);
$command->method('getName')->willReturn($name);
$command->method('isEnabled')->willReturn(true);
$command->method('getAliases')->willReturn([]);
$command->method('getDefinition')->willReturn(new InputDefinition());
$command->method('setApplication')->with(Assert::isInstanceOf(Application::class));
return $command;
}

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Api\DisableKeyCommand;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
@ -17,19 +17,19 @@ class DisableKeyCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
private MockObject $apiKeyService;
protected function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DisableKeyCommand($this->apiKeyService->reveal()));
$this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DisableKeyCommand($this->apiKeyService));
}
/** @test */
public function providedApiKeyIsDisabled(): void
{
$apiKey = 'abcd1234';
$this->apiKeyService->disable($apiKey)->shouldBeCalledOnce();
$this->apiKeyService->expects($this->once())->method('disable')->with($this->equalTo($apiKey));
$this->commandTester->execute([
'apiKey' => $apiKey,
@ -44,7 +44,9 @@ class DisableKeyCommandTest extends TestCase
{
$apiKey = 'abcd1234';
$expectedMessage = 'API key "abcd1234" does not exist.';
$disable = $this->apiKeyService->disable($apiKey)->willThrow(new InvalidArgumentException($expectedMessage));
$this->apiKeyService->expects($this->once())->method('disable')->with(
$this->equalTo($apiKey),
)->willThrowException(new InvalidArgumentException($expectedMessage));
$this->commandTester->execute([
'apiKey' => $apiKey,
@ -52,6 +54,5 @@ class DisableKeyCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
self::assertStringContainsString($expectedMessage, $output);
$disable->shouldHaveBeenCalledOnce();
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;
use Cake\Chronos\Chronos;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\ApiKey\RoleResolverInterface;
use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
@ -21,22 +20,25 @@ class GenerateKeyCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
private MockObject $apiKeyService;
protected function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$roleResolver = $this->prophesize(RoleResolverInterface::class);
$roleResolver->determineRoles(Argument::type(InputInterface::class))->willReturn([]);
$this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class);
$roleResolver = $this->createMock(RoleResolverInterface::class);
$roleResolver->method('determineRoles')->with($this->isInstanceOf(InputInterface::class))->willReturn([]);
$command = new GenerateKeyCommand($this->apiKeyService->reveal(), $roleResolver->reveal());
$command = new GenerateKeyCommand($this->apiKeyService, $roleResolver);
$this->commandTester = $this->testerForCommand($command);
}
/** @test */
public function noExpirationDateIsDefinedIfNotProvided(): void
{
$this->apiKeyService->create(null, null)->shouldBeCalledOnce()->willReturn(ApiKey::create());
$this->apiKeyService->expects($this->once())->method('create')->with(
$this->isNull(),
$this->isNull(),
)->willReturn(ApiKey::create());
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
@ -47,9 +49,10 @@ class GenerateKeyCommandTest extends TestCase
/** @test */
public function expirationDateIsDefinedIfProvided(): void
{
$this->apiKeyService->create(Argument::type(Chronos::class), null)->shouldBeCalledOnce()->willReturn(
ApiKey::create(),
);
$this->apiKeyService->expects($this->once())->method('create')->with(
$this->isInstanceOf(Chronos::class),
$this->isNull(),
)->willReturn(ApiKey::create());
$this->commandTester->execute([
'--expiration-date' => '2016-01-01',
@ -59,9 +62,10 @@ class GenerateKeyCommandTest extends TestCase
/** @test */
public function nameIsDefinedIfProvided(): void
{
$this->apiKeyService->create(null, Argument::type('string'))->shouldBeCalledOnce()->willReturn(
ApiKey::create(),
);
$this->apiKeyService->expects($this->once())->method('create')->with(
$this->isNull(),
$this->isType('string'),
)->willReturn(ApiKey::create());
$this->commandTester->execute([
'--name' => 'Alice',

View file

@ -5,8 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;
use Cake\Chronos\Chronos;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
@ -21,12 +21,12 @@ class ListKeysCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $apiKeyService;
private MockObject $apiKeyService;
protected function setUp(): void
{
$this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListKeysCommand($this->apiKeyService->reveal()));
$this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListKeysCommand($this->apiKeyService));
}
/**
@ -35,13 +35,14 @@ class ListKeysCommandTest extends TestCase
*/
public function returnsExpectedOutput(array $keys, bool $enabledOnly, string $expected): void
{
$listKeys = $this->apiKeyService->listKeys($enabledOnly)->willReturn($keys);
$this->apiKeyService->expects($this->once())->method('listKeys')->with(
$this->equalTo($enabledOnly),
)->willReturn($keys);
$this->commandTester->execute(['--enabled-only' => $enabledOnly]);
$output = $this->commandTester->getDisplay();
self::assertEquals($expected, $output);
$listKeys->shouldHaveBeenCalledOnce();
}
public function provideKeysAndOutputs(): iterable

View file

@ -9,9 +9,8 @@ use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Db\CreateDatabaseCommand;
use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
@ -28,40 +27,37 @@ class CreateDatabaseCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $processHelper;
private ObjectProphecy $regularConn;
private ObjectProphecy $schemaManager;
private ObjectProphecy $driver;
private MockObject $processHelper;
private MockObject $regularConn;
private MockObject $schemaManager;
private MockObject $driver;
protected function setUp(): void
{
$locker = $this->prophesize(LockFactory::class);
$lock = $this->prophesize(LockInterface::class);
$lock->acquire(Argument::any())->willReturn(true);
$lock->release()->will(function (): void {
});
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
$locker = $this->createMock(LockFactory::class);
$lock = $this->createMock(LockInterface::class);
$lock->method('acquire')->withAnyParameters()->willReturn(true);
$locker->method('createLock')->withAnyParameters()->willReturn($lock);
$phpExecutableFinder = $this->prophesize(PhpExecutableFinder::class);
$phpExecutableFinder->find(false)->willReturn('/usr/local/bin/php');
$phpExecutableFinder = $this->createMock(PhpExecutableFinder::class);
$phpExecutableFinder->method('find')->with($this->isFalse())->willReturn('/usr/local/bin/php');
$this->processHelper = $this->prophesize(ProcessRunnerInterface::class);
$this->schemaManager = $this->prophesize(AbstractSchemaManager::class);
$this->processHelper = $this->createMock(ProcessRunnerInterface::class);
$this->schemaManager = $this->createMock(AbstractSchemaManager::class);
$this->regularConn = $this->prophesize(Connection::class);
$this->regularConn->createSchemaManager()->willReturn($this->schemaManager->reveal());
$this->driver = $this->prophesize(Driver::class);
$this->regularConn->getDriver()->willReturn($this->driver->reveal());
$this->driver->getDatabasePlatform()->willReturn($this->prophesize(AbstractPlatform::class)->reveal());
$noDbNameConn = $this->prophesize(Connection::class);
$noDbNameConn->createSchemaManager()->willReturn($this->schemaManager->reveal());
$this->regularConn = $this->createMock(Connection::class);
$this->regularConn->method('createSchemaManager')->willReturn($this->schemaManager);
$this->driver = $this->createMock(Driver::class);
$this->regularConn->method('getDriver')->willReturn($this->driver);
$noDbNameConn = $this->createMock(Connection::class);
$noDbNameConn->method('createSchemaManager')->withAnyParameters()->willReturn($this->schemaManager);
$command = new CreateDatabaseCommand(
$locker->reveal(),
$this->processHelper->reveal(),
$phpExecutableFinder->reveal(),
$this->regularConn->reveal(),
$noDbNameConn->reveal(),
$locker,
$this->processHelper,
$phpExecutableFinder,
$this->regularConn,
$noDbNameConn,
);
$this->commandTester = $this->testerForCommand($command);
@ -71,38 +67,33 @@ class CreateDatabaseCommandTest extends TestCase
public function successMessageIsPrintedIfDatabaseAlreadyExists(): void
{
$shlinkDatabase = 'shlink_database';
$getDatabase = $this->regularConn->getParams()->willReturn(['dbname' => $shlinkDatabase]);
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
});
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
$this->regularConn->expects($this->once())->method('getParams')->willReturn(['dbname' => $shlinkDatabase]);
$this->schemaManager->expects($this->once())->method('listDatabases')->willReturn(
['foo', $shlinkDatabase, 'bar'],
);
$this->schemaManager->expects($this->never())->method('createDatabase');
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn(['foo_table', 'bar_table']);
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Database already exists. Run "db:migrate" command', $output);
$getDatabase->shouldHaveBeenCalledOnce();
$listDatabases->shouldHaveBeenCalledOnce();
$createDatabase->shouldNotHaveBeenCalled();
$listTables->shouldHaveBeenCalledOnce();
}
/** @test */
public function databaseIsCreatedIfItDoesNotExist(): void
{
$shlinkDatabase = 'shlink_database';
$getDatabase = $this->regularConn->getParams()->willReturn(['dbname' => $shlinkDatabase]);
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
});
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table', MIGRATIONS_TABLE]);
$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('listTableNames')->willReturn(
['foo_table', 'bar_table', MIGRATIONS_TABLE],
);
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
$this->commandTester->execute([]);
$getDatabase->shouldHaveBeenCalledOnce();
$listDatabases->shouldHaveBeenCalledOnce();
$createDatabase->shouldHaveBeenCalledOnce();
$listTables->shouldHaveBeenCalledOnce();
}
/**
@ -112,28 +103,28 @@ class CreateDatabaseCommandTest extends TestCase
public function tablesAreCreatedIfDatabaseIsEmpty(array $tables): void
{
$shlinkDatabase = 'shlink_database';
$getDatabase = $this->regularConn->getParams()->willReturn(['dbname' => $shlinkDatabase]);
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', $shlinkDatabase, 'bar']);
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
});
$listTables = $this->schemaManager->listTableNames()->willReturn($tables);
$runCommand = $this->processHelper->run(Argument::type(OutputInterface::class), [
'/usr/local/bin/php',
CreateDatabaseCommand::DOCTRINE_SCRIPT,
CreateDatabaseCommand::DOCTRINE_CREATE_SCHEMA_COMMAND,
'--no-interaction',
]);
$this->regularConn->expects($this->once())->method('getParams')->willReturn(['dbname' => $shlinkDatabase]);
$this->schemaManager->expects($this->once())->method('listDatabases')->willReturn(
['foo', $shlinkDatabase, 'bar'],
);
$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->driver->method('getDatabasePlatform')->willReturn($this->createMock(AbstractPlatform::class));
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Creating database tables...', $output);
self::assertStringContainsString('Database properly created!', $output);
$getDatabase->shouldHaveBeenCalledOnce();
$listDatabases->shouldHaveBeenCalledOnce();
$createDatabase->shouldNotHaveBeenCalled();
$listTables->shouldHaveBeenCalledOnce();
$runCommand->shouldHaveBeenCalledOnce();
}
public function provideEmptyDatabase(): iterable
@ -145,20 +136,13 @@ class CreateDatabaseCommandTest extends TestCase
/** @test */
public function databaseCheckIsSkippedForSqlite(): void
{
$this->driver->getDatabasePlatform()->willReturn($this->prophesize(SqlitePlatform::class)->reveal());
$this->driver->method('getDatabasePlatform')->willReturn($this->createMock(SqlitePlatform::class));
$shlinkDatabase = 'shlink_database';
$getDatabase = $this->regularConn->getParams()->willReturn(['dbname' => $shlinkDatabase]);
$listDatabases = $this->schemaManager->listDatabases()->willReturn(['foo', 'bar']);
$createDatabase = $this->schemaManager->createDatabase($shlinkDatabase)->will(function (): void {
});
$listTables = $this->schemaManager->listTableNames()->willReturn(['foo_table', 'bar_table']);
$this->regularConn->expects($this->never())->method('getParams');
$this->schemaManager->expects($this->never())->method('listDatabases');
$this->schemaManager->expects($this->never())->method('createDatabase');
$this->schemaManager->expects($this->once())->method('listTableNames')->willReturn(['foo_table', 'bar_table']);
$this->commandTester->execute([]);
$getDatabase->shouldNotHaveBeenCalled();
$listDatabases->shouldNotHaveBeenCalled();
$createDatabase->shouldNotHaveBeenCalled();
$listTables->shouldHaveBeenCalledOnce();
}
}

View file

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Db;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Db\MigrateDatabaseCommand;
use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
@ -21,45 +20,41 @@ class MigrateDatabaseCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $processHelper;
private MockObject $processHelper;
protected function setUp(): void
{
$locker = $this->prophesize(LockFactory::class);
$lock = $this->prophesize(LockInterface::class);
$lock->acquire(Argument::any())->willReturn(true);
$lock->release()->will(function (): void {
});
$locker->createLock(Argument::cetera())->willReturn($lock->reveal());
$locker = $this->createMock(LockFactory::class);
$lock = $this->createMock(LockInterface::class);
$lock->method('acquire')->withAnyParameters()->willReturn(true);
$locker->method('createLock')->withAnyParameters()->willReturn($lock);
$phpExecutableFinder = $this->prophesize(PhpExecutableFinder::class);
$phpExecutableFinder->find(false)->willReturn('/usr/local/bin/php');
$phpExecutableFinder = $this->createMock(PhpExecutableFinder::class);
$phpExecutableFinder->method('find')->with($this->isFalse())->willReturn('/usr/local/bin/php');
$this->processHelper = $this->prophesize(ProcessRunnerInterface::class);
$this->processHelper = $this->createMock(ProcessRunnerInterface::class);
$command = new MigrateDatabaseCommand(
$locker->reveal(),
$this->processHelper->reveal(),
$phpExecutableFinder->reveal(),
);
$command = new MigrateDatabaseCommand($locker, $this->processHelper, $phpExecutableFinder);
$this->commandTester = $this->testerForCommand($command);
}
/** @test */
public function migrationsCommandIsRunWithProperVerbosity(): void
{
$runCommand = $this->processHelper->run(Argument::type(OutputInterface::class), [
'/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),
$this->equalTo([
'/usr/local/bin/php',
MigrateDatabaseCommand::DOCTRINE_MIGRATIONS_SCRIPT,
MigrateDatabaseCommand::DOCTRINE_MIGRATE_COMMAND,
'--no-interaction',
]),
);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Migrating database...', $output);
self::assertStringContainsString('Database properly migrated!', $output);
$runCommand->shouldHaveBeenCalledOnce();
}
}

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Domain;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Domain\DomainRedirectsCommand;
use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
@ -22,12 +22,12 @@ class DomainRedirectsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $domainService;
private MockObject $domainService;
protected function setUp(): void
{
$this->domainService = $this->prophesize(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DomainRedirectsCommand($this->domainService->reveal()));
$this->domainService = $this->createMock(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DomainRedirectsCommand($this->domainService));
}
/**
@ -37,11 +37,14 @@ class DomainRedirectsCommandTest extends TestCase
public function onlyPlainQuestionsAreAskedForNewDomainsAndDomainsWithNoRedirects(?Domain $domain): void
{
$domainAuthority = 'my-domain.com';
$findDomain = $this->domainService->findByAuthority($domainAuthority)->willReturn($domain);
$configureRedirects = $this->domainService->configureNotFoundRedirects(
$domainAuthority,
NotFoundRedirects::withRedirects('foo.com', null, 'baz.com'),
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withRedirects('foo.com', null, 'baz.com')),
)->willReturn(Domain::withAuthority(''));
$this->domainService->expects($this->never())->method('listDomains');
$this->commandTester->setInputs(['foo.com', '', 'baz.com']);
$this->commandTester->execute(['domain' => $domainAuthority]);
@ -55,9 +58,6 @@ class DomainRedirectsCommandTest extends TestCase
);
self::assertStringContainsString('URL to redirect to when a user hits an invalid short URL', $output);
self::assertEquals(3, substr_count($output, '(Leave empty for no redirect)'));
$findDomain->shouldHaveBeenCalledOnce();
$configureRedirects->shouldHaveBeenCalledOnce();
$this->domainService->listDomains()->shouldNotHaveBeenCalled();
}
public function provideDomains(): iterable
@ -73,11 +73,14 @@ class DomainRedirectsCommandTest extends TestCase
$domain = Domain::withAuthority($domainAuthority);
$domain->configureNotFoundRedirects(NotFoundRedirects::withRedirects('foo.com', 'bar.com', 'baz.com'));
$findDomain = $this->domainService->findByAuthority($domainAuthority)->willReturn($domain);
$configureRedirects = $this->domainService->configureNotFoundRedirects(
$domainAuthority,
NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com'),
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withRedirects(null, 'edited.com', 'baz.com')),
)->willReturn($domain);
$this->domainService->expects($this->never())->method('listDomains');
$this->commandTester->setInputs(['2', '1', 'edited.com', '0']);
$this->commandTester->execute(['domain' => $domainAuthority]);
@ -90,9 +93,6 @@ class DomainRedirectsCommandTest extends TestCase
self::assertStringNotContainsStringIgnoringCase('(Leave empty for no redirect)', $output);
self::assertEquals(3, substr_count($output, 'Set new redirect URL'));
self::assertEquals(3, substr_count($output, 'Remove redirect'));
$findDomain->shouldHaveBeenCalledOnce();
$configureRedirects->shouldHaveBeenCalledOnce();
$this->domainService->listDomains()->shouldNotHaveBeenCalled();
}
/** @test */
@ -101,11 +101,13 @@ class DomainRedirectsCommandTest extends TestCase
$domainAuthority = 'example.com';
$domain = Domain::withAuthority($domainAuthority);
$listDomains = $this->domainService->listDomains()->willReturn([]);
$findDomain = $this->domainService->findByAuthority($domainAuthority)->willReturn($domain);
$configureRedirects = $this->domainService->configureNotFoundRedirects(
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
$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('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
)->willReturn($domain);
$this->commandTester->setInputs([$domainAuthority, '', '', '']);
@ -113,9 +115,6 @@ class DomainRedirectsCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Domain authority for which you want to set specific redirects', $output);
$listDomains->shouldHaveBeenCalledOnce();
$findDomain->shouldHaveBeenCalledOnce();
$configureRedirects->shouldHaveBeenCalledOnce();
}
/** @test */
@ -124,15 +123,17 @@ class DomainRedirectsCommandTest extends TestCase
$domainAuthority = 'existing-two.com';
$domain = Domain::withAuthority($domainAuthority);
$listDomains = $this->domainService->listDomains()->willReturn([
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([
DomainItem::forDefaultDomain('default-domain.com', new NotFoundRedirectOptions()),
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
DomainItem::forNonDefaultDomain(Domain::withAuthority($domainAuthority)),
]);
$findDomain = $this->domainService->findByAuthority($domainAuthority)->willReturn($domain);
$configureRedirects = $this->domainService->configureNotFoundRedirects(
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
)->willReturn($domain);
$this->commandTester->setInputs(['1', '', '', '']);
@ -143,9 +144,6 @@ class DomainRedirectsCommandTest extends TestCase
self::assertStringNotContainsString('default-domain.com', $output);
self::assertStringContainsString('existing-one.com', $output);
self::assertStringContainsString($domainAuthority, $output);
$listDomains->shouldHaveBeenCalledOnce();
$findDomain->shouldHaveBeenCalledOnce();
$configureRedirects->shouldHaveBeenCalledOnce();
}
/** @test */
@ -154,15 +152,17 @@ class DomainRedirectsCommandTest extends TestCase
$domainAuthority = 'new-domain.com';
$domain = Domain::withAuthority($domainAuthority);
$listDomains = $this->domainService->listDomains()->willReturn([
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([
DomainItem::forDefaultDomain('default-domain.com', new NotFoundRedirectOptions()),
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-one.com')),
DomainItem::forNonDefaultDomain(Domain::withAuthority('existing-two.com')),
]);
$findDomain = $this->domainService->findByAuthority($domainAuthority)->willReturn($domain);
$configureRedirects = $this->domainService->configureNotFoundRedirects(
$domainAuthority,
NotFoundRedirects::withoutRedirects(),
$this->domainService->expects($this->once())->method('findByAuthority')->with(
$this->equalTo($domainAuthority),
)->willReturn($domain);
$this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with(
$this->equalTo($domainAuthority),
$this->equalTo(NotFoundRedirects::withoutRedirects()),
)->willReturn($domain);
$this->commandTester->setInputs(['2', $domainAuthority, '', '', '']);
@ -173,8 +173,5 @@ class DomainRedirectsCommandTest extends TestCase
self::assertStringNotContainsString('default-domain.com', $output);
self::assertStringContainsString('existing-one.com', $output);
self::assertStringContainsString('existing-two.com', $output);
$listDomains->shouldHaveBeenCalledOnce();
$findDomain->shouldHaveBeenCalledOnce();
$configureRedirects->shouldHaveBeenCalledOnce();
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Domain;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Domain\GetDomainVisitsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -25,16 +24,16 @@ class GetDomainVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitsHelper;
private ObjectProphecy $stringifier;
private MockObject $visitsHelper;
private MockObject $stringifier;
protected function setUp(): void
{
$this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class);
$this->stringifier = $this->prophesize(ShortUrlStringifierInterface::class);
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
new GetDomainVisitsCommand($this->visitsHelper->reveal(), $this->stringifier->reveal()),
new GetDomainVisitsCommand($this->visitsHelper, $this->stringifier),
);
}
@ -46,10 +45,13 @@ class GetDomainVisitsCommandTest extends TestCase
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$domain = 'doma.in';
$getVisits = $this->visitsHelper->visitsForDomain($domain, Argument::any())->willReturn(
new Paginator(new ArrayAdapter([$visit])),
$this->visitsHelper->expects($this->once())->method('visitsForDomain')->with(
$this->equalTo($domain),
$this->anything(),
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
'the_short_url',
);
$stringify = $this->stringifier->stringify($shortUrl)->willReturn('the_short_url');
$this->commandTester->execute(['domain' => $domain]);
$output = $this->commandTester->getDisplay();
@ -65,7 +67,5 @@ class GetDomainVisitsCommandTest extends TestCase
OUTPUT,
$output,
);
$getVisits->shouldHaveBeenCalledOnce();
$stringify->shouldHaveBeenCalledOnce();
}
}

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Domain;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Domain\ListDomainsCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Config\NotFoundRedirects;
@ -21,12 +21,12 @@ class ListDomainsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $domainService;
private MockObject $domainService;
protected function setUp(): void
{
$this->domainService = $this->prophesize(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListDomainsCommand($this->domainService->reveal()));
$this->domainService = $this->createMock(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListDomainsCommand($this->domainService));
}
/**
@ -42,7 +42,7 @@ class ListDomainsCommandTest extends TestCase
'https://foo.com/baz-domain/invalid',
));
$listDomains = $this->domainService->listDomains()->willReturn([
$this->domainService->expects($this->once())->method('listDomains')->with()->willReturn([
DomainItem::forDefaultDomain('foo.com', new NotFoundRedirectOptions(
invalidShortUrl: 'https://foo.com/default/invalid',
baseUrl: 'https://foo.com/default/base',
@ -55,7 +55,6 @@ class ListDomainsCommandTest extends TestCase
self::assertEquals($expectedOutput, $this->commandTester->getDisplay());
self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
$listDomains->shouldHaveBeenCalledOnce();
}
public function provideInputsAndOutputs(): iterable

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\ShortUrl\CreateShortUrlCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
@ -27,18 +26,17 @@ class CreateShortUrlCommandTest extends TestCase
private const DEFAULT_DOMAIN = 'default.com';
private CommandTester $commandTester;
private ObjectProphecy $urlShortener;
private ObjectProphecy $stringifier;
private MockObject $urlShortener;
private MockObject $stringifier;
protected function setUp(): void
{
$this->urlShortener = $this->prophesize(UrlShortener::class);
$this->stringifier = $this->prophesize(ShortUrlStringifierInterface::class);
$this->stringifier->stringify(Argument::type(ShortUrl::class))->willReturn('');
$this->urlShortener = $this->createMock(UrlShortener::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$command = new CreateShortUrlCommand(
$this->urlShortener->reveal(),
$this->stringifier->reveal(),
$this->urlShortener,
$this->stringifier,
new UrlShortenerOptions(domain: ['hostname' => self::DEFAULT_DOMAIN], defaultShortCodesLength: 5),
);
$this->commandTester = $this->testerForCommand($command);
@ -48,8 +46,10 @@ class CreateShortUrlCommandTest extends TestCase
public function properShortCodeIsCreatedIfLongUrlIsCorrect(): void
{
$shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten(Argument::cetera())->willReturn($shortUrl);
$stringify = $this->stringifier->stringify($shortUrl)->willReturn('stringified_short_url');
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willReturn($shortUrl);
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
'stringified_short_url',
);
$this->commandTester->execute([
'longUrl' => 'http://domain.com/foo/bar',
@ -59,16 +59,16 @@ class CreateShortUrlCommandTest extends TestCase
self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
self::assertStringContainsString('stringified_short_url', $output);
$urlToShortCode->shouldHaveBeenCalledOnce();
$stringify->shouldHaveBeenCalledOnce();
}
/** @test */
public function exceptionWhileParsingLongUrlOutputsError(): void
{
$url = 'http://domain.com/invalid';
$this->urlShortener->shorten(Argument::cetera())->willThrow(InvalidUrlException::fromUrl($url))
->shouldBeCalledOnce();
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willThrowException(
InvalidUrlException::fromUrl($url),
);
$this->stringifier->method('stringify')->with($this->isInstanceOf(ShortUrl::class))->willReturn('');
$this->commandTester->execute(['longUrl' => $url]);
$output = $this->commandTester->getDisplay();
@ -80,30 +80,32 @@ class CreateShortUrlCommandTest extends TestCase
/** @test */
public function providingNonUniqueSlugOutputsError(): void
{
$urlToShortCode = $this->urlShortener->shorten(Argument::cetera())->willThrow(
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willThrowException(
NonUniqueSlugException::fromSlug('my-slug'),
);
$this->stringifier->method('stringify')->with($this->isInstanceOf(ShortUrl::class))->willReturn('');
$this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--custom-slug' => 'my-slug']);
$output = $this->commandTester->getDisplay();
self::assertEquals(ExitCodes::EXIT_FAILURE, $this->commandTester->getStatusCode());
self::assertStringContainsString('Provided slug "my-slug" is already in use', $output);
$urlToShortCode->shouldHaveBeenCalledOnce();
}
/** @test */
public function properlyProcessesProvidedTags(): void
{
$shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten(
Argument::that(function (ShortUrlCreation $meta) {
$this->urlShortener->expects($this->once())->method('shorten')->with(
$this->callback(function (ShortUrlCreation $meta) {
$tags = $meta->getTags();
Assert::assertEquals(['foo', 'bar', 'baz', 'boo', 'zar'], $tags);
return true;
}),
)->willReturn($shortUrl);
$stringify = $this->stringifier->stringify($shortUrl)->willReturn('stringified_short_url');
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
'stringified_short_url',
);
$this->commandTester->execute([
'longUrl' => 'http://domain.com/foo/bar',
@ -113,8 +115,6 @@ class CreateShortUrlCommandTest extends TestCase
self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
self::assertStringContainsString('stringified_short_url', $output);
$urlToShortCode->shouldHaveBeenCalledOnce();
$stringify->shouldHaveBeenCalledOnce();
}
/**
@ -123,18 +123,18 @@ class CreateShortUrlCommandTest extends TestCase
*/
public function properlyProcessesProvidedDomain(array $input, ?string $expectedDomain): void
{
$shorten = $this->urlShortener->shorten(
Argument::that(function (ShortUrlCreation $meta) use ($expectedDomain) {
$this->urlShortener->expects($this->once())->method('shorten')->with(
$this->callback(function (ShortUrlCreation $meta) use ($expectedDomain) {
Assert::assertEquals($expectedDomain, $meta->getDomain());
return true;
}),
)->willReturn(ShortUrl::createEmpty());
$this->stringifier->method('stringify')->with($this->isInstanceOf(ShortUrl::class))->willReturn('');
$input['longUrl'] = 'http://domain.com/foo/bar';
$this->commandTester->execute($input);
self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
$shorten->shouldHaveBeenCalledOnce();
}
public function provideDomains(): iterable
@ -152,17 +152,16 @@ class CreateShortUrlCommandTest extends TestCase
public function urlValidationHasExpectedValueBasedOnProvidedFlags(array $options, ?bool $expectedValidateUrl): void
{
$shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten(
Argument::that(function (ShortUrlCreation $meta) use ($expectedValidateUrl) {
$this->urlShortener->expects($this->once())->method('shorten')->with(
$this->callback(function (ShortUrlCreation $meta) use ($expectedValidateUrl) {
Assert::assertEquals($expectedValidateUrl, $meta->doValidateUrl());
return $meta;
return true;
}),
)->willReturn($shortUrl);
$this->stringifier->method('stringify')->with($this->isInstanceOf(ShortUrl::class))->willReturn('');
$options['longUrl'] = 'http://domain.com/foo/bar';
$this->commandTester->execute($options);
$urlToShortCode->shouldHaveBeenCalledOnce();
}
public function provideFlags(): iterable

View file

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\ShortUrl\DeleteShortUrlCommand;
use Shlinkio\Shlink\Core\Exception;
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlServiceInterface;
@ -14,7 +13,6 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use Symfony\Component\Console\Tester\CommandTester;
use function array_pop;
use function sprintf;
use const PHP_EOL;
@ -24,23 +22,22 @@ class DeleteShortUrlCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $service;
private MockObject $service;
protected function setUp(): void
{
$this->service = $this->prophesize(DeleteShortUrlServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service->reveal()));
$this->service = $this->createMock(DeleteShortUrlServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service));
}
/** @test */
public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void
{
$shortCode = 'abc123';
$deleteByShortCode = $this->service->deleteByShortCode(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
false,
)->will(function (): void {
});
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->isFalse(),
);
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();
@ -49,7 +46,6 @@ class DeleteShortUrlCommandTest extends TestCase
sprintf('Short URL with short code "%s" successfully deleted.', $shortCode),
$output,
);
$deleteByShortCode->shouldHaveBeenCalledOnce();
}
/** @test */
@ -57,15 +53,15 @@ class DeleteShortUrlCommandTest extends TestCase
{
$shortCode = 'abc123';
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$deleteByShortCode = $this->service->deleteByShortCode($identifier, false)->willThrow(
Exception\ShortUrlNotFoundException::fromNotFound($identifier),
);
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo($identifier),
$this->isFalse(),
)->willThrowException(Exception\ShortUrlNotFoundException::fromNotFound($identifier));
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString(sprintf('No URL found with short code "%s"', $shortCode), $output);
$deleteByShortCode->shouldHaveBeenCalledOnce();
}
/**
@ -79,18 +75,17 @@ class DeleteShortUrlCommandTest extends TestCase
): void {
$shortCode = 'abc123';
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
$deleteByShortCode = $this->service->deleteByShortCode($identifier, Argument::type('bool'))->will(
function (array $args) use ($shortCode): void {
$ignoreThreshold = array_pop($args);
if (!$ignoreThreshold) {
throw Exception\DeleteShortUrlException::fromVisitsThreshold(
10,
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
);
}
},
);
$this->service->expects($this->exactly($expectedDeleteCalls))->method('deleteByShortCode')->with(
$this->equalTo($identifier),
$this->isType('bool'),
)->willReturnCallback(function ($_, bool $ignoreThreshold) use ($shortCode): void {
if (!$ignoreThreshold) {
throw Exception\DeleteShortUrlException::fromVisitsThreshold(
10,
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
);
}
});
$this->commandTester->setInputs($retryAnswer);
$this->commandTester->execute(['shortCode' => $shortCode]);
@ -101,7 +96,6 @@ class DeleteShortUrlCommandTest extends TestCase
$shortCode,
), $output);
self::assertStringContainsString($expectedMessage, $output);
$deleteByShortCode->shouldHaveBeenCalledTimes($expectedDeleteCalls);
}
public function provideRetryDeleteAnswers(): iterable
@ -115,10 +109,10 @@ class DeleteShortUrlCommandTest extends TestCase
public function deleteIsNotRetriedWhenThresholdIsReachedAndQuestionIsDeclined(): void
{
$shortCode = 'abc123';
$deleteByShortCode = $this->service->deleteByShortCode(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
false,
)->willThrow(Exception\DeleteShortUrlException::fromVisitsThreshold(
$this->service->expects($this->once())->method('deleteByShortCode')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->isFalse(),
)->willThrowException(Exception\DeleteShortUrlException::fromVisitsThreshold(
10,
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
));
@ -132,6 +126,5 @@ class DeleteShortUrlCommandTest extends TestCase
$shortCode,
), $output);
self::assertStringContainsString('Short URL was not deleted.', $output);
$deleteByShortCode->shouldHaveBeenCalledOnce();
}
}

View file

@ -6,9 +6,8 @@ namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use Cake\Chronos\Chronos;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\ShortUrl\GetShortUrlVisitsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Common\Util\DateRange;
@ -31,12 +30,12 @@ class GetShortUrlVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitsHelper;
private MockObject $visitsHelper;
protected function setUp(): void
{
$this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class);
$command = new GetShortUrlVisitsCommand($this->visitsHelper->reveal());
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$command = new GetShortUrlVisitsCommand($this->visitsHelper);
$this->commandTester = $this->testerForCommand($command);
}
@ -44,12 +43,10 @@ class GetShortUrlVisitsCommandTest extends TestCase
public function noDateFlagsTriesToListWithoutDateRange(): void
{
$shortCode = 'abc123';
$this->visitsHelper->visitsForShortUrl(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(DateRange::allTime()),
)
->willReturn(new Paginator(new ArrayAdapter([])))
->shouldBeCalledOnce();
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(DateRange::allTime())),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute(['shortCode' => $shortCode]);
}
@ -60,12 +57,10 @@ class GetShortUrlVisitsCommandTest extends TestCase
$shortCode = 'abc123';
$startDate = '2016-01-01';
$endDate = '2016-02-01';
$this->visitsHelper->visitsForShortUrl(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate))),
)
->willReturn(new Paginator(new ArrayAdapter([])))
->shouldBeCalledOnce();
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(buildDateRange(Chronos::parse($startDate), Chronos::parse($endDate)))),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute([
'shortCode' => $shortCode,
@ -79,9 +74,9 @@ class GetShortUrlVisitsCommandTest extends TestCase
{
$shortCode = 'abc123';
$startDate = 'foo';
$info = $this->visitsHelper->visitsForShortUrl(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
new VisitsParams(DateRange::allTime()),
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->equalTo(new VisitsParams(DateRange::allTime())),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->execute([
@ -90,7 +85,6 @@ class GetShortUrlVisitsCommandTest extends TestCase
]);
$output = $this->commandTester->getDisplay();
$info->shouldHaveBeenCalledOnce();
self::assertStringContainsString(
sprintf('Ignored provided "start-date" since its value "%s" is not a valid date', $startDate),
$output,
@ -104,12 +98,10 @@ class GetShortUrlVisitsCommandTest extends TestCase
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$shortCode = 'abc123';
$this->visitsHelper->visitsForShortUrl(
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode),
Argument::any(),
)->willReturn(
new Paginator(new ArrayAdapter([$visit])),
)->shouldBeCalledOnce();
$this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
$this->anything(),
)->willReturn(new Paginator(new ArrayAdapter([$visit])));
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();

View file

@ -6,9 +6,8 @@ namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use Cake\Chronos\Chronos;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\ShortUrl\ListShortUrlsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -31,12 +30,12 @@ class ListShortUrlsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $shortUrlService;
private MockObject $shortUrlService;
protected function setUp(): void
{
$this->shortUrlService = $this->prophesize(ShortUrlServiceInterface::class);
$command = new ListShortUrlsCommand($this->shortUrlService->reveal(), new ShortUrlDataTransformer(
$this->shortUrlService = $this->createMock(ShortUrlServiceInterface::class);
$command = new ListShortUrlsCommand($this->shortUrlService, new ShortUrlDataTransformer(
new ShortUrlStringifier([]),
));
$this->commandTester = $this->testerForCommand($command);
@ -51,9 +50,8 @@ class ListShortUrlsCommandTest extends TestCase
$data[] = ShortUrl::withLongUrl('url_' . $i);
}
$this->shortUrlService->listShortUrls(Argument::cetera())
->will(fn () => new Paginator(new ArrayAdapter($data)))
->shouldBeCalledTimes(3);
$this->shortUrlService->expects($this->exactly(3))->method('listShortUrls')->withAnyParameters()
->willReturnCallback(fn () => new Paginator(new ArrayAdapter($data)));
$this->commandTester->setInputs(['y', 'y', 'n']);
$this->commandTester->execute([]);
@ -74,9 +72,9 @@ class ListShortUrlsCommandTest extends TestCase
$data[] = ShortUrl::withLongUrl('url_' . $i);
}
$this->shortUrlService->listShortUrls(ShortUrlsParams::emptyInstance())
->willReturn(new Paginator(new ArrayAdapter($data)))
->shouldBeCalledOnce();
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::emptyInstance()),
)->willReturn(new Paginator(new ArrayAdapter($data)));
$this->commandTester->setInputs(['n']);
$this->commandTester->execute([]);
@ -95,9 +93,9 @@ class ListShortUrlsCommandTest extends TestCase
public function passingPageWillMakeListStartOnThatPage(): void
{
$page = 5;
$this->shortUrlService->listShortUrls(ShortUrlsParams::fromRawData(['page' => $page]))
->willReturn(new Paginator(new ArrayAdapter([])))
->shouldBeCalledOnce();
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData(['page' => $page])),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->setInputs(['y']);
$this->commandTester->execute(['--page' => $page]);
@ -113,15 +111,15 @@ class ListShortUrlsCommandTest extends TestCase
array $notExpectedContents,
ApiKey $apiKey,
): void {
$this->shortUrlService->listShortUrls(ShortUrlsParams::emptyInstance())
->willReturn(new Paginator(new ArrayAdapter([
ShortUrl::fromMeta(ShortUrlCreation::fromRawData([
'longUrl' => 'foo.com',
'tags' => ['foo', 'bar', 'baz'],
'apiKey' => $apiKey,
])),
])))
->shouldBeCalledOnce();
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::emptyInstance()),
)->willReturn(new Paginator(new ArrayAdapter([
ShortUrl::fromMeta(ShortUrlCreation::fromRawData([
'longUrl' => 'foo.com',
'tags' => ['foo', 'bar', 'baz'],
'apiKey' => $apiKey,
])),
])));
$this->commandTester->setInputs(['y']);
$this->commandTester->execute($input);
@ -189,19 +187,19 @@ class ListShortUrlsCommandTest extends TestCase
?string $startDate = null,
?string $endDate = null,
): void {
$listShortUrls = $this->shortUrlService->listShortUrls(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(
$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->commandTester->setInputs(['n']);
$this->commandTester->execute($commandArgs);
$listShortUrls->shouldHaveBeenCalledOnce();
}
public function provideArgs(): iterable
@ -251,14 +249,14 @@ class ListShortUrlsCommandTest extends TestCase
*/
public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void
{
$listShortUrls = $this->shortUrlService->listShortUrls(ShortUrlsParams::fromRawData([
'orderBy' => $expectedOrderBy,
]))->willReturn(new Paginator(new ArrayAdapter([])));
$this->shortUrlService->expects($this->once())->method('listShortUrls')->with(
$this->equalTo(ShortUrlsParams::fromRawData([
'orderBy' => $expectedOrderBy,
])),
)->willReturn(new Paginator(new ArrayAdapter([])));
$this->commandTester->setInputs(['n']);
$this->commandTester->execute($commandArgs);
$listShortUrls->shouldHaveBeenCalledOnce();
}
public function provideOrderBy(): iterable
@ -273,19 +271,19 @@ class ListShortUrlsCommandTest extends TestCase
/** @test */
public function requestingAllElementsWillSetItemsPerPage(): void
{
$listShortUrls = $this->shortUrlService->listShortUrls(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(
$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->commandTester->execute(['--all' => true]);
$listShortUrls->shouldHaveBeenCalledOnce();
}
}

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\ShortUrl\ResolveUrlCommand;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -23,12 +23,12 @@ class ResolveUrlCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $urlResolver;
private MockObject $urlResolver;
protected function setUp(): void
{
$this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
$this->commandTester = $this->testerForCommand(new ResolveUrlCommand($this->urlResolver->reveal()));
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
$this->commandTester = $this->testerForCommand(new ResolveUrlCommand($this->urlResolver));
}
/** @test */
@ -37,9 +37,9 @@ class ResolveUrlCommandTest extends TestCase
$shortCode = 'abc123';
$expectedUrl = 'http://domain.com/foo/bar';
$shortUrl = ShortUrl::withLongUrl($expectedUrl);
$this->urlResolver->resolveShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode))->willReturn(
$shortUrl,
)->shouldBeCalledOnce();
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
$this->equalTo(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)),
)->willReturn($shortUrl);
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();
@ -52,9 +52,9 @@ class ResolveUrlCommandTest extends TestCase
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123');
$shortCode = $identifier->shortCode;
$this->urlResolver->resolveShortUrl($identifier)
->willThrow(ShortUrlNotFoundException::fromNotFound($identifier))
->shouldBeCalledOnce();
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
$this->equalTo($identifier),
)->willThrowException(ShortUrlNotFoundException::fromNotFound($identifier));
$this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay();

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Tag\DeleteTagsCommand;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
@ -16,12 +16,12 @@ class DeleteTagsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
private MockObject $tagService;
protected function setUp(): void
{
$this->tagService = $this->prophesize(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteTagsCommand($this->tagService->reveal()));
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteTagsCommand($this->tagService));
}
/** @test */
@ -37,8 +37,7 @@ class DeleteTagsCommandTest extends TestCase
public function serviceIsInvokedOnSuccess(): void
{
$tagNames = ['foo', 'bar'];
$deleteTags = $this->tagService->deleteTags($tagNames)->will(function (): void {
});
$this->tagService->expects($this->once())->method('deleteTags')->with($this->equalTo($tagNames));
$this->commandTester->execute([
'--name' => $tagNames,
@ -46,6 +45,5 @@ class DeleteTagsCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Tags properly deleted', $output);
$deleteTags->shouldHaveBeenCalled();
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Tag\GetTagVisitsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -25,16 +24,16 @@ class GetTagVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitsHelper;
private ObjectProphecy $stringifier;
private MockObject $visitsHelper;
private MockObject $stringifier;
protected function setUp(): void
{
$this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class);
$this->stringifier = $this->prophesize(ShortUrlStringifierInterface::class);
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
new GetTagVisitsCommand($this->visitsHelper->reveal(), $this->stringifier->reveal()),
new GetTagVisitsCommand($this->visitsHelper, $this->stringifier),
);
}
@ -46,10 +45,13 @@ class GetTagVisitsCommandTest extends TestCase
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$tag = 'abc123';
$getVisits = $this->visitsHelper->visitsForTag($tag, Argument::any())->willReturn(
new Paginator(new ArrayAdapter([$visit])),
$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',
);
$stringify = $this->stringifier->stringify($shortUrl)->willReturn('the_short_url');
$this->commandTester->execute(['tag' => $tag]);
$output = $this->commandTester->getDisplay();
@ -65,7 +67,5 @@ class GetTagVisitsCommandTest extends TestCase
OUTPUT,
$output,
);
$getVisits->shouldHaveBeenCalledOnce();
$stringify->shouldHaveBeenCalledOnce();
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Tag\ListTagsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
@ -20,33 +19,36 @@ class ListTagsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
private MockObject $tagService;
protected function setUp(): void
{
$this->tagService = $this->prophesize(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListTagsCommand($this->tagService->reveal()));
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListTagsCommand($this->tagService));
}
/** @test */
public function noTagsPrintsEmptyMessage(): void
{
$tagsInfo = $this->tagService->tagsInfo(Argument::any())->willReturn(new Paginator(new ArrayAdapter([])));
$this->tagService->expects($this->once())->method('tagsInfo')->withAnyParameters()->willReturn(
new Paginator(new ArrayAdapter([])),
);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('No tags found', $output);
$tagsInfo->shouldHaveBeenCalled();
}
/** @test */
public function listOfTagsIsPrinted(): void
{
$tagsInfo = $this->tagService->tagsInfo(Argument::any())->willReturn(new Paginator(new ArrayAdapter([
new TagInfo('foo', 10, 2),
new TagInfo('bar', 7, 32),
])));
$this->tagService->expects($this->once())->method('tagsInfo')->withAnyParameters()->willReturn(
new Paginator(new ArrayAdapter([
new TagInfo('foo', 10, 2),
new TagInfo('bar', 7, 32),
])),
);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
@ -63,6 +65,5 @@ class ListTagsCommandTest extends TestCase
OUTPUT,
$output,
);
$tagsInfo->shouldHaveBeenCalled();
}
}

View file

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Tag\RenameTagCommand;
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Tag\Entity\Tag;
@ -19,12 +19,12 @@ class RenameTagCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
private MockObject $tagService;
protected function setUp(): void
{
$this->tagService = $this->prophesize(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new RenameTagCommand($this->tagService->reveal()));
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new RenameTagCommand($this->tagService));
}
/** @test */
@ -32,9 +32,9 @@ class RenameTagCommandTest extends TestCase
{
$oldName = 'foo';
$newName = 'bar';
$renameTag = $this->tagService->renameTag(TagRenaming::fromNames($oldName, $newName))->willThrow(
TagNotFoundException::fromTag('foo'),
);
$this->tagService->expects($this->once())->method('renameTag')->with(
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
)->willThrowException(TagNotFoundException::fromTag('foo'));
$this->commandTester->execute([
'oldName' => $oldName,
@ -43,7 +43,6 @@ class RenameTagCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Tag with name "foo" could not be found', $output);
$renameTag->shouldHaveBeenCalled();
}
/** @test */
@ -51,9 +50,9 @@ class RenameTagCommandTest extends TestCase
{
$oldName = 'foo';
$newName = 'bar';
$renameTag = $this->tagService->renameTag(TagRenaming::fromNames($oldName, $newName))->willReturn(
new Tag($newName),
);
$this->tagService->expects($this->once())->method('renameTag')->with(
$this->equalTo(TagRenaming::fromNames($oldName, $newName)),
)->willReturn(new Tag($newName));
$this->commandTester->execute([
'oldName' => $oldName,
@ -62,6 +61,5 @@ class RenameTagCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Tag properly renamed', $output);
$renameTag->shouldHaveBeenCalled();
}
}

View file

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Visit;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand;
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationDbUpdaterInterface;
@ -22,12 +21,12 @@ class DownloadGeoLiteDbCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $dbUpdater;
private MockObject $dbUpdater;
protected function setUp(): void
{
$this->dbUpdater = $this->prophesize(GeolocationDbUpdaterInterface::class);
$this->commandTester = $this->testerForCommand(new DownloadGeoLiteDbCommand($this->dbUpdater->reveal()));
$this->dbUpdater = $this->createMock(GeolocationDbUpdaterInterface::class);
$this->commandTester = $this->testerForCommand(new DownloadGeoLiteDbCommand($this->dbUpdater));
}
/**
@ -39,10 +38,8 @@ class DownloadGeoLiteDbCommandTest extends TestCase
string $expectedMessage,
int $expectedExitCode,
): void {
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will(
function (array $args) use ($olderDbExists): void {
[$beforeDownload, $handleProgress] = $args;
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback(
function (callable $beforeDownload, callable $handleProgress) use ($olderDbExists): void {
$beforeDownload($olderDbExists);
$handleProgress(100, 50);
@ -62,7 +59,6 @@ class DownloadGeoLiteDbCommandTest extends TestCase
);
self::assertStringContainsString($expectedMessage, $output);
self::assertSame($expectedExitCode, $exitCode);
$checkDbUpdate->shouldHaveBeenCalledOnce();
}
public function provideFailureParams(): iterable
@ -85,7 +81,9 @@ class DownloadGeoLiteDbCommandTest extends TestCase
*/
public function printsExpectedMessageWhenNoErrorOccurs(callable $checkUpdateBehavior, string $expectedMessage): void
{
$checkDbUpdate = $this->dbUpdater->checkDbUpdate(Argument::cetera())->will($checkUpdateBehavior);
$this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback(
$checkUpdateBehavior,
);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
@ -93,16 +91,13 @@ class DownloadGeoLiteDbCommandTest extends TestCase
self::assertStringContainsString($expectedMessage, $output);
self::assertSame(ExitCodes::EXIT_SUCCESS, $exitCode);
$checkDbUpdate->shouldHaveBeenCalledOnce();
}
public function provideSuccessParams(): iterable
{
yield 'up to date db' => [fn () => GeolocationResult::CHECK_SKIPPED, '[INFO] GeoLite2 db file is up to date.'];
yield 'outdated db' => [function (array $args): GeolocationResult {
[$beforeDownload] = $args;
yield 'outdated db' => [function (callable $beforeDownload): GeolocationResult {
$beforeDownload(true);
return GeolocationResult::DB_CREATED;
}, '[OK] GeoLite2 db file properly downloaded.'];
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Visit;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Visit\GetNonOrphanVisitsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -25,16 +24,16 @@ class GetNonOrphanVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitsHelper;
private ObjectProphecy $stringifier;
private MockObject $visitsHelper;
private MockObject $stringifier;
protected function setUp(): void
{
$this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class);
$this->stringifier = $this->prophesize(ShortUrlStringifierInterface::class);
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
new GetNonOrphanVisitsCommand($this->visitsHelper->reveal(), $this->stringifier->reveal()),
new GetNonOrphanVisitsCommand($this->visitsHelper, $this->stringifier),
);
}
@ -45,10 +44,12 @@ class GetNonOrphanVisitsCommandTest extends TestCase
$visit = Visit::forValidShortUrl($shortUrl, new Visitor('bar', 'foo', '', ''))->locate(
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$getVisits = $this->visitsHelper->nonOrphanVisits(Argument::any())->willReturn(
$this->visitsHelper->expects($this->once())->method('nonOrphanVisits')->withAnyParameters()->willReturn(
new Paginator(new ArrayAdapter([$visit])),
);
$stringify = $this->stringifier->stringify($shortUrl)->willReturn('the_short_url');
$this->stringifier->expects($this->once())->method('stringify')->with($this->equalTo($shortUrl))->willReturn(
'the_short_url',
);
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
@ -64,7 +65,5 @@ class GetNonOrphanVisitsCommandTest extends TestCase
OUTPUT,
$output,
);
$getVisits->shouldHaveBeenCalledOnce();
$stringify->shouldHaveBeenCalledOnce();
}
}

View file

@ -5,9 +5,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Visit;
use Pagerfanta\Adapter\ArrayAdapter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Visit\GetOrphanVisitsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
@ -23,12 +22,12 @@ class GetOrphanVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitsHelper;
private MockObject $visitsHelper;
protected function setUp(): void
{
$this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class);
$this->commandTester = $this->testerForCommand(new GetOrphanVisitsCommand($this->visitsHelper->reveal()));
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->commandTester = $this->testerForCommand(new GetOrphanVisitsCommand($this->visitsHelper));
}
/** @test */
@ -37,7 +36,7 @@ class GetOrphanVisitsCommandTest extends TestCase
$visit = Visit::forBasePath(new Visitor('bar', 'foo', '', ''))->locate(
VisitLocation::fromGeolocation(new Location('', 'Spain', '', 'Madrid', 0, 0, '')),
);
$getVisits = $this->visitsHelper->orphanVisits(Argument::any())->willReturn(
$this->visitsHelper->expects($this->once())->method('orphanVisits')->withAnyParameters()->willReturn(
new Paginator(new ArrayAdapter([$visit])),
);
@ -55,6 +54,5 @@ class GetOrphanVisitsCommandTest extends TestCase
OUTPUT,
$output,
);
$getVisits->shouldHaveBeenCalledOnce();
}
}

View file

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Visit;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand;
use Shlinkio\Shlink\CLI\Command\Visit\LocateVisitsCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
@ -35,33 +34,24 @@ class LocateVisitsCommandTest extends TestCase
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $visitService;
private ObjectProphecy $visitToLocation;
private ObjectProphecy $lock;
private ObjectProphecy $downloadDbCommand;
private MockObject $visitService;
private MockObject $visitToLocation;
private MockObject $lock;
private MockObject $downloadDbCommand;
protected function setUp(): void
{
$this->visitService = $this->prophesize(VisitLocator::class);
$this->visitToLocation = $this->prophesize(VisitToLocationHelperInterface::class);
$this->visitService = $this->createMock(VisitLocator::class);
$this->visitToLocation = $this->createMock(VisitToLocationHelperInterface::class);
$locker = $this->prophesize(Lock\LockFactory::class);
$this->lock = $this->prophesize(Lock\LockInterface::class);
$this->lock->acquire(false)->willReturn(true);
$this->lock->release()->will(function (): void {
});
$locker->createLock(Argument::type('string'), 600.0, false)->willReturn($this->lock->reveal());
$locker = $this->createMock(Lock\LockFactory::class);
$this->lock = $this->createMock(Lock\LockInterface::class);
$locker->method('createLock')->with($this->isType('string'), 600.0, false)->willReturn($this->lock);
$command = new LocateVisitsCommand(
$this->visitService->reveal(),
$this->visitToLocation->reveal(),
$locker->reveal(),
);
$command = new LocateVisitsCommand($this->visitService, $this->visitToLocation, $locker);
$this->downloadDbCommand = $this->createCommandMock(DownloadGeoLiteDbCommand::NAME);
$this->downloadDbCommand->run(Argument::cetera())->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester = $this->testerForCommand($command, $this->downloadDbCommand->reveal());
$this->commandTester = $this->testerForCommand($command, $this->downloadDbCommand);
}
/**
@ -79,14 +69,23 @@ class LocateVisitsCommandTest extends TestCase
$location = VisitLocation::fromGeolocation(Location::emptyInstance());
$mockMethodBehavior = $this->invokeHelperMethods($visit, $location);
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will($mockMethodBehavior);
$locateEmptyVisits = $this->visitService->locateVisitsWithEmptyLocation(Argument::cetera())->will(
$mockMethodBehavior,
);
$locateAllVisits = $this->visitService->locateAllVisits(Argument::cetera())->will($mockMethodBehavior);
$resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willReturn(
Location::emptyInstance(),
);
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
$this->visitService->expects($this->exactly($expectedUnlocatedCalls))
->method('locateUnlocatedVisits')
->withAnyParameters()
->willReturnCallback($mockMethodBehavior);
$this->visitService->expects($this->exactly($expectedEmptyCalls))
->method('locateVisitsWithEmptyLocation')
->withAnyParameters()
->willReturnCallback($mockMethodBehavior);
$this->visitService->expects($this->exactly($expectedAllCalls))
->method('locateAllVisits')
->withAnyParameters()
->willReturnCallback($mockMethodBehavior);
$this->visitToLocation->expects(
$this->exactly($expectedUnlocatedCalls + $expectedEmptyCalls + $expectedAllCalls),
)->method('resolveVisitLocation')->withAnyParameters()->willReturn(Location::emptyInstance());
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester->setInputs(['y']);
$this->commandTester->execute($args);
@ -98,12 +97,6 @@ class LocateVisitsCommandTest extends TestCase
} else {
self::assertStringNotContainsString('Continue at your own', $output);
}
$locateVisits->shouldHaveBeenCalledTimes($expectedUnlocatedCalls);
$locateEmptyVisits->shouldHaveBeenCalledTimes($expectedEmptyCalls);
$locateAllVisits->shouldHaveBeenCalledTimes($expectedAllCalls);
$resolveIpLocation->shouldHaveBeenCalledTimes(
$expectedUnlocatedCalls + $expectedEmptyCalls + $expectedAllCalls,
);
}
public function provideArgs(): iterable
@ -122,18 +115,19 @@ class LocateVisitsCommandTest extends TestCase
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance());
$location = VisitLocation::fromGeolocation(Location::emptyInstance());
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
$this->invokeHelperMethods($visit, $location),
);
$resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willThrow($e);
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
$this->visitService->expects($this->once())
->method('locateUnlocatedVisits')
->withAnyParameters()
->willReturnCallback($this->invokeHelperMethods($visit, $location));
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException($e);
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Processing IP', $output);
self::assertStringContainsString($message, $output);
$locateVisits->shouldHaveBeenCalledOnce();
$resolveIpLocation->shouldHaveBeenCalledOnce();
}
public function provideIgnoredAddresses(): iterable
@ -148,28 +142,26 @@ class LocateVisitsCommandTest extends TestCase
$visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', ''));
$location = VisitLocation::fromGeolocation(Location::emptyInstance());
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(
$this->invokeHelperMethods($visit, $location),
);
$resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willThrow(
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
$this->visitService->expects($this->once())
->method('locateUnlocatedVisits')
->withAnyParameters()
->willReturnCallback($this->invokeHelperMethods($visit, $location));
$this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException(
IpCannotBeLocatedException::forError(WrongIpException::fromIpAddress('1.2.3.4')),
);
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('An error occurred while locating IP. Skipped', $output);
$locateVisits->shouldHaveBeenCalledOnce();
$resolveIpLocation->shouldHaveBeenCalledOnce();
}
private function invokeHelperMethods(Visit $visit, VisitLocation $location): callable
{
return function (array $args) use ($visit, $location): void {
/** @var VisitGeolocationHelperInterface $helper */
[$helper] = $args;
return static function (VisitGeolocationHelperInterface $helper) use ($visit, $location): void {
$helper->geolocateVisit($visit);
$helper->onVisitLocated($location, $visit);
};
@ -178,11 +170,11 @@ class LocateVisitsCommandTest extends TestCase
/** @test */
public function noActionIsPerformedIfLockIsAcquired(): void
{
$this->lock->acquire(false)->willReturn(false);
$this->lock->method('acquire')->with($this->isFalse())->willReturn(false);
$locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function (): void {
});
$resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any());
$this->visitService->expects($this->never())->method('locateUnlocatedVisits');
$this->visitToLocation->expects($this->never())->method('resolveVisitLocation');
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay();
@ -191,25 +183,27 @@ class LocateVisitsCommandTest extends TestCase
sprintf('Command "%s" is already in progress. Skipping.', LocateVisitsCommand::NAME),
$output,
);
$locateVisits->shouldNotHaveBeenCalled();
$resolveIpLocation->shouldNotHaveBeenCalled();
}
/** @test */
public function showsProperMessageWhenGeoLiteUpdateFails(): void
{
$this->downloadDbCommand->run(Argument::cetera())->willReturn(ExitCodes::EXIT_FAILURE);
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_FAILURE);
$this->visitService->expects($this->never())->method('locateUnlocatedVisits');
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('It is not possible to locate visits without a GeoLite2 db file.', $output);
$this->visitService->locateUnlocatedVisits(Argument::cetera())->shouldNotHaveBeenCalled();
}
/** @test */
public function providingAllFlagOnItsOwnDisplaysNotice(): void
{
$this->lock->method('acquire')->with($this->isFalse())->willReturn(true);
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->commandTester->execute(['--all' => true]);
$output = $this->commandTester->getDisplay();
@ -222,6 +216,8 @@ class LocateVisitsCommandTest extends TestCase
*/
public function processingAllCancelsCommandIfUserDoesNotActivelyAgreeToConfirmation(array $inputs): void
{
$this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Execution aborted');

View file

@ -31,8 +31,8 @@ class ApplicationFactoryTest extends TestCase
'baz' => 'baz',
],
]);
$sm->setService('foo', $this->createCommandMock('foo')->reveal());
$sm->setService('bar', $this->createCommandMock('bar')->reveal());
$sm->setService('foo', $this->createCommandMock('foo'));
$sm->setService('bar', $this->createCommandMock('bar'));
$instance = ($this->factory)($sm);

View file

@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\CLI\GeoLite;
use Cake\Chronos\Chronos;
use GeoIp2\Database\Reader;
use MaxMind\Db\Reader\Metadata;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationDbUpdater;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationResult;
@ -25,23 +23,18 @@ use function range;
class GeolocationDbUpdaterTest extends TestCase
{
use ProphecyTrait;
private GeolocationDbUpdater $geolocationDbUpdater;
private ObjectProphecy $dbUpdater;
private ObjectProphecy $geoLiteDbReader;
private ObjectProphecy $lock;
private MockObject $dbUpdater;
private MockObject $geoLiteDbReader;
private MockObject $lock;
protected function setUp(): void
{
$this->dbUpdater = $this->prophesize(DbUpdaterInterface::class);
$this->geoLiteDbReader = $this->prophesize(Reader::class);
$this->dbUpdater = $this->createMock(DbUpdaterInterface::class);
$this->geoLiteDbReader = $this->createMock(Reader::class);
$this->trackingOptions = new TrackingOptions();
$this->lock = $this->prophesize(Lock\LockInterface::class);
$this->lock->acquire(true)->willReturn(true);
$this->lock->release()->will(function (): void {
});
$this->lock = $this->createMock(Lock\LockInterface::class);
$this->lock->method('acquire')->with($this->isTrue())->willReturn(true);
}
/** @test */
@ -50,25 +43,21 @@ class GeolocationDbUpdaterTest extends TestCase
$mustBeUpdated = fn () => self::assertTrue(true);
$prev = new DbUpdateException('');
$fileExists = $this->dbUpdater->databaseFileExists()->willReturn(false);
$getMeta = $this->geoLiteDbReader->metadata();
$download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev);
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(false);
$this->dbUpdater->expects($this->once())->method('downloadFreshCopy')->with(
$this->isNull(),
)->willThrowException($prev);
$this->geoLiteDbReader->expects($this->never())->method('metadata');
try {
$this->geolocationDbUpdater()->checkDbUpdate($mustBeUpdated);
self::assertTrue(false); // If this is reached, the test will fail
self::fail();
} catch (Throwable $e) {
/** @var GeolocationDbUpdateFailedException $e */
self::assertInstanceOf(GeolocationDbUpdateFailedException::class, $e);
self::assertSame($prev, $e->getPrevious());
self::assertFalse($e->olderDbExists());
}
$fileExists->shouldHaveBeenCalledOnce();
$getMeta->shouldNotHaveBeenCalled();
$download->shouldHaveBeenCalledOnce();
$this->lock->acquire(true)->shouldHaveBeenCalledOnce();
$this->lock->release()->shouldHaveBeenCalledOnce();
}
/**
@ -77,26 +66,24 @@ class GeolocationDbUpdaterTest extends TestCase
*/
public function exceptionIsThrownWhenOlderDbIsTooOldAndDownloadFails(int $days): void
{
$fileExists = $this->dbUpdater->databaseFileExists()->willReturn(true);
$getMeta = $this->geoLiteDbReader->metadata()->willReturn($this->buildMetaWithBuildEpoch(
Chronos::now()->subDays($days)->getTimestamp(),
));
$prev = new DbUpdateException('');
$download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev);
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(true);
$this->dbUpdater->expects($this->once())->method('downloadFreshCopy')->with(
$this->isNull(),
)->willThrowException($prev);
$this->geoLiteDbReader->expects($this->once())->method('metadata')->with()->willReturn(
$this->buildMetaWithBuildEpoch(Chronos::now()->subDays($days)->getTimestamp()),
);
try {
$this->geolocationDbUpdater()->checkDbUpdate();
self::assertTrue(false); // If this is reached, the test will fail
self::fail();
} catch (Throwable $e) {
/** @var GeolocationDbUpdateFailedException $e */
self::assertInstanceOf(GeolocationDbUpdateFailedException::class, $e);
self::assertSame($prev, $e->getPrevious());
self::assertTrue($e->olderDbExists());
}
$fileExists->shouldHaveBeenCalledOnce();
$getMeta->shouldHaveBeenCalledOnce();
$download->shouldHaveBeenCalledOnce();
}
public function provideBigDays(): iterable
@ -113,17 +100,15 @@ class GeolocationDbUpdaterTest extends TestCase
*/
public function databaseIsNotUpdatedIfItIsNewEnough(string|int $buildEpoch): void
{
$fileExists = $this->dbUpdater->databaseFileExists()->willReturn(true);
$getMeta = $this->geoLiteDbReader->metadata()->willReturn($this->buildMetaWithBuildEpoch($buildEpoch));
$download = $this->dbUpdater->downloadFreshCopy(null)->will(function (): void {
});
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(true);
$this->dbUpdater->expects($this->never())->method('downloadFreshCopy');
$this->geoLiteDbReader->expects($this->once())->method('metadata')->with()->willReturn(
$this->buildMetaWithBuildEpoch($buildEpoch),
);
$result = $this->geolocationDbUpdater()->checkDbUpdate();
self::assertEquals(GeolocationResult::DB_IS_UP_TO_DATE, $result);
$fileExists->shouldHaveBeenCalledOnce();
$getMeta->shouldHaveBeenCalledOnce();
$download->shouldNotHaveBeenCalled();
}
public function provideSmallDays(): iterable
@ -139,18 +124,16 @@ class GeolocationDbUpdaterTest extends TestCase
/** @test */
public function exceptionIsThrownWhenCheckingExistingDatabaseWithInvalidBuildEpoch(): void
{
$fileExists = $this->dbUpdater->databaseFileExists()->willReturn(true);
$getMeta = $this->geoLiteDbReader->metadata()->willReturn($this->buildMetaWithBuildEpoch('invalid'));
$download = $this->dbUpdater->downloadFreshCopy(null)->will(function (): void {
});
$this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(true);
$this->dbUpdater->expects($this->never())->method('downloadFreshCopy');
$this->geoLiteDbReader->expects($this->once())->method('metadata')->with()->willReturn(
$this->buildMetaWithBuildEpoch('invalid'),
);
$this->expectException(GeolocationDbUpdateFailedException::class);
$this->expectExceptionMessage(
'Build epoch with value "invalid" from existing geolocation database, could not be parsed to integer.',
);
$fileExists->shouldBeCalledOnce();
$getMeta->shouldBeCalledOnce();
$download->shouldNotBeCalled();
$this->geolocationDbUpdater()->checkDbUpdate();
}
@ -177,10 +160,10 @@ class GeolocationDbUpdaterTest extends TestCase
public function downloadDbIsSkippedIfTrackingIsDisabled(TrackingOptions $options): void
{
$result = $this->geolocationDbUpdater($options)->checkDbUpdate();
$this->dbUpdater->expects($this->never())->method('databaseFileExists');
$this->geoLiteDbReader->expects($this->never())->method('metadata');
self::assertEquals(GeolocationResult::CHECK_SKIPPED, $result);
$this->dbUpdater->databaseFileExists(Argument::cetera())->shouldNotHaveBeenCalled();
$this->geoLiteDbReader->metadata(Argument::cetera())->shouldNotHaveBeenCalled();
}
public function provideTrackingOptions(): iterable
@ -192,13 +175,13 @@ class GeolocationDbUpdaterTest extends TestCase
private function geolocationDbUpdater(?TrackingOptions $options = null): GeolocationDbUpdater
{
$locker = $this->prophesize(Lock\LockFactory::class);
$locker->createLock(Argument::type('string'))->willReturn($this->lock->reveal());
$locker = $this->createMock(Lock\LockFactory::class);
$locker->method('createLock')->with($this->isType('string'))->willReturn($this->lock);
return new GeolocationDbUpdater(
$this->dbUpdater->reveal(),
$this->geoLiteDbReader->reveal(),
$locker->reveal(),
$this->dbUpdater,
$this->geoLiteDbReader,
$locker,
$options ?? new TrackingOptions(),
);
}

View file

@ -4,10 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Util;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Util\ProcessRunner;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\HelperSet;
@ -17,90 +15,73 @@ use Symfony\Component\Process\Process;
class ProcessRunnerTest extends TestCase
{
use ProphecyTrait;
private ProcessRunner $runner;
private ObjectProphecy $helper;
private ObjectProphecy $formatter;
private ObjectProphecy $process;
private ObjectProphecy $output;
private MockObject $helper;
private MockObject $formatter;
private MockObject $process;
private MockObject $output;
protected function setUp(): void
{
$this->helper = $this->prophesize(ProcessHelper::class);
$this->formatter = $this->prophesize(DebugFormatterHelper::class);
$helperSet = $this->prophesize(HelperSet::class);
$helperSet->get('debug_formatter')->willReturn($this->formatter->reveal());
$this->helper->getHelperSet()->willReturn($helperSet->reveal());
$this->process = $this->prophesize(Process::class);
$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);
$this->helper->method('getHelperSet')->with()->willReturn($helperSet);
$this->process = $this->createMock(Process::class);
$this->output = $this->createMock(OutputInterface::class);
$this->runner = new ProcessRunner($this->helper->reveal(), fn () => $this->process->reveal());
$this->output = $this->prophesize(OutputInterface::class);
$this->runner = new ProcessRunner($this->helper, fn () => $this->process);
}
/** @test */
public function noMessagesAreWrittenWhenOutputIsNotVerbose(): void
{
$isVeryVerbose = $this->output->isVeryVerbose()->willReturn(false);
$isDebug = $this->output->isDebug()->willReturn(false);
$mustRun = $this->process->mustRun(Argument::cetera())->willReturn($this->process->reveal());
$this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(false);
$this->output->expects($this->once())->method('isDebug')->with()->willReturn(false);
$this->output->expects($this->never())->method('write');
$this->process->expects($this->once())->method('mustRun')->withAnyParameters()->willReturnSelf();
$this->process->expects($this->never())->method('isSuccessful');
$this->process->expects($this->never())->method('getCommandLine');
$this->helper->expects($this->never())->method('wrapCallback');
$this->formatter->expects($this->never())->method('start');
$this->formatter->expects($this->never())->method('stop');
$this->runner->run($this->output->reveal(), []);
$isVeryVerbose->shouldHaveBeenCalledTimes(2);
$isDebug->shouldHaveBeenCalledOnce();
$mustRun->shouldHaveBeenCalledOnce();
$this->process->isSuccessful()->shouldNotHaveBeenCalled();
$this->process->getCommandLine()->shouldNotHaveBeenCalled();
$this->output->write(Argument::cetera())->shouldNotHaveBeenCalled();
$this->helper->wrapCallback(Argument::cetera())->shouldNotHaveBeenCalled();
$this->formatter->start(Argument::cetera())->shouldNotHaveBeenCalled();
$this->formatter->stop(Argument::cetera())->shouldNotHaveBeenCalled();
$this->runner->run($this->output, []);
}
/** @test */
public function someMessagesAreWrittenWhenOutputIsVerbose(): void
{
$isVeryVerbose = $this->output->isVeryVerbose()->willReturn(true);
$isDebug = $this->output->isDebug()->willReturn(false);
$mustRun = $this->process->mustRun(Argument::cetera())->willReturn($this->process->reveal());
$isSuccessful = $this->process->isSuccessful()->willReturn(true);
$getCommandLine = $this->process->getCommandLine()->willReturn('true');
$start = $this->formatter->start(Argument::cetera())->willReturn('');
$stop = $this->formatter->stop(Argument::cetera())->willReturn('');
$this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(true);
$this->output->expects($this->once())->method('isDebug')->with()->willReturn(false);
$this->output->expects($this->exactly(2))->method('write')->withAnyParameters();
$this->process->expects($this->once())->method('mustRun')->withAnyParameters()->willReturnSelf();
$this->process->expects($this->exactly(2))->method('isSuccessful')->with()->willReturn(true);
$this->process->expects($this->once())->method('getCommandLine')->with()->willReturn('true');
$this->formatter->expects($this->once())->method('start')->withAnyParameters()->willReturn('');
$this->formatter->expects($this->once())->method('stop')->withAnyParameters()->willReturn('');
$this->helper->expects($this->never())->method('wrapCallback');
$this->runner->run($this->output->reveal(), []);
$isVeryVerbose->shouldHaveBeenCalledTimes(2);
$isDebug->shouldHaveBeenCalledOnce();
$mustRun->shouldHaveBeenCalledOnce();
$this->output->write(Argument::cetera())->shouldHaveBeenCalledTimes(2);
$this->helper->wrapCallback(Argument::cetera())->shouldNotHaveBeenCalled();
$isSuccessful->shouldHaveBeenCalledTimes(2);
$getCommandLine->shouldHaveBeenCalledOnce();
$start->shouldHaveBeenCalledOnce();
$stop->shouldHaveBeenCalledOnce();
$this->runner->run($this->output, []);
}
/** @test */
public function wrapsCallbackWhenOutputIsDebug(): void
{
$isVeryVerbose = $this->output->isVeryVerbose()->willReturn(false);
$isDebug = $this->output->isDebug()->willReturn(true);
$mustRun = $this->process->mustRun(Argument::cetera())->willReturn($this->process->reveal());
$wrapCallback = $this->helper->wrapCallback(Argument::cetera())->willReturn(function (): void {
});
$this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(false);
$this->output->expects($this->once())->method('isDebug')->with()->willReturn(true);
$this->output->expects($this->never())->method('write');
$this->process->expects($this->once())->method('mustRun')->withAnyParameters()->willReturnSelf();
$this->process->expects($this->never())->method('isSuccessful');
$this->process->expects($this->never())->method('getCommandLine');
$this->helper->expects($this->once())->method('wrapCallback')->withAnyParameters()->willReturn(
function (): void {
},
);
$this->formatter->expects($this->never())->method('start');
$this->formatter->expects($this->never())->method('stop');
$this->runner->run($this->output->reveal(), []);
$isVeryVerbose->shouldHaveBeenCalledTimes(2);
$isDebug->shouldHaveBeenCalledOnce();
$mustRun->shouldHaveBeenCalledOnce();
$wrapCallback->shouldHaveBeenCalledOnce();
$this->process->isSuccessful()->shouldNotHaveBeenCalled();
$this->process->getCommandLine()->shouldNotHaveBeenCalled();
$this->output->write(Argument::cetera())->shouldNotHaveBeenCalled();
$this->formatter->start(Argument::cetera())->shouldNotHaveBeenCalled();
$this->formatter->stop(Argument::cetera())->shouldNotHaveBeenCalled();
$this->runner->run($this->output, []);
}
}

View file

@ -4,10 +4,8 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Util;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use ReflectionObject;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Symfony\Component\Console\Helper\Table;
@ -16,15 +14,13 @@ use Symfony\Component\Console\Output\OutputInterface;
class ShlinkTableTest extends TestCase
{
use ProphecyTrait;
private ShlinkTable $shlinkTable;
private ObjectProphecy $baseTable;
private MockObject $baseTable;
protected function setUp(): void
{
$this->baseTable = $this->prophesize(Table::class);
$this->shlinkTable = ShlinkTable::fromBaseTable($this->baseTable->reveal());
$this->baseTable = $this->createMock(Table::class);
$this->shlinkTable = ShlinkTable::fromBaseTable($this->baseTable);
}
/** @test */
@ -35,29 +31,28 @@ class ShlinkTableTest extends TestCase
$headerTitle = 'Header';
$footerTitle = 'Footer';
$setStyle = $this->baseTable->setStyle(Argument::type(TableStyle::class))->willReturn(
$this->baseTable->reveal(),
);
$setHeaders = $this->baseTable->setHeaders($headers)->willReturn($this->baseTable->reveal());
$setRows = $this->baseTable->setRows($rows)->willReturn($this->baseTable->reveal());
$setFooterTitle = $this->baseTable->setFooterTitle($footerTitle)->willReturn($this->baseTable->reveal());
$setHeaderTitle = $this->baseTable->setHeaderTitle($headerTitle)->willReturn($this->baseTable->reveal());
$render = $this->baseTable->render()->willReturn($this->baseTable->reveal());
$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('render')->with()->willReturnSelf();
$this->shlinkTable->render($headers, $rows, $footerTitle, $headerTitle);
$setStyle->shouldHaveBeenCalledOnce();
$setHeaders->shouldHaveBeenCalledOnce();
$setRows->shouldHaveBeenCalledOnce();
$setFooterTitle->shouldHaveBeenCalledOnce();
$setHeaderTitle->shouldHaveBeenCalledOnce();
$render->shouldHaveBeenCalledOnce();
}
/** @test */
public function newTableIsCreatedForFactoryMethod(): void
{
$instance = ShlinkTable::default($this->prophesize(OutputInterface::class)->reveal());
$instance = ShlinkTable::default($this->createMock(OutputInterface::class));
$ref = new ReflectionObject($instance);
$baseTable = $ref->getProperty('baseTable');