diff --git a/src/Exceptions/TotalStepsNotSetException.php b/src/Exceptions/TotalStepsNotSetException.php new file mode 100644 index 0000000..eb775dd --- /dev/null +++ b/src/Exceptions/TotalStepsNotSetException.php @@ -0,0 +1,16 @@ +metadata; } + if ($this->totalSteps !== null) { + $localData['current_step'] = $this->currentStep; + $localData['total_steps'] = $this->totalSteps; + } + $progressData[$this->getLocalKey()] = $localData; return $this->saveOverallProgressData($progressData); @@ -518,4 +534,48 @@ public function onComplete(callable $callback): static { return $this; } + + /** + * Set the total number of steps for the progress. + * + * @param int $steps The total number of steps + */ + public function setTotalSteps(int $steps): static { + $this->totalSteps = $steps; + $this->currentStep = 0; + + return $this; + } + + /** + * Advance the progress by a given number of steps. + * + * @param int $step The number of steps to advance + * + * @throws TotalStepsNotSetException + */ + public function advance(int $step = 1): static { + if ($this->totalSteps === null) { + throw new TotalStepsNotSetException; + } + + $this->currentStep += $step; + $progress = ($this->currentStep / $this->totalSteps) * 100; + + return $this->setLocalProgress($progress); + } + + /** + * Get the total number of steps. + */ + public function getTotalSteps(): ?int { + return $this->totalSteps; + } + + /** + * Get the current step. + */ + public function getCurrentStep(): int { + return $this->currentStep; + } } diff --git a/tests/ProgressableTest.php b/tests/ProgressableTest.php index 40f5003..ce8e470 100644 --- a/tests/ProgressableTest.php +++ b/tests/ProgressableTest.php @@ -3,6 +3,7 @@ namespace Verseles\Progressable\Tests; use Orchestra\Testbench\TestCase; +use Verseles\Progressable\Exceptions\TotalStepsNotSetException; use Verseles\Progressable\Exceptions\UniqueNameAlreadySetException; use Verseles\Progressable\Exceptions\UniqueNameNotSetException; use Verseles\Progressable\Progressable; @@ -485,4 +486,44 @@ public function test_merge_metadata(): void { $this->assertEquals('new_value1', $storedMetadata['key1']); $this->assertEquals('value2', $storedMetadata['key2']); } + + public function test_set_total_steps(): void { + $this->setTotalSteps(10); + $this->assertEquals(10, $this->getTotalSteps()); + $this->assertEquals(0, $this->getCurrentStep()); + } + + public function test_advance(): void { + $this->setOverallUniqueName('test_advance_'.$this->testId); + $this->setTotalSteps(10); + + $this->advance(); + $this->assertEquals(1, $this->getCurrentStep()); + $this->assertEquals(10, $this->getLocalProgress()); + + $this->advance(2); + $this->assertEquals(3, $this->getCurrentStep()); + $this->assertEquals(30, $this->getLocalProgress()); + } + + public function test_advance_without_total_steps_throws_exception(): void { + $this->setOverallUniqueName('test_advance_exception_'.$this->testId); + $this->expectException(TotalStepsNotSetException::class); + $this->advance(); + } + + public function test_step_info_in_progress_data(): void { + $this->setOverallUniqueName('test_step_info_'.$this->testId); + $this->setTotalSteps(5); + $this->advance(1); + + $progressData = $this->getOverallProgressData(); + $localData = $progressData[$this->getLocalKey()]; + + $this->assertArrayHasKey('current_step', $localData); + $this->assertArrayHasKey('total_steps', $localData); + $this->assertEquals(1, $localData['current_step']); + $this->assertEquals(5, $localData['total_steps']); + $this->assertEquals(20, $localData['progress']); + } }