Improved ApplicationConfigCustomizer while asking for visits threshold

This commit is contained in:
Alejandro Celaya
2018-10-06 12:01:18 +02:00
parent 5337eb48e7
commit 75f6160432
3 changed files with 114 additions and 5 deletions

View File

@@ -4,10 +4,13 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Config\Plugin; namespace Shlinkio\Shlink\Installer\Config\Plugin;
use Shlinkio\Shlink\Common\Util\StringUtilsTrait; use Shlinkio\Shlink\Common\Util\StringUtilsTrait;
use Shlinkio\Shlink\Installer\Exception\InvalidConfigOptionException;
use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig; use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function array_diff; use function array_diff;
use function array_keys; use function array_keys;
use function is_numeric;
use function sprintf;
class ApplicationConfigCustomizer implements ConfigCustomizerInterface class ApplicationConfigCustomizer implements ConfigCustomizerInterface
{ {
@@ -64,12 +67,24 @@ class ApplicationConfigCustomizer implements ConfigCustomizerInterface
. 'have more than a specific amount of visits?' . 'have more than a specific amount of visits?'
); );
case self::VISITS_THRESHOLD: case self::VISITS_THRESHOLD:
return (int) $io->ask( return $io->ask(
'What is the amount of visits from which the system will not allow short URLs to be deleted?', 'What is the amount of visits from which the system will not allow short URLs to be deleted?',
15 15,
[$this, 'validateVisitsThreshold']
); );
} }
return ''; return '';
} }
public function validateVisitsThreshold($value): int
{
if (! is_numeric($value) || $value < 1) {
throw new InvalidConfigOptionException(
sprintf('Provided value "%s" is invalid. Expected a number greater than 1', $value)
);
}
return (int) $value;
}
} }

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Exception;
use RuntimeException;
class InvalidConfigOptionException extends RuntimeException implements ExceptionInterface
{
}

View File

@@ -7,8 +7,11 @@ use PHPUnit\Framework\TestCase;
use Prophecy\Argument; use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Installer\Config\Plugin\ApplicationConfigCustomizer; use Shlinkio\Shlink\Installer\Config\Plugin\ApplicationConfigCustomizer;
use Shlinkio\Shlink\Installer\Exception\InvalidConfigOptionException;
use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig; use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function array_shift;
use function strpos;
class ApplicationConfigCustomizerTest extends TestCase class ApplicationConfigCustomizerTest extends TestCase
{ {
@@ -34,17 +37,47 @@ class ApplicationConfigCustomizerTest extends TestCase
*/ */
public function configIsRequestedToTheUser() public function configIsRequestedToTheUser()
{ {
$ask = $this->io->ask(Argument::cetera())->willReturn('the_secret'); $ask = $this->io->ask(Argument::cetera())->willReturn('asked');
$confirm = $this->io->confirm(Argument::cetera())->willReturn(false);
$config = new CustomizableAppConfig(); $config = new CustomizableAppConfig();
$this->plugin->process($this->io->reveal(), $config); $this->plugin->process($this->io->reveal(), $config);
$this->assertTrue($config->hasApp()); $this->assertTrue($config->hasApp());
$this->assertEquals([ $this->assertEquals([
'SECRET' => 'the_secret', 'SECRET' => 'asked',
'DISABLE_TRACK_PARAM' => 'the_secret', 'DISABLE_TRACK_PARAM' => 'asked',
'CHECK_VISITS_THRESHOLD' => false,
], $config->getApp()); ], $config->getApp());
$ask->shouldHaveBeenCalledTimes(2); $ask->shouldHaveBeenCalledTimes(2);
$confirm->shouldHaveBeenCalledTimes(1);
}
/**
* @test
*/
public function visitsThresholdIsRequestedIfCheckIsEnabled()
{
$ask = $this->io->ask(Argument::cetera())->will(function (array $args) {
$message = array_shift($args);
return strpos($message, 'What is the amount of visits') === 0 ? 20 : 'asked';
});
$confirm = $this->io->confirm(Argument::cetera())->willReturn(true);
$config = new CustomizableAppConfig();
$this->plugin->process($this->io->reveal(), $config);
$this->assertTrue($config->hasApp());
$this->assertEquals([
'SECRET' => 'asked',
'DISABLE_TRACK_PARAM' => 'asked',
'CHECK_VISITS_THRESHOLD' => true,
'VISITS_THRESHOLD' => 20,
], $config->getApp());
$ask->shouldHaveBeenCalledTimes(3);
$confirm->shouldHaveBeenCalledTimes(1);
} }
/** /**
@@ -56,6 +89,8 @@ class ApplicationConfigCustomizerTest extends TestCase
$config = new CustomizableAppConfig(); $config = new CustomizableAppConfig();
$config->setApp([ $config->setApp([
'SECRET' => 'foo', 'SECRET' => 'foo',
'CHECK_VISITS_THRESHOLD' => true,
'VISITS_THRESHOLD' => 20,
]); ]);
$this->plugin->process($this->io->reveal(), $config); $this->plugin->process($this->io->reveal(), $config);
@@ -63,6 +98,8 @@ class ApplicationConfigCustomizerTest extends TestCase
$this->assertEquals([ $this->assertEquals([
'SECRET' => 'foo', 'SECRET' => 'foo',
'DISABLE_TRACK_PARAM' => 'disable_param', 'DISABLE_TRACK_PARAM' => 'disable_param',
'CHECK_VISITS_THRESHOLD' => true,
'VISITS_THRESHOLD' => 20,
], $config->getApp()); ], $config->getApp());
$ask->shouldHaveBeenCalledTimes(1); $ask->shouldHaveBeenCalledTimes(1);
} }
@@ -78,6 +115,8 @@ class ApplicationConfigCustomizerTest extends TestCase
$config->setApp([ $config->setApp([
'SECRET' => 'foo', 'SECRET' => 'foo',
'DISABLE_TRACK_PARAM' => 'the_new_secret', 'DISABLE_TRACK_PARAM' => 'the_new_secret',
'CHECK_VISITS_THRESHOLD' => true,
'VISITS_THRESHOLD' => 20,
]); ]);
$this->plugin->process($this->io->reveal(), $config); $this->plugin->process($this->io->reveal(), $config);
@@ -85,7 +124,52 @@ class ApplicationConfigCustomizerTest extends TestCase
$this->assertEquals([ $this->assertEquals([
'SECRET' => 'foo', 'SECRET' => 'foo',
'DISABLE_TRACK_PARAM' => 'the_new_secret', 'DISABLE_TRACK_PARAM' => 'the_new_secret',
'CHECK_VISITS_THRESHOLD' => true,
'VISITS_THRESHOLD' => 20,
], $config->getApp()); ], $config->getApp());
$ask->shouldNotHaveBeenCalled(); $ask->shouldNotHaveBeenCalled();
} }
/**
* @test
* @dataProvider provideInvalidValues
* @param mixed $value
*/
public function validateVisitsThresholdThrowsExceptionWhenProvidedValueIsInvalid($value)
{
$this->expectException(InvalidConfigOptionException::class);
$this->plugin->validateVisitsThreshold($value);
}
public function provideInvalidValues(): array
{
return [
'string' => ['foo'],
'empty string' => [''],
'negative number' => [-5],
'negative number as string' => ['-5'],
'zero' => [0],
'zero as string' => ['0'],
];
}
/**
* @test
* @dataProvider provideValidValues
* @param mixed $value
*/
public function validateVisitsThresholdCastsToIntWhenProvidedValueIsValid($value, int $expected)
{
$this->assertEquals($expected, $this->plugin->validateVisitsThreshold($value));
}
public function provideValidValues(): array
{
return [
'positive as string' => ['20', 20],
'positive as integer' => [5, 5],
'one as string' => ['1', 1],
'one as integer' => [1, 1],
];
}
} }