From 00a8d68e573b941961c5fd966b848860097385ea Mon Sep 17 00:00:00 2001 From: Oleg Makedonsky Date: Thu, 26 Sep 2024 15:24:05 +0200 Subject: [PATCH] add skip step functionality --- src/Livewire/Forms/StepForm.php | 17 +++++++ src/Livewire/WizardComponent.php | 14 +++--- tests/TestSupport/Steps/SkipStepForm.php | 18 ++++++++ tests/WizardTest.php | 56 ++++++++++++++++++++++-- 4 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 tests/TestSupport/Steps/SkipStepForm.php diff --git a/src/Livewire/Forms/StepForm.php b/src/Livewire/Forms/StepForm.php index 34a6855..99a2be1 100644 --- a/src/Livewire/Forms/StepForm.php +++ b/src/Livewire/Forms/StepForm.php @@ -2,11 +2,14 @@ namespace Satoved\LivewireSteps\Livewire\Forms; +use Closure; use Livewire\Form; use Satoved\LivewireSteps\Livewire\WizardComponent; abstract class StepForm extends Form { + protected ?Closure $skipCondition = null; + abstract public function render(); public static function id(): string @@ -47,6 +50,20 @@ public function isFirst(): bool return $this->index() === 0; } + public function shouldBeSkipped(): bool + { + if ($this->skipCondition !== null) { + return ($this->skipCondition)(); + } + + return false; + } + + public function skipIf(Closure $skipCondition): void + { + $this->skipCondition = $skipCondition; + } + public function isLast(): bool { return $this->index() === ($this->getComponent()->totalSteps() - 1); diff --git a/src/Livewire/WizardComponent.php b/src/Livewire/WizardComponent.php index 10723e1..405ac83 100644 --- a/src/Livewire/WizardComponent.php +++ b/src/Livewire/WizardComponent.php @@ -41,16 +41,20 @@ protected function currentStep(): StepForm */ public function nextStep(): void { - if ($this->currentStepIndex === $this->totalSteps() - 1) { - throw NoNextStep::make(self::class, get_class($this->currentStep())); - } + do { + if ($this->currentStepIndex === $this->totalSteps() - 1) { + throw NoNextStep::make(self::class, get_class($this->currentStep())); + } - $this->currentStepIndex++; + $this->currentStepIndex++; + } while ($this->currentStep()->shouldBeSkipped()); } public function previousStep(): void { - $this->currentStepIndex = max(0, $this->currentStepIndex - 1); + do { + $this->currentStepIndex = max(0, $this->currentStepIndex - 1); + } while ($this->currentStepIndex !== 0 && $this->currentStep()->shouldBeSkipped()); } protected function isFirstStep(): bool diff --git a/tests/TestSupport/Steps/SkipStepForm.php b/tests/TestSupport/Steps/SkipStepForm.php new file mode 100644 index 0000000..a6bd2cf --- /dev/null +++ b/tests/TestSupport/Steps/SkipStepForm.php @@ -0,0 +1,18 @@ +assertSee('__SECOND_STEP_BODY__'); }); -it('can render the next and previous step', function () { +it('can go to the next and previous steps', function () { Livewire::test(MyWizardComponent::class) ->assertSee('__FIRST_STEP_BODY__') ->call('nextStep') @@ -31,6 +32,54 @@ ->assertSee('__FIRST_STEP_BODY__'); }); +it('can skip steps', function () { + $class = new class extends WizardComponent { + public FirstStepForm $firstStepForm; + public SkipStepForm $skipTestForm; + public SecondStepForm $secondStepForm; + + public function render() + { + return '
{{ $this->renderStep() }}
'; + } + }; + + Livewire::test($class) + ->assertSee('__FIRST_STEP_BODY__') + ->call('nextStep') + ->assertSee('__SECOND_STEP_BODY__') + ->call('previousStep') + ->assertSee('__FIRST_STEP_BODY__'); +}); + + +it('can skip steps via closure', function () { + $class = new class extends WizardComponent { + public FirstStepForm $firstStepForm; + public SomeIntricateNameStepForm $toSkipStepForm; + public SecondStepForm $secondStepForm; + + public function booted() + { + $this->toSkipStepForm->skipIf(function () { + return true; + }); + } + + public function render() + { + return '
{{ $this->renderStep() }}
'; + } + }; + + Livewire::test($class) + ->assertSee('__FIRST_STEP_BODY__') + ->call('nextStep') + ->assertSee('__SECOND_STEP_BODY__') + ->call('previousStep') + ->assertSee('__FIRST_STEP_BODY__'); +}); + it('throws an exception when going to the next step on the last step', function () { Livewire::test(MyWizardComponent::class, ['currentStepIndex' => 1]) ->call('nextStep'); @@ -66,8 +115,7 @@ }); it('has default labels for steps', function () { - $class = new class extends WizardComponent - { + $class = new class extends WizardComponent { public SomeIntricateNameStepForm $someIntricateNameStepForm; public function render() @@ -119,4 +167,4 @@ public function render() return true; }); -}); +}); \ No newline at end of file