From 15d473bdfe088ae1531bdd8b36385423244e01b4 Mon Sep 17 00:00:00 2001 From: GoodM4ven Date: Thu, 7 Mar 2024 20:46:17 +0300 Subject: [PATCH] [Feature] Automatic validation option upon toggling multi-select prompts - Added an argument and a property "validateOnToggle" to MultiSelectPrompt that defaults to false - If set to true, `validated` property gets set to true upon `toggleHighlight`; which triggers validation - Wrote a test for it - Ensured everything passes I found this to be valuable and essential for the next PR, which is about introducing re-evaluated and cached options closure... Basically, what I was a bit confused aboutu in #116 . If you like it, should I do the docs? --- src/MultiSelectPrompt.php | 5 +++++ src/helpers.php | 2 +- tests/Feature/MultiSelectPromptTest.php | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/MultiSelectPrompt.php b/src/MultiSelectPrompt.php index b2f0c704..ed1ad685 100644 --- a/src/MultiSelectPrompt.php +++ b/src/MultiSelectPrompt.php @@ -42,6 +42,7 @@ public function __construct( public int $scroll = 5, public bool|string $required = false, public mixed $validate = null, + public bool $validateOnToggle = false, public string $hint = '', ) { $this->options = $options instanceof Collection ? $options->all() : $options; @@ -129,5 +130,9 @@ protected function toggleHighlighted(): void } else { $this->values[] = $value; } + + if ($this->validateOnToggle) { + $this->validated = true; + } } } diff --git a/src/helpers.php b/src/helpers.php index 8c05b784..97dfdb4e 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -39,7 +39,7 @@ function select(string $label, array|Collection $options, int|string|null $defau * @param array|Collection $default * @return array */ -function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.'): array +function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, bool $validateOnToggle = false, string $hint = 'Use the space bar to select options.'): array { return (new MultiSelectPrompt(...func_get_args()))->prompt(); } diff --git a/tests/Feature/MultiSelectPromptTest.php b/tests/Feature/MultiSelectPromptTest.php index 53b9cbc8..37d0a5aa 100644 --- a/tests/Feature/MultiSelectPromptTest.php +++ b/tests/Feature/MultiSelectPromptTest.php @@ -122,6 +122,25 @@ Prompt::assertOutputContains('You must select at least one color.'); }); +it('can validate automatically upon toggling options', function () { + Prompt::fake([Key::DOWN, Key::SPACE, Key::SPACE, Key::UP, Key::SPACE, Key::ENTER]); + + $result = multiselect( + label: 'What was the reason for the guard\'s retirement?', + options: [ + 'arrow' => 'He took an arrow in the knee', + 'swordless' => 'He lost his sword', + 'dragone' => 'He defeated all dragons', + ], + validate: fn ($values) => in_array('arrow', $values) ? null : 'Missing a joke!', + validateOnToggle: true, + ); + + expect($result)->toBe(['arrow']); + + Prompt::assertOutputContains('Missing a joke!'); +}); + it('can fall back', function () { Prompt::fallbackWhen(true);