mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-22 08:56:42 -06:00
Added as much additional data as possible to exceptions
This commit is contained in:
parent
fffb2872ef
commit
5266743a0c
@ -83,7 +83,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||
$ignoreThreshold = array_pop($args);
|
||||
|
||||
if (!$ignoreThreshold) {
|
||||
throw new Exception\DeleteShortUrlException(10);
|
||||
throw Exception\DeleteShortUrlException::fromVisitsThreshold(10, '');
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -112,7 +112,7 @@ class DeleteShortUrlCommandTest extends TestCase
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$deleteByShortCode = $this->service->deleteByShortCode($shortCode, false)->willThrow(
|
||||
new Exception\DeleteShortUrlException(10)
|
||||
Exception\DeleteShortUrlException::fromVisitsThreshold(10, '')
|
||||
);
|
||||
$this->commandTester->setInputs(['no']);
|
||||
|
||||
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Shlinkio\Shlink\Core\Exception;
|
||||
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
use Throwable;
|
||||
use Zend\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
|
||||
use Zend\ProblemDetails\Exception\ProblemDetailsExceptionInterface;
|
||||
|
||||
@ -18,18 +17,9 @@ class DeleteShortUrlException extends DomainException implements ProblemDetailsE
|
||||
private const TITLE = 'Cannot delete short URL';
|
||||
private const TYPE = 'INVALID_SHORTCODE_DELETION'; // FIXME Should be INVALID_SHORT_URL_DELETION
|
||||
|
||||
/** @var int */
|
||||
private $visitsThreshold;
|
||||
|
||||
public function __construct(int $visitsThreshold, string $message = '', int $code = 0, ?Throwable $previous = null)
|
||||
{
|
||||
$this->visitsThreshold = $visitsThreshold;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
public static function fromVisitsThreshold(int $threshold, string $shortCode): self
|
||||
{
|
||||
$e = new self($threshold, sprintf(
|
||||
$e = new self(sprintf(
|
||||
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
||||
$shortCode,
|
||||
$threshold
|
||||
@ -39,13 +29,16 @@ class DeleteShortUrlException extends DomainException implements ProblemDetailsE
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY;
|
||||
$e->additional = ['threshold' => $threshold];
|
||||
$e->additional = [
|
||||
'shortCode' => $shortCode,
|
||||
'threshold' => $threshold,
|
||||
];
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
public function getVisitsThreshold(): int
|
||||
{
|
||||
return $this->visitsThreshold;
|
||||
return $this->additional['threshold'];
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class InvalidUrlException extends DomainException implements ProblemDetailsExcep
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = $status;
|
||||
$e->additional = ['url' => $url];
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ class NonUniqueSlugException extends InvalidArgumentException implements Problem
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_BAD_REQUEST;
|
||||
$e->additional = ['customSlug' => $slug];
|
||||
|
||||
if ($domain !== null) {
|
||||
$e->additional['domain'] = $domain;
|
||||
}
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ class ShortUrlNotFoundException extends DomainException implements ProblemDetail
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_NOT_FOUND;
|
||||
$e->additional = ['shortCode' => $shortCode];
|
||||
|
||||
if ($domain !== null) {
|
||||
$e->additional['domain'] = $domain;
|
||||
}
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ class TagNotFoundException extends DomainException implements ProblemDetailsExce
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_NOT_FOUND;
|
||||
$e->additional = ['tag' => $tag];
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
@ -24,19 +24,6 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
||||
private const TITLE = 'Invalid data';
|
||||
private const TYPE = 'INVALID_ARGUMENT';
|
||||
|
||||
/** @var array */
|
||||
private $invalidElements;
|
||||
|
||||
public function __construct(
|
||||
string $message = '',
|
||||
array $invalidElements = [],
|
||||
int $code = 0,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
$this->invalidElements = $invalidElements;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
public static function fromInputFilter(InputFilterInterface $inputFilter, ?Throwable $prev = null): self
|
||||
{
|
||||
return static::fromArray($inputFilter->getMessages(), $prev);
|
||||
@ -45,22 +32,20 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
||||
public static function fromArray(array $invalidData, ?Throwable $prev = null): self
|
||||
{
|
||||
$status = StatusCodeInterface::STATUS_BAD_REQUEST;
|
||||
$e = new self('Provided data is not valid', $invalidData, $status, $prev);
|
||||
$e = new self('Provided data is not valid', $status, $prev);
|
||||
|
||||
$e->detail = $e->getMessage();
|
||||
$e->title = self::TITLE;
|
||||
$e->type = self::TYPE;
|
||||
$e->status = StatusCodeInterface::STATUS_BAD_REQUEST;
|
||||
$e->additional = [
|
||||
'invalidElements' => $invalidData,
|
||||
];
|
||||
$e->additional = ['invalidElements' => $invalidData];
|
||||
|
||||
return $e;
|
||||
}
|
||||
|
||||
public function getInvalidElements(): array
|
||||
{
|
||||
return $this->invalidElements;
|
||||
return $this->additional['invalidElements'];
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
@ -80,7 +65,7 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
||||
|
||||
private function invalidElementsToString(): string
|
||||
{
|
||||
return reduce_left($this->invalidElements, function ($messageSet, string $name, $_, string $acc) {
|
||||
return reduce_left($this->getInvalidElements(), function ($messageSet, string $name, $_, string $acc) {
|
||||
return $acc . sprintf(
|
||||
"\n '%s' => %s",
|
||||
$name,
|
||||
|
@ -5,17 +5,15 @@ declare(strict_types=1);
|
||||
namespace ShlinkioTest\Shlink\Core\Exception;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\Common\Util\StringUtilsTrait;
|
||||
use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException;
|
||||
|
||||
use function Functional\map;
|
||||
use function range;
|
||||
use function Shlinkio\Shlink\Core\generateRandomShortCode;
|
||||
use function sprintf;
|
||||
|
||||
class DeleteShortUrlExceptionTest extends TestCase
|
||||
{
|
||||
use StringUtilsTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideThresholds
|
||||
@ -29,29 +27,12 @@ class DeleteShortUrlExceptionTest extends TestCase
|
||||
|
||||
$this->assertEquals($threshold, $e->getVisitsThreshold());
|
||||
$this->assertEquals($expectedMessage, $e->getMessage());
|
||||
$this->assertEquals(0, $e->getCode());
|
||||
$this->assertNull($e->getPrevious());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideThresholds
|
||||
*/
|
||||
public function visitsThresholdIsProperlyReturned(int $threshold): void
|
||||
{
|
||||
$e = new DeleteShortUrlException($threshold);
|
||||
|
||||
$this->assertEquals($threshold, $e->getVisitsThreshold());
|
||||
$this->assertEquals('', $e->getMessage());
|
||||
$this->assertEquals(0, $e->getCode());
|
||||
$this->assertNull($e->getPrevious());
|
||||
}
|
||||
|
||||
public function provideThresholds(): array
|
||||
{
|
||||
return map(range(5, 50, 5), function (int $number) {
|
||||
$shortCode = $this->generateRandomString(6);
|
||||
return [$number, $shortCode, sprintf(
|
||||
return [$number, $shortCode = generateRandomShortCode(6), sprintf(
|
||||
'Impossible to delete short URL with short code "%s" since it has more than "%s" visits.',
|
||||
$shortCode,
|
||||
$number
|
||||
|
@ -13,38 +13,9 @@ use Throwable;
|
||||
use Zend\InputFilter\InputFilterInterface;
|
||||
|
||||
use function print_r;
|
||||
use function random_int;
|
||||
|
||||
class ValidationExceptionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideExceptionData
|
||||
*/
|
||||
public function createsExceptionWrappingExpectedData(
|
||||
array $args,
|
||||
string $expectedMessage,
|
||||
array $expectedInvalidElements,
|
||||
int $expectedCode,
|
||||
?Throwable $expectedPrev
|
||||
): void {
|
||||
$e = new ValidationException(...$args);
|
||||
|
||||
$this->assertEquals($expectedMessage, $e->getMessage());
|
||||
$this->assertEquals($expectedInvalidElements, $e->getInvalidElements());
|
||||
$this->assertEquals($expectedCode, $e->getCode());
|
||||
$this->assertEquals($expectedPrev, $e->getPrevious());
|
||||
}
|
||||
|
||||
public function provideExceptionData(): iterable
|
||||
{
|
||||
yield 'empty args' => [[], '', [], 0, null];
|
||||
yield 'with message' => [['something'], 'something', [], 0, null];
|
||||
yield 'with elements' => [['something_else', [1, 2, 3]], 'something_else', [1, 2, 3], 0, null];
|
||||
yield 'with code' => [['foo', [], $foo = random_int(-100, 100)], 'foo', [], $foo, null];
|
||||
yield 'with prev' => [['bar', [], 8, $e = new RuntimeException()], 'bar', [], 8, $e];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideExceptions
|
||||
|
Loading…
Reference in New Issue
Block a user