service = $this->prophesize(DeleteShortUrlServiceInterface::class); $this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service->reveal())); } /** @test */ public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void { $shortCode = 'abc123'; $deleteByShortCode = $this->service->deleteByShortCode( ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), false, )->will(function (): void { }); $this->commandTester->execute(['shortCode' => $shortCode]); $output = $this->commandTester->getDisplay(); self::assertStringContainsString( sprintf('Short URL with short code "%s" successfully deleted.', $shortCode), $output, ); $deleteByShortCode->shouldHaveBeenCalledOnce(); } /** @test */ public function invalidShortCodePrintsMessage(): void { $shortCode = 'abc123'; $identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode); $deleteByShortCode = $this->service->deleteByShortCode($identifier, false)->willThrow( 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(); } /** * @test * @dataProvider provideRetryDeleteAnswers */ public function deleteIsRetriedWhenThresholdIsReachedAndQuestionIsAccepted( array $retryAnswer, int $expectedDeleteCalls, string $expectedMessage, ): 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->commandTester->setInputs($retryAnswer); $this->commandTester->execute(['shortCode' => $shortCode]); $output = $this->commandTester->getDisplay(); self::assertStringContainsString(sprintf( 'Impossible to delete short URL with short code "%s", since it has more than "10" visits.', $shortCode, ), $output); self::assertStringContainsString($expectedMessage, $output); $deleteByShortCode->shouldHaveBeenCalledTimes($expectedDeleteCalls); } public function provideRetryDeleteAnswers(): iterable { yield 'answering yes to retry' => [['yes'], 2, 'Short URL with short code "abc123" successfully deleted.']; yield 'answering no to retry' => [['no'], 1, 'Short URL was not deleted.']; yield 'answering default to retry' => [[PHP_EOL], 1, 'Short URL was not deleted.']; } /** @test */ public function deleteIsNotRetriedWhenThresholdIsReachedAndQuestionIsDeclined(): void { $shortCode = 'abc123'; $deleteByShortCode = $this->service->deleteByShortCode( ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), false, )->willThrow(Exception\DeleteShortUrlException::fromVisitsThreshold( 10, ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), )); $this->commandTester->setInputs(['no']); $this->commandTester->execute(['shortCode' => $shortCode]); $output = $this->commandTester->getDisplay(); self::assertStringContainsString(sprintf( 'Impossible to delete short URL with short code "%s", since it has more than "10" visits.', $shortCode, ), $output); self::assertStringContainsString('Short URL was not deleted.', $output); $deleteByShortCode->shouldHaveBeenCalledOnce(); } }