Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Testing/PendingCommand.php
Строк: 476
<?php

namespace IlluminateTesting;

use 
IlluminateConsoleOutputStyle;
use 
IlluminateConsolePromptValidationException;
use 
IlluminateContractsConsoleKernel;
use 
IlluminateContractsContainerContainer;
use 
IlluminateContractsSupportArrayable;
use 
IlluminateSupportArr;
use 
Mockery;
use 
MockeryExceptionNoMatchingExpectationException;
use 
PHPUnitFrameworkTestCase as PHPUnitTestCase;
use 
SymfonyComponentConsoleCommandCommand;
use 
SymfonyComponentConsoleHelperTable;
use 
SymfonyComponentConsoleInputArrayInput;
use 
SymfonyComponentConsoleOutputBufferedOutput;

class 
PendingCommand
{
    
/**
     * The test being run.
     *
     * @var IlluminateFoundationTestingTestCase
     */
    
public $test;

    
/**
     * The application instance.
     *
     * @var IlluminateContractsContainerContainer
     */
    
protected $app;

    
/**
     * The command to run.
     *
     * @var string
     */
    
protected $command;

    
/**
     * The parameters to pass to the command.
     *
     * @var array
     */
    
protected $parameters;

    
/**
     * The expected exit code.
     *
     * @var int
     */
    
protected $expectedExitCode;

    
/**
     * The unexpected exit code.
     *
     * @var int
     */
    
protected $unexpectedExitCode;

    
/**
     * Determine if the command has executed.
     *
     * @var bool
     */
    
protected $hasExecuted false;

    
/**
     * Create a new pending console command run.
     *
     * @param  PHPUnitFrameworkTestCase  $test
     * @param  IlluminateContractsContainerContainer  $app
     * @param  string  $command
     * @param  array  $parameters
     * @return void
     */
    
public function __construct(PHPUnitTestCase $testContainer $app$command$parameters)
    {
        
$this->app $app;
        
$this->test $test;
        
$this->command $command;
        
$this->parameters $parameters;
    }

    
/**
     * Specify an expected question that will be asked when the command runs.
     *
     * @param  string  $question
     * @param  string|bool  $answer
     * @return $this
     */
    
public function expectsQuestion($question$answer)
    {
        
$this->test->expectedQuestions[] = [$question$answer];

        return 
$this;
    }

    
/**
     * Specify an expected confirmation question that will be asked when the command runs.
     *
     * @param  string  $question
     * @param  string  $answer
     * @return $this
     */
    
public function expectsConfirmation($question$answer 'no')
    {
        return 
$this->expectsQuestion($questionstrtolower($answer) === 'yes');
    }

    
/**
     * Specify an expected choice question with expected answers that will be asked/shown when the command runs.
     *
     * @param  string  $question
     * @param  string|array  $answer
     * @param  array  $answers
     * @param  bool  $strict
     * @return $this
     */
    
public function expectsChoice($question$answer$answers$strict false)
    {
        
$this->test->expectedChoices[$question] = [
            
'expected' => $answers,
            
'strict' => $strict,
        ];

        return 
$this->expectsQuestion($question$answer);
    }

    
/**
     * Specify output that should be printed when the command runs.
     *
     * @param  string  $output
     * @return $this
     */
    
public function expectsOutput($output)
    {
        
$this->test->expectedOutput[] = $output;

        return 
$this;
    }

    
/**
     * Specify output that should never be printed when the command runs.
     *
     * @param  string  $output
     * @return $this
     */
    
public function doesntExpectOutput($output)
    {
        
$this->test->unexpectedOutput[$output] = false;

        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 that the given string shouldn't be contained in the command output.
     *
     * @param  string  $string
     * @return $this
     */
    
public function doesntExpectOutputToContain($string)
    {
        
$this->test->unexpectedOutputSubstrings[$string] = false;

        return 
$this;
    }

    
/**
     * Specify a table that should be printed when the command runs.
     *
     * @param  array  $headers
     * @param  IlluminateContractsSupportArrayable|array  $rows
     * @param  string  $tableStyle
     * @param  array  $columnStyles
     * @return $this
     */
    
public function expectsTable($headers$rows$tableStyle 'default', array $columnStyles = [])
    {
        
$table = (new Table($output = new BufferedOutput))
            ->
setHeaders((array) $headers)
            ->
setRows($rows instanceof Arrayable $rows->toArray() : $rows)
            ->
setStyle($tableStyle);

        foreach (
$columnStyles as $columnIndex => $columnStyle) {
            
$table->setColumnStyle($columnIndex$columnStyle);
        }

        
$table->render();

        
$lines array_filter(
            
explode(PHP_EOL$output->fetch())
        );

        foreach (
$lines as $line) {
            
$this->expectsOutput($line);
        }

        return 
$this;
    }

    
/**
     * Assert that the command has the given exit code.
     *
     * @param  int  $exitCode
     * @return $this
     */
    
public function assertExitCode($exitCode)
    {
        
$this->expectedExitCode $exitCode;

        return 
$this;
    }

    
/**
     * Assert that the command does not have the given exit code.
     *
     * @param  int  $exitCode
     * @return $this
     */
    
public function assertNotExitCode($exitCode)
    {
        
$this->unexpectedExitCode $exitCode;

        return 
$this;
    }

    
/**
     * Assert that the command has the success exit code.
     *
     * @return $this
     */
    
public function assertSuccessful()
    {
        return 
$this->assertExitCode(Command::SUCCESS);
    }

    
/**
     * Assert that the command has the success exit code.
     *
     * @return $this
     */
    
public function assertOk()
    {
        return 
$this->assertSuccessful();
    }

    
/**
     * Assert that the command does not have the success exit code.
     *
     * @return $this
     */
    
public function assertFailed()
    {
        return 
$this->assertNotExitCode(Command::SUCCESS);
    }

    
/**
     * Execute the command.
     *
     * @return int
     */
    
public function execute()
    {
        return 
$this->run();
    }

    
/**
     * Execute the command.
     *
     * @return int
     *
     * @throws MockeryExceptionNoMatchingExpectationException
     */
    
public function run()
    {
        
$this->hasExecuted true;

        
$mock $this->mockConsoleOutput();

        try {
            
$exitCode $this->app->make(Kernel::class)->call($this->command$this->parameters$mock);
        } catch (
NoMatchingExpectationException $e) {
            if (
$e->getMethodName() === 'askQuestion') {
                
$this->test->fail('Unexpected question "'.$e->getActualArguments()[0]->getQuestion().'" was asked.');
            }

            throw 
$e;
        } catch (
PromptValidationException) {
            
$exitCode Command::FAILURE;
        }

        if (
$this->expectedExitCode !== null) {
            
$this->test->assertEquals(
                
$this->expectedExitCode$exitCode,
                
"Expected status code {$this->expectedExitCode} but received {$exitCode}."
            
);
        } elseif (! 
is_null($this->unexpectedExitCode)) {
            
$this->test->assertNotEquals(
                
$this->unexpectedExitCode$exitCode,
                
"Unexpected status code {$this->unexpectedExitCode} was received."
            
);
        }

        
$this->verifyExpectations();
        
$this->flushExpectations();

        return 
$exitCode;
    }

    
/**
     * Determine if expected questions / choices / outputs are fulfilled.
     *
     * @return void
     */
    
protected function verifyExpectations()
    {
        if (
count($this->test->expectedQuestions)) {
            
$this->test->fail('Question "'.Arr::first($this->test->expectedQuestions)[0].'" was not asked.');
        }

        if (
count($this->test->expectedChoices) > 0) {
            foreach (
$this->test->expectedChoices as $question => $answers) {
                
$assertion $answers['strict'] ? 'assertEquals' 'assertEqualsCanonicalizing';

                
$this->test->{$assertion}(
                    
$answers['expected'],
                    
$answers['actual'],
                    
'Question "'.$question.'" has different options.'
                
);
            }
        }

        if (
count($this->test->expectedOutput)) {
            
$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.');
        }

        if (
$output array_search(true$this->test->unexpectedOutputSubstrings)) {
            
$this->test->fail('Output "'.$output.'" was printed.');
        }
    }

    
/**
     * Mock the application's console output.
     *
     * @return MockeryMockInterface
     */
    
protected function mockConsoleOutput()
    {
        
$mock Mockery::mock(OutputStyle::class.'[askQuestion]', [
            new 
ArrayInput($this->parameters), $this->createABufferedOutputMock(),
        ]);

        foreach (
$this->test->expectedQuestions as $i => $question) {
            
$mock->shouldReceive('askQuestion')
                ->
once()
                ->
ordered()
                ->
with(Mockery::on(function ($argument) use ($question) {
                    if (isset(
$this->test->expectedChoices[$question[0]])) {
                        
$this->test->expectedChoices[$question[0]]['actual'] = $argument->getAutocompleterValues();
                    }

                    return 
$argument->getQuestion() == $question[0];
                }))
                ->
andReturnUsing(function () use ($question$i) {
                    unset(
$this->test->expectedQuestions[$i]);

                    return 
$question[1];
                });
        }

        
$this->app->bind(OutputStyle::class, function () use ($mock) {
            return 
$mock;
        });

        return 
$mock;
    }

    
/**
     * Create a mock for the buffered output.
     *
     * @return MockeryMockInterface
     */
    
private function createABufferedOutputMock()
    {
        
$mock Mockery::mock(BufferedOutput::class.'[doWrite]')
                ->
shouldAllowMockingProtectedMethods()
                ->
shouldIgnoreMissing();

        foreach (
$this->test->expectedOutput as $i => $output) {
            
$mock->shouldReceive('doWrite')
                ->
once()
                ->
ordered()
                ->
with($outputMockery::any())
                ->
andReturnUsing(function () use ($i) {
                    unset(
$this->test->expectedOutput[$i]);
                });
        }

        foreach (
$this->test->expectedOutputSubstrings as $i => $text) {
            
$mock->shouldReceive('doWrite')
                ->
atLeast()
                ->
times(0)
                ->
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')
                ->
atLeast()
                ->
times(0)
                ->
ordered()
                ->
with($outputMockery::any())
                ->
andReturnUsing(function () use ($output) {
                    
$this->test->unexpectedOutput[$output] = true;
                });
        }

        foreach (
$this->test->unexpectedOutputSubstrings as $text => $displayed) {
            
$mock->shouldReceive('doWrite')
                 ->
atLeast()
                 ->
times(0)
                 ->
withArgs(fn ($output) => str_contains($output$text))
                 ->
andReturnUsing(function () use ($text) {
                     
$this->test->unexpectedOutputSubstrings[$text] = true;
                 });
        }

        return 
$mock;
    }

    
/**
     * Flush the expectations from the test case.
     *
     * @return void
     */
    
protected function flushExpectations()
    {
        
$this->test->expectedOutput = [];
        
$this->test->expectedOutputSubstrings = [];
        
$this->test->unexpectedOutput = [];
        
$this->test->unexpectedOutputSubstrings = [];
        
$this->test->expectedTables = [];
        
$this->test->expectedQuestions = [];
        
$this->test->expectedChoices = [];
    }

    
/**
     * Handle the object's destruction.
     *
     * @return void
     */
    
public function __destruct()
    {
        if (
$this->hasExecuted) {
            return;
        }

        
$this->run();
    }
}
Онлайн: 0
Реклама