Print warning when trying to create short URL from CLI on openswoole in verbose mode

This commit is contained in:
Alejandro Celaya 2023-04-12 18:30:02 +02:00
parent f078d95588
commit 399c56a097
4 changed files with 67 additions and 5 deletions

View File

@ -176,6 +176,11 @@ class CreateShortUrlCommand extends Command
ShortUrlInputFilter::FORWARD_QUERY => !$input->getOption('no-forward-query'), ShortUrlInputFilter::FORWARD_QUERY => !$input->getOption('no-forward-query'),
], $this->options)); ], $this->options));
$result->onEventDispatchingError(static fn () => $io->isVerbose() && $io->warning(
'Short URL properly created, but the real-time updates cannot be notified when generating the '
. 'short URL from the command line. Migrate to roadrunner in order to bypass this limitation.',
));
$io->writeln([ $io->writeln([
sprintf('Processed long URL: <info>%s</info>', $longUrl), sprintf('Processed long URL: <info>%s</info>', $longUrl),
sprintf('Generated short URL: <info>%s</info>', $this->stringifier->stringify($result->shortUrl)), sprintf('Generated short URL: <info>%s</info>', $this->stringifier->stringify($result->shortUrl)),

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl; namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use PHPUnit\Framework\Assert; use PHPUnit\Framework\Assert;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Test;
@ -20,6 +21,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult; use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface; use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait; use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
class CreateShortUrlCommandTest extends TestCase class CreateShortUrlCommandTest extends TestCase
@ -62,11 +64,12 @@ class CreateShortUrlCommandTest extends TestCase
$this->commandTester->execute([ $this->commandTester->execute([
'longUrl' => 'http://domain.com/foo/bar', 'longUrl' => 'http://domain.com/foo/bar',
'--max-visits' => '3', '--max-visits' => '3',
]); ], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]);
$output = $this->commandTester->getDisplay(); $output = $this->commandTester->getDisplay();
self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode()); self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
self::assertStringContainsString('stringified_short_url', $output); self::assertStringContainsString('stringified_short_url', $output);
self::assertStringNotContainsString('but the real-time updates cannot be notified', $output);
} }
#[Test] #[Test]
@ -170,4 +173,40 @@ class CreateShortUrlCommandTest extends TestCase
yield 'no flags' => [[], null]; yield 'no flags' => [[], null];
yield 'validate-url' => [['--validate-url' => true], true]; yield 'validate-url' => [['--validate-url' => true], true];
} }
/**
* @param callable(string $output): void $assert
*/
#[Test, DataProvider('provideDispatchBehavior')]
public function warningIsPrintedInVerboseModeWhenDispatchErrors(int $verbosity, callable $assert): void
{
$shortUrl = ShortUrl::createFake();
$this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willReturn(
UrlShorteningResult::withErrorOnEventDispatching($shortUrl, new ServiceNotFoundException()),
);
$this->stringifier->method('stringify')->willReturn('stringified_short_url');
$this->commandTester->execute(['longUrl' => 'http://domain.com/foo/bar'], ['verbosity' => $verbosity]);
$output = $this->commandTester->getDisplay();
$assert($output);
}
public static function provideDispatchBehavior(): iterable
{
$containsAssertion = static fn (string $output) => self::assertStringContainsString(
'but the real-time updates cannot be notified',
$output,
);
$doesNotContainAssertion = static fn (string $output) => self::assertStringNotContainsString(
'but the real-time updates cannot be notified',
$output,
);
yield 'quiet' => [OutputInterface::VERBOSITY_QUIET, $doesNotContainAssertion];
yield 'normal' => [OutputInterface::VERBOSITY_NORMAL, $doesNotContainAssertion];
yield 'verbose' => [OutputInterface::VERBOSITY_VERBOSE, $containsAssertion];
yield 'very verbose' => [OutputInterface::VERBOSITY_VERY_VERBOSE, $containsAssertion];
yield 'debug' => [OutputInterface::VERBOSITY_DEBUG, $containsAssertion];
}
} }

View File

@ -16,7 +16,7 @@ final class UrlShorteningResult
} }
/** /**
* @param callable(Throwable $errorOnEventDispatching): void $handler * @param callable(Throwable $errorOnEventDispatching): mixed $handler
*/ */
public function onEventDispatchingError(callable $handler): void public function onEventDispatchingError(callable $handler): void
{ {

View File

@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl;
use Cake\Chronos\Chronos; use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
@ -26,6 +27,7 @@ class UrlShortenerTest extends TestCase
private MockObject & EntityManager $em; private MockObject & EntityManager $em;
private MockObject & ShortUrlTitleResolutionHelperInterface $titleResolutionHelper; private MockObject & ShortUrlTitleResolutionHelperInterface $titleResolutionHelper;
private MockObject & ShortCodeUniquenessHelperInterface $shortCodeHelper; private MockObject & ShortCodeUniquenessHelperInterface $shortCodeHelper;
private MockObject & EventDispatcherInterface $dispatcher;
protected function setUp(): void protected function setUp(): void
{ {
@ -39,17 +41,19 @@ class UrlShortenerTest extends TestCase
fn (callable $callback) => $callback(), fn (callable $callback) => $callback(),
); );
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
$this->urlShortener = new UrlShortener( $this->urlShortener = new UrlShortener(
$this->titleResolutionHelper, $this->titleResolutionHelper,
$this->em, $this->em,
new SimpleShortUrlRelationResolver(), new SimpleShortUrlRelationResolver(),
$this->shortCodeHelper, $this->shortCodeHelper,
$this->createMock(EventDispatcherInterface::class), $this->dispatcher,
); );
} }
#[Test] #[Test, DataProvider('provideDispatchBehavior')]
public function urlIsProperlyShortened(): void public function urlIsProperlyShortened(bool $expectDispatchError, callable $dispatchBehavior): void
{ {
$longUrl = 'http://foobar.com/12345/hello?foo=bar'; $longUrl = 'http://foobar.com/12345/hello?foo=bar';
$meta = ShortUrlCreation::fromRawData(['longUrl' => $longUrl]); $meta = ShortUrlCreation::fromRawData(['longUrl' => $longUrl]);
@ -57,10 +61,24 @@ class UrlShortenerTest extends TestCase
$meta, $meta,
)->willReturnArgument(0); )->willReturnArgument(0);
$this->shortCodeHelper->method('ensureShortCodeUniqueness')->willReturn(true); $this->shortCodeHelper->method('ensureShortCodeUniqueness')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->willReturnCallback($dispatchBehavior);
$result = $this->urlShortener->shorten($meta); $result = $this->urlShortener->shorten($meta);
$thereIsError = false;
$result->onEventDispatchingError(function () use (&$thereIsError) {
$thereIsError = true;
});
self::assertEquals($longUrl, $result->shortUrl->getLongUrl()); self::assertEquals($longUrl, $result->shortUrl->getLongUrl());
self::assertEquals($expectDispatchError, $thereIsError);
}
public static function provideDispatchBehavior(): iterable
{
yield 'no dispatch error' => [false, static function (): void {}];
yield 'dispatch error' => [true, static function (): void {
throw new ServiceNotFoundException();
}];
} }
#[Test] #[Test]