Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expectsTable assertion do not work when mixed with expectsOutput #35805

Closed
BnitoBzh opened this issue Jan 6, 2021 · 2 comments · Fixed by #35820
Closed

expectsTable assertion do not work when mixed with expectsOutput #35805

BnitoBzh opened this issue Jan 6, 2021 · 2 comments · Fixed by #35820
Labels

Comments

@BnitoBzh
Copy link

BnitoBzh commented Jan 6, 2021

  • Laravel Version: 8.20.1
  • PHP Version: 7.4.13
  • Database Driver & Version: sqlite

Description:

On command testing, usage of expectsTable assertion do not work when used between expectsOutput.

Steps To Reproduce:

The command :

public function handle(): int
{
        $this->line('Before table');
        $this->table(['Header'], [['Value']]);
        $this->line('After table');
        return 0;
}

The test :

$this->artisan('command:name')
            ->expectsOutput('Before table')
            ->expectsTable(['Header'], [['Value']])
            ->expectsOutput('After table')
            ->assertExitCode(0);

The error :
Mockery\Exception\InvalidOrderException: Method [...] Output_BufferedOutput::doWrite('After table', <Any>)() called out of order: expected order 2, was 7

First test :
In the expectsTable assertion function, replace usage of $this->test->expectedTables[] = ... with the logic of the applyTableOutputExpectations function seems to fix the issue. Not tested with the laravel framework unit tests.

In other words, the expectsTable function could be :

/**
     * Specify a table that should be printed when the command runs.
     *
     * @param  array  $headers
     * @param  \Illuminate\Contracts\Support\Arrayable|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;
    }
@driesvints
Copy link
Member

I can indeed see this being problematic as even moving around the statements doesn't help. Performing two separate checks does work for me but is a bit cumbersome.

After looking into it further it indeed does seem to me that your solution makes sense. I think it could be considered but it does seems like a change in behavior to me so might need to go to the master branch.

@driesvints
Copy link
Member

Sent in a PR: #35820

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants