diff --git a/src/Illuminate/Console/Concerns/InteractsWithIO.php b/src/Illuminate/Console/Concerns/InteractsWithIO.php index a398928f633f..6101477a1a77 100644 --- a/src/Illuminate/Console/Concerns/InteractsWithIO.php +++ b/src/Illuminate/Console/Concerns/InteractsWithIO.php @@ -263,8 +263,8 @@ public function withProgressBar($totalSteps, Closure $callback) $bar->start(); if (is_iterable($totalSteps)) { - foreach ($totalSteps as $value) { - $callback($value, $bar); + foreach ($totalSteps as $key => $value) { + $callback($value, $bar, $key); $bar->advance(); } diff --git a/tests/Console/Concerns/InteractsWithIOTest.php b/tests/Console/Concerns/InteractsWithIOTest.php new file mode 100755 index 000000000000..0e8f47281187 --- /dev/null +++ b/tests/Console/Concerns/InteractsWithIOTest.php @@ -0,0 +1,88 @@ +makePartial(); + $command->setOutput($output); + + $output->shouldReceive('createProgressBar') + ->once() + ->with(count($iterable)) + ->andReturnUsing(function ($steps) use ($bufferedOutput) { + // we can't mock ProgressBar because it's final, so return a real one + return new ProgressBar($bufferedOutput, $steps); + }); + + $calledTimes = 0; + $result = $command->withProgressBar($iterable, function ($value, $bar, $key) use (&$calledTimes, $iterable) { + $this->assertInstanceOf(ProgressBar::class, $bar); + $this->assertSame(array_values($iterable)[$calledTimes], $value); + $this->assertSame(array_keys($iterable)[$calledTimes], $key); + $calledTimes++; + }); + + $this->assertSame(count($iterable), $calledTimes); + $this->assertSame($iterable, $result); + } + + public static function iterableDataProvider(): Generator + { + yield [['a', 'b', 'c']]; + + yield [['foo' => 'a', 'bar' => 'b', 'baz' => 'c']]; + } + + public function testWithProgressBarInteger() + { + $command = new CommandInteractsWithIO; + $bufferedOutput = new BufferedOutput(); + $output = m::mock(OutputStyle::class, [new ArgvInput(), $bufferedOutput])->makePartial(); + $command->setOutput($output); + + $totalSteps = 5; + + $output->shouldReceive('createProgressBar') + ->once() + ->with($totalSteps) + ->andReturnUsing(function ($steps) use ($bufferedOutput) { + // we can't mock ProgressBar because it's final, so return a real one + return new ProgressBar($bufferedOutput, $steps); + }); + + $called = false; + $command->withProgressBar($totalSteps, function ($bar) use (&$called) { + $this->assertInstanceOf(ProgressBar::class, $bar); + $called = true; + }); + + $this->assertTrue($called); + } +} + +class CommandInteractsWithIO extends Command +{ + use InteractsWithIO; +}