Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Illuminate/Contracts/Process/InvokedProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,12 @@ public function latestErrorOutput();
* @return \Illuminate\Process\ProcessResult
*/
public function wait(?callable $output = null);

/**
* Wait until the given callback returns true.
*
* @param callable|null $output
* @return \Illuminate\Process\ProcessResult
*/
public function waitUntil(?callable $output = null);
}
25 changes: 25 additions & 0 deletions src/Illuminate/Process/FakeInvokedProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,31 @@ public function wait(?callable $output = null)
return $this->process->toProcessResult($this->command);
}

/**
* Wait until the given callback returns true.
*
* @param callable|null $output
* @return \Illuminate\Contracts\Process\ProcessResult
*/
public function waitUntil(?callable $output = null)
{
$this->outputHandler = $output ?: $this->outputHandler;

if (! $this->outputHandler) {
$this->remainingRunIterations = 0;

return $this->predictProcessResult();
}

while ($this->running() && ! call_user_func($this->outputHandler, 'out', $this->latestOutput())) {
//
}

$this->remainingRunIterations = 0;

return $this->process->toProcessResult($this->command);
}

/**
* Get the ultimate process result that will be returned by this "process".
*
Expand Down
71 changes: 71 additions & 0 deletions tests/Process/ProcessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,77 @@ public function testFakeInvokedProcessOutputWithLatestOutput()
$this->assertEquals("ONE\nTWO\nTHREE\n", $output[2]);
}

public function testFakeInvokedProcessWaitUntil()
{
$factory = new Factory;

$factory->fake(function () use ($factory) {
return $factory->describe()
->output('WAITING')
->output('READY')
->output('DONE')
->runsFor(iterations: 3);
});

$process = $factory->start('echo "WAITING"; sleep 1; echo "READY"; sleep 1; echo "DONE";');

$callbackInvoked = [];

$result = $process->waitUntil(function ($type, $buffer) use (&$callbackInvoked) {
$callbackInvoked[] = $buffer;
return str_contains($buffer, 'READY');
});

$this->assertInstanceOf(ProcessResult::class, $result);
$this->assertTrue($result->successful());
$this->assertContains("WAITING\n", $callbackInvoked);
$this->assertContains("READY\n", $callbackInvoked);
}

public function testFakeInvokedProcessWaitUntilWithNoCallback()
{
$factory = new Factory;

$factory->fake(function () use ($factory) {
return $factory->describe()
->output('OUTPUT');
});

$process = $factory->start('echo "OUTPUT"');

$result = $process->waitUntil();

$this->assertInstanceOf(ProcessResult::class, $result);
$this->assertTrue($result->successful());
$this->assertEquals("OUTPUT\n", $result->output());
}

public function testFakeInvokedProcessWaitUntilStopsWhenConditionMet()
{
$factory = new Factory;

$factory->fake(function () use ($factory) {
return $factory->describe()
->output('STEP1')
->output('TARGET')
->output('STEP3')
->runsFor(iterations: 3);
});

$process = $factory->start('echo "STEP1"; sleep 1; echo "TARGET"; sleep 1; echo "STEP3";');

$callbackCount = 0;

$result = $process->waitUntil(function ($type, $buffer) use (&$callbackCount) {
$callbackCount++;
return str_contains($buffer, 'TARGET');
});

$this->assertInstanceOf(ProcessResult::class, $result);
$this->assertTrue($result->successful());
$this->assertEquals(2, $callbackCount);
}

public function testBasicFakeAssertions()
{
$factory = new Factory;
Expand Down