From 35d9f9a27513401a258547c4ad9a98b376c2df0b Mon Sep 17 00:00:00 2001 From: Francisco Madeira Date: Wed, 16 Feb 2022 18:58:15 +0000 Subject: [PATCH] [9.x] Adds `expectsOutputToContain` to the `PendingCommand`. (#40984) * feat: Adds `expectsOutputToContain` to the `PendingCommand`. * formatting Co-authored-by: Taylor Otwell --- .../Testing/Concerns/InteractsWithConsole.php | 7 +++++ src/Illuminate/Testing/PendingCommand.php | 26 +++++++++++++++++++ .../Testing/ArtisanCommandTest.php | 23 ++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php index 38409d3d697f..9f8fbcc88f73 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php @@ -22,6 +22,13 @@ trait InteractsWithConsole */ public $expectedOutput = []; + /** + * All of the expected text to be present on the output. + * + * @var array + */ + public $expectedOutputSubstrings = []; + /** * All of the output lines that aren't expected to be displayed. * diff --git a/src/Illuminate/Testing/PendingCommand.php b/src/Illuminate/Testing/PendingCommand.php index 870108644336..496215fa4aa1 100644 --- a/src/Illuminate/Testing/PendingCommand.php +++ b/src/Illuminate/Testing/PendingCommand.php @@ -154,6 +154,19 @@ public function doesntExpectOutput($output) return $this; } + /** + * Specify that the given string should be contained in the command output. + * + * @param string $string + * @return $this + */ + public function expectsOutputToContain($string) + { + $this->test->expectedOutputSubstrings[] = $string; + + return $this; + } + /** * Specify a table that should be printed when the command runs. * @@ -311,6 +324,10 @@ protected function verifyExpectations() $this->test->fail('Output "'.Arr::first($this->test->expectedOutput).'" was not printed.'); } + if (count($this->test->expectedOutputSubstrings)) { + $this->test->fail('Output does not contain "'.Arr::first($this->test->expectedOutputSubstrings).'".'); + } + if ($output = array_search(true, $this->test->unexpectedOutput)) { $this->test->fail('Output "'.$output.'" was printed.'); } @@ -373,6 +390,14 @@ private function createABufferedOutputMock() }); } + foreach ($this->test->expectedOutputSubstrings as $i => $text) { + $mock->shouldReceive('doWrite') + ->withArgs(fn ($output) => str_contains($output, $text)) + ->andReturnUsing(function () use ($i) { + unset($this->test->expectedOutputSubstrings[$i]); + }); + } + foreach ($this->test->unexpectedOutput as $output => $displayed) { $mock->shouldReceive('doWrite') ->ordered() @@ -393,6 +418,7 @@ private function createABufferedOutputMock() protected function flushExpectations() { $this->test->expectedOutput = []; + $this->test->expectedOutputSubstrings = []; $this->test->unexpectedOutput = []; $this->test->expectedTables = []; $this->test->expectedQuestions = []; diff --git a/tests/Integration/Testing/ArtisanCommandTest.php b/tests/Integration/Testing/ArtisanCommandTest.php index 82e827732597..23f1f3a4fcfc 100644 --- a/tests/Integration/Testing/ArtisanCommandTest.php +++ b/tests/Integration/Testing/ArtisanCommandTest.php @@ -32,6 +32,10 @@ protected function setUp(): void $this->line($this->ask('What?')); $this->line($this->ask('Huh?')); }); + + Artisan::command('contains', function () { + $this->line('My name is Taylor Otwell'); + }); } public function test_console_command_that_passes() @@ -110,6 +114,25 @@ public function test_console_command_that_fails_from_unordered_output() }); } + public function test_console_command_that_passes_if_the_output_contains() + { + $this->artisan('contains') + ->expectsOutputToContain('Taylor Otwell') + ->assertExitCode(0); + } + + public function test_console_command_that_fails_if_the_output_does_not_contain() + { + $this->expectException(AssertionFailedError::class); + $this->expectExceptionMessage('Output does not contain "Otwell Taylor".'); + + $this->ignoringMockOnceExceptions(function () { + $this->artisan('contains') + ->expectsOutputToContain('Otwell Taylor') + ->assertExitCode(0); + }); + } + /** * Don't allow Mockery's InvalidCountException to be reported. Mocks setup * in PendingCommand cause PHPUnit tearDown() to later throw the exception.